web-dev-qa-db-ja.com

iOS:ユーザーが下にドラッグしたときにUITableViewヘッダーを拡大/サイズ変更しますか?

ストーリーボードを使用して、imageViewheaderView内にtableView'sViewControllerとして配置しました。

これは私のストーリーボードの設定方法です:

enter image description here

ユーザーが表示しているデータに応じて、viewControllerheaderViewを表示または非表示にします。私の質問は、headerViewが表示されていて、ユーザーがtableViewを下にドラッグすると、imageViewを両方のnavigationBartableViewは、その間のスペースをカバーするようにサイズ変更されますか?

これが現在行っていることです:

enter image description here

しかし、これは私が目指していることです:

enter image description here

どんな助けでも大歓迎です。私は視差ライブラリを見てきましたが、sectionTitlesをサポートしているものはなく、必ずしも視差効果を使用する必要もありません。ユーザーが上にスクロールしたときに、headerViewを非表示にせずに、regularViewに跳ね返してほしい。ありがとう!

更新:

私は以下のダニーが投稿したアドバイスに従い、以下を行いました:

-(void)scrollViewDidScroll:(UIScrollView*)scrollView {

CGRect initialFrame = CGRectMake(0, 0, 320, 160);

if (scrollView.contentOffset.y < 0) {

    initialFrame.size.height =! scrollView.contentOffset.y;
    childHeaderView.frame = initialFrame;
} }

childHeaderViewはimageViewであり、何らかの理由で下にドラッグすると、画像が(navBarの後ろの半分のように)上に移動して戻りません。何かアドバイスをいただければ幸いです!!ありがとう!

29
KingPolygon

私は最近、制約を使用してこれを達成することについてブログ投稿を投稿しましたが、これは役立つ可能性があります。

これがリンクです: IScrollViewでの制約を使用した視差効果の作成

7
petehare

最初に、ヘッダーからUIImageViewを削除し、UIImageViewの上に単純なUITableViewとして追加する必要があります。その後、UITableViewDelegateプロトコルはUIScrollViewDelegateプロトコルに準拠しているため、scrollViewDidScroll:メソッドは、tableViewが下にスクロールしており、bouncingの効果があるかどうかを確認します。このようなもの:

-(void)someInitMethod {
   initialFrame = yourHeaderView.frame;
}
-(void)scrollViewDidScroll:(UIScrollView*)scrollView {
    if(scrollView.contentOffset.y < 0) {
       initialFrame.size.height -= scrollView.contentOffset.y;
       yourHeaderView.frame = initialFrame;
    }
}

また、contentModeに適切なUIImageViewを設定してください。また、この実装はバウンス効果を生み出すと思いますが、今はテストできないのでわかりませんが、これはあなたにとって良い出発点だと思います。

5
danypata

これは私がそれを達成した方法です、私の場合、私は上部のマップビューを使用していました:

  1. ストーリーボードにビューコントローラを作成します。
  2. テーブルビューを追加し、すべての側から制約を0に設定します。
  3. テーブルビューの下にマップビュー(または任意のビュー)を追加して、上部にレンダリングされるようにします。重なっているように見えます。
  4. 左上と右上に制約を追加します。
  5. ビューコントローラーviewDidLoadに以下を追加します:tableView.contentInset = UIEdgeInsetsMake(200, 0, 0, 0) where 200はビューの高さです。これにより、テーブルビューのコンテンツが下にプッシュされます。
  6. ビューコントローラーで、スクロールに基づいてビューのサイズを変更する次のコードを追加します。

    func scrollViewDidScroll(scrollView: UIScrollView) {
        var scrollOffset = scrollView.contentOffset.y
        var headerFrame = mapView.frame
        if (scrollOffset < 0) {
            // Adjust map
            headerFrame = CGRect(x: mapView.frame.Origin.x,
                y: mapView.frame.Origin.y,
                width: mapView.frame.size.width,
                height: -scrollOffset)
        } else {
            // Adjust map
            headerFrame = CGRect(x: mapView.frame.Origin.x,
                y: mapView.frame.Origin.y,
                width: mapView.frame.size.width,
                height: 0)
        }
        mapView.frame = headerFrame
    }
    

ストーリーボードからcontentInsetを設定できれば、さらにきれいになります

2
geometrikal

このページの以前の解決策では、これをセクションタイトルやインデックスバーと一緒に使用する必要があるときに問題が発生したため、次の代替案を自分で考えました。ご注意ください;私のプロジェクトではautolayoutを使用せず、iOS9以降でのみテストしました。

プロジェクトのストーリーボード:

  1. UIViewController内にUITableViewを作成します(またはUITableViewControllerで試してください)。
  2. UIViewをUITableViewの上部(ただし内部)にドロップすると、最初のセルの上のテーブルヘッダーになります。
  3. このヘッダービューに希望の高さ(たとえば200pxなど)を設定し、背景色を「クリアカラー」に設定します。クリアカラーは重要です。ビューはシースルーである必要があります。
  4. 2番目のUIViewをテーブルヘッダーUIView内にドロップし、親と同じサイズにします。これが実際のヘッダーになるので、自由に色を付けたり、画像ビューやその他のコンテンツを設定したりしてください。
  5. この2番目のUIViewをUIViewController IBOutletに接続します。私の場合は「headerView」と名付けました。

次に、UIViewController.m:に移動します

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Remove view from table header and place it in the background instead.
    [self.headerView removeFromSuperview];
    UIView *backgroundView = [UIView new];
    [backgroundView addSubview:self.headerView];
    self.tableView.backgroundView = backgroundView;
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    /* Set initialScrollOffset ivar to start offset, because in my case
       the scroll offset was affected by the statusbar + navigation bar heights
       and the view controller's "extend edges under top bars" option. */
    initialScrollOffset = self.tableView.contentOffset.y;
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    /* Modify headerView height only if the table content gets pulled
       beyond initial offset. */
    if (scrollView.contentOffset.y < initialScrollOffset) {
        CGRect frame = self.headerView.frame;
        frame.size.height = self.tableView.tableHeaderView.frame.size.height + -scrollView.contentOffset.y;
        self.headerView.frame = frame;
    }
}

この実装が必要だったのは、背景色とラベルが付いたストレッチヘッダーだけです。ただし、このヘッダーにUIImageViewを追加するのは簡単です。

また、手順1〜5は完全にオプションです。プログラムでヘッダービューを作成するか、代わりにXIBを使用できます。セルとセクションのタイトルを揃えるためのスペーサーとして機能するため、目的のヘッダーと同じ高さのクリアカラーのヘッダービューがテーブルに設定されていることを確認する限り。

編集:

私はこれを達成するためのもっとすっきりした方法を見つけました。

  1. 上記のように、インターフェイスビルダーでテーブルヘッダーを作成します。1つのUIViewを2番目のUIViewが埋め込まれたコンテナとして使用します。
  2. 上記のviewDidLoadコードをスキップしてください。UIViewをコンテナーから取り出す必要はなく、テーブルの背景として設定する必要もありません。
  3. 変更 scrollViewDidScroll:これにメソッド:

IViewController.m:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
      if (scrollView.contentOffset.y < initialScrollOffset) {
           CGRect frame = self.headerView.frame;
           frame.size.height = self.tableView.tableHeaderView.frame.size.height - scrollView.contentOffset.y;
           frame.Origin.y = self.tableView.tableHeaderView.frame.Origin.y + scrollView.contentOffset.y;
           self.headerView.frame = frame;
    }
}

それでおしまい。他のソリューションとの視覚的な違いは、コンテンツが他のセルと重なるのではなく、残りのセルとともに上にスクロールすることです。

1
Tonnie

これを見てください https://github.com/matteogobbi/MGSpotyViewController これは、要件ごとに同じ効果を実装します。

1
Prabhu

これがあなたに役立つかどうかはわかりません。

自分のスクロールデリゲートを設定します。

そしてこれを実装します:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    float scrollViewHeight = scrollView.frame.size.height;
    float scrollContentSizeHeight = scrollView.contentSize.height;
    float scrollOffset = scrollView.contentOffset.y;

    if (scrollOffset == 0)
    {
        // then we are at the top
    }
    else if (scrollOffset + scrollViewHeight == scrollContentSizeHeight)
    {
        // then we are at the end
        // Do what you need here 
    }
}
0
Islam Adel