うん。私はあなたのために気の利いたトリックを持っています。
赤い輪郭を描いたビューをスクロールビューにする代わりに、画面いっぱいに表示する通常の UIView にします。そのビューで、スクロール ビュー (テーブル ビュー) とイメージ ビューを図のようにレイアウトします。
ルート ビューの境界を埋める (つまり、画面全体を埋める) スクロール ビューを、他のすべてのスクロール ビューおよびイメージ ビューの上に配置します。このビューのコンテンツ サイズを、スクロールするすべてのビューのコンテンツの高さの合計に設定します。つまり、他のすべてのビューの上に非表示のスクロールビューがあり、そのコンテンツ サイズの高さは、内側のスクロールビュー (テーブルビュー) コンテンツ サイズの高さ + 画像ビュー サイズの高さです。
階層は次のようになります。

次に、非常に背の高いコンテンツサイズで作成したこのスクロールビューの上に、デリゲートをビューコントローラーにします。実装scrollViewDidScroll
すると、いくつかの魔法がかかります。
Scrollviews は基本的に、境界の原点を運動量などのファンキーな式で調整することによってスクロールします。したがって、このscrollviewDidScroll
方法では、基になるビューの境界を調整するだけです。
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
//the scroll view underneath (in the container view) will have a max content offset equal to the content height
//but minus the bounds height
CGFloat maxYOffsetForUnderScrollView = self.underScrollView.contentSize.height - self.underScrollView.bounds.size.height;
CGRect scrolledBoundsForContainerView = self.view.bounds;
if (scrollView.contentOffset.y <= maxYOffsetForUnderScrollView) {
//in this scenario we are still within the content for the underScrollView
//so we make sure the container view is scrolled to the top and set the offset for the contained scrollview
self.containerView.bounds = scrolledBoundsForContainerView;
self.underScrollview.contentOffset = scrollView.contentOffset;
return;
}
//in this scenario we have scrolled throug the entirety of the contained scrollview
//set its offset to the max and change the bounds of the container view to scroll everything else.
self.underScrollView.contentOffset = CGPointMake(0, maxYOffsetForUnderScrollView);
scrolledBoundsForContainerView.origin.y = scrollView.contentOffset.y - maxYOffsetForUnderScrollView;
self.containerView.bounds = scrolledBoundsForContainerView;
}
scrollViewDidScroll はアニメーションのすべてのフレームで呼び出されるため、含まれているビューのこの誤ったスクロールが非常に自然に見えることがわかります。
ちょっと待って!私はあなたが言うのを聞きます。上部のスクロール ビューはすべてのタッチをインターセプトするようになり、その下のビューもタッチする必要があります。それについても興味深い解決策があります。
一番上のスクロールビューをどこか画面外に設定します(つまり、フレームを画面外に設定しますが、同じサイズです)。次に、メソッドでスクロールビューをメインビューにviewDidLoad
追加します。panGestureRecogniser
これは、実際に画面を表示しなくても、iOS の自然なスクロールの勢いなどをすべて取得できることを意味します。含まれているスクロール ビューは、パン ジェスチャ レコグナイザーも呼び出されるため (UIEvent 処理とは異なる動作をするため)、おそらくおかしなことになるので、それを削除する必要があります。
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.view addGestureRecognizer:self.scrollview.panGestureRecognizer];
[self.underScrollview removeGestureRecognizer:self.underScrollView.panGestureRecognizer];
//further code to set up content sizes and stuff
}
これを作るのは楽しかったので、github のサンプル プロジェクトへのリンクを以下に示します:
https://github.com/joelparsons/multipleScrollers
編集:
どこに配置しても画面外にあるときに上部のスクロールビューのスクロールバーを表示するには、次のscrollIndicatorInsets
ように作成されたインセットに設定できます。
CGPoint scrollviewOrigin = self.scrollview.frame.origin;
self.scrollview.scrollIndicatorInsets = UIEdgeInsetsMake(-scrollviewOrigin.y,0,scrollviewOrigin.y,scrollviewOrigin.x);
*スクロールビューは適切な高さでなければならないことに注意してください。
そして、バーをスクロールビューの可視境界の外側に描画するには、境界へのクリップをオフにする必要があります
self.scrollview.clipsToBounds = NO;