问题描述
这个问题是 快速滚动后,粘性滚动视图子视图的帧不正确.可编译示例.如果您想下载示例项目,请访问该链接.
This question is a spin-off of Sticky scrollview subview has incorrect frame after scrolling fast. Compilable example. If you would like to download the sample project, visit that link.
场景:(虽然这会有所不同)
The scenario: (though this will vary)
ViewController
. View
. . MainScrollview
. . . ImageScroller
. . . . ImageView(s)
. . . TextView (Inside container view)
主滚动视图是屏幕的大小.屏幕的上半部分是 UIImageViews 的水平滚动滚动视图.
The main scrollview is the size of the screen. The top ~half of the screen is a horizontally scrolling scrollview of UIImageViews.
目标:向上滚动(通过向下拖动)超过正常偏移量将拉伸 imageScroller 中的可见图像(这在示例中已完成).向下滚动(通过向上拖动)超过 0 偏移量将使 textView 滚动到 imagesScroller 上方,使 imagesScroller 看起来是静态的.
The goal:Scrolling up (by dragging down) past the normal offset will stretch the visible image in the imageScroller (This is completed in the example). Scrolling down (by dragging up) past 0 offset will have the textView scroll above the imagesScroller, making the imagesScroller appear to be static.
我的实现将起作用(使用链接问题中给出的答案),但显然不是最佳的.我试图重新排列 mainScrollview 后面的 imageScroller,所以它实际上是静态的,但这需要在 mainScroller 上制作一个透明视图,其大小为 imageScroller,它将把触摸事件传递给 imageScroller.对我来说,这并不比在上述方案中不断为 imageScroller 计算适当的 Y 偏移更干净.
My implementation will work (with the answer given in the linked question) but it is clearly not optimal. I've tried to rearrange the imageScroller behind the mainScrollview so it actually is static, but that requires making a transparent view on the mainScroller the size of the imageScroller that will pass down touch events to the imageScroller. To me, that's no cleaner than constantly calculating the proper Y-offset for the imageScroller in the scheme described above.
推荐答案
我建议你应该通过稍微改变一下来做到这一点.
I suggest you should do this by changing things around a little.
1 - 重新排列视图层次结构
self.view ---+
|
+---> self.mainScrollView
|
+---> self.imageScrollView
以你的话来说...
ViewController
. View
. . MainScrollview
. . . TextView (Inside container view)
. . ImageScroller
. . . ImageView(s)
您的 imageScrollView 是 mainScrollView 的兄弟,而不是孩子.
Your imageScrollView is a sibling of mainScrollView, not a child.
self.mainScrollView
是最上面的视图,完全覆盖了 imageScrollView
.在这两种情况下,它们的框架都是 self.view.bounds
.mainScrollView
应该有一个透明的背景([UIColor clearColor]
),这样你就可以看到它后面的 imageScrollView.mainScrollView 的 textView 将其原点设置为 self.view.bounds.size.height
以便您在开始向下滚动之前看不到它.
self.mainScrollView
is the uppermost view and completely covers imageScrollView
. In both cases their frame is self.view.bounds
. mainScrollView
should have a transparent background ([UIColor clearColor]
) so that you can see the imageScrollView behind it. The mainScrollView's textView has it's origin set to self.view.bounds.size.height
so that you don't see it until you start scrolling down.
2 - 管理您的手势
由于 mainScrollView 是最上面的,它的 PanGestureRecognizer 将捕获您的所有触摸,并且不会将任何内容转发到 imageScrollView.您需要修复此问题,以便您可以滚动图像.
As mainScrollView is uppermost, it's PanGestureRecognizer will capture all of your touches, and nothing will get forwarded to imageScrollView. You need to fix this so that you can scroll the images.
要管理手势协商,您可以将这两个手势附加到一个视图中.最简单的实现是将 imageScrollView 的 panGestureRecognizer 附加到 mainScrollView:
To manage gesture negotiation, you can attach both of these gestures onto a single view. The simplest implentation is to attach the imageScrollView's panGestureRecognizer to the mainScrollView:
UIGestureRecognizer* panGR = self.imageScroller.panGestureRecognizer;
[self.mainScrollView addGestureRecognizer:panGR];
imageScrollview.panGestureRecognizer
现在将识别 mainScrollView 上的手势,并将继续将结果消息传递给它的 imageScrollView.
imageScrollview.panGestureRecognizer
will now recognise gestures on mainScrollView, and will continue to pass resulting messages through to it's imageScrollView.
这可能就是您需要做的全部.在我的测试实现中,只要至少 mainViewController 的 canCancelContentTouches
或 delaysContentTouches
之一设置为 YES,这就足够了.
This may be all you need to do. In my test implementation this is sufficient, so long as at least one of mainViewController's canCancelContentTouches
or delaysContentTouches
is set to YES.
要获得更细粒度的控制,您可以在两个 scrollView 上叠加一个透明的手势视图,并将两个 scrollView 的 panGestureRecognizers 附加到手势视图.请注意这一点 - 您附加手势识别器的顺序将反映在拦截手势的顺序中.
For more fine-grained control you could make a transparent gesture view overlay on both scrollViews, and attach both scrollView's panGestureRecognizers to the gesture view. Take care with this - the order in which you attach the gestureRecognizers will be reflected in the order in which gestures are intercepted.
有关劫持 scrollview 的 panGestureRecognizer 的更多详细信息,非常值得观看 WWDC 2012 的Enhancing User Experience with Scroll Views",尤其是后半部分,其中使用 scrollView 控制同级 openGL 视图.
For more detail on hijacking scrollview's panGestureRecognizer, it's well worth watching "Enhancing User Experience with Scroll Views" from WWDC 2012, especially the second half, where a scrollView is used to control a sibling openGL view.
关于在向下拖动时拉伸图像,这可以通过 mainScrollView 上的 scrollViewDidScroll
委托方法有效地完成 - 当 contentOffset.y 为负时,在 imageView 上应用变换.
As regards stretching the image when dragging down, this might be done effectively via the scrollViewDidScroll
delegate method on mainScrollView - apply a transform on the imageView while contentOffset.y is negative.
这篇关于使用具有滚动放大效果的粘性(水平滚动)标题实现滚动视图的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!