使用 UIScrollView 和 UITextFields 作为子视图进行不需要的自动滚动
“太长;没有阅读”版本:当告诉 UITextField
<时,有什么方法可以禁用 UIScrollView
的自动滚动行为< code>becomeFirstResponder?
我有一个启用分页的滚动视图和多个作为子视图的视图,每个子视图都由其自己的视图控制器控制。每个子视图都有一个 UITextField。
要求是当页面滚动到视图中时,其文本字段应成为第一响应者。
当使用手指滑动滚动时,这很好——我使用滚动视图委托方法 scrollViewDidEndDecelerating:
来知道滚动何时停止并且页面处于视图中,我可以告诉文本字段成为第一响应者。
但是,当滚动视图“自动滚动”时,例如告诉滚动视图 scrollRectToVisible:animated:
时,不会调用用于减速的滚动视图委托方法。当在没有用户交互的情况下将新创建的页面滚动到视图中,或者当用户点击 UIPageControl
时,我会使用此方法。
我的解决方案是简单地设置文本字段的第一响应者状态,然后告诉它滚动到视图中 - 但似乎告诉滚动视图中的文本字段成为第一响应者会导致滚动视图自动将其滚动到视图中。
我假设这是将文本字段放入表视图单元格时使用的行为(因为表视图是滚动视图子类)。如果您设置一个小型测试应用程序,其中包含表视图和表单元格内的文本字段,如果键盘在表视图单元格成为第一响应者时遮盖表视图单元格,表视图将自动滚动它以使其可见。
但我不明白为什么在我的示例中会出现这种行为,我没有使用表视图 - 只是一个普通的滚动视图。
我还应该提到,我的滚动视图禁用了垂直滚动,只能水平滚动。
我在另一个测试应用程序中进行了测试,该应用程序将文本字段作为滚动视图的直接子视图(没有视图控制器或容器视图),并且发生了同样的情况。如果您告诉屏幕外的文本字段成为第一响应者,滚动视图会自动为您滚动它。
这通常不会成为问题,但它似乎搞乱了滚动视图的分页。当我用手指滚动时,每个视图都会弹起并正确居中。但是,当我滚动一个矩形以显示动画并告诉文本字段成为第一响应者时,滚动视图似乎与自身发生冲突,并且视图仅滚动到视图的一部分,并且不居中。
然后,如果我用手指触摸视图(不是滑动,甚至移动),滚动视图会跳回到第一页。
我当前针对所有这些愚蠢的自动滚动行为的解决方法是使用 NSTimer 来确定何时更新第一响应者。
我使用 scrollRectToVisible:animated
在代码中进行手动滚动,然后在 0.3 秒后调用我的方法将文本字段更新为第一响应者。 (0.3秒是反复试验,试图看看哪一个似乎是允许动画的最短时间,但仍然足够长,不会导致与滚动视图的冲突。
正如你所看到的,这并不优雅, 当告诉UITextField
becomeFirstResponder
时,
有什么方法可以禁用UIScrollView
的自动滚动行为吗?< /强>
The "too long; didn't read" version: Is there any way to disable the automatic scrolling behaviour of UIScrollView
when telling a UITextField
to becomeFirstResponder
?
I have a scroll view with paging enabled and several views as subviews, each subview being controlled by its own view controller. Each subview has a UITextField.
The requirement is that when a page is scrolled into view, it's text field should become first responder.
This is fine when using finger swipes to scroll -- I use the scroll view delegate method scrollViewDidEndDecelerating:
to know when scrolling stops and a page is in view, I can tell the text field to become first responder.
However, when the scroll view is "autoscrolled", as in when telling the scrollview to scrollRectToVisible:animated:
, the scroll view delegate method for deceleration isn't called. I use this method when scrolling newly created pages into view without the user's interation, or when the user taps the UIPageControl
.
My solution was to simply set the first responder status of the text field before telling it to scroll into view - but it seems that telling a text field that is in a scroll view to become first responder causes the scroll view to automatically scroll it into view.
I assume this is behaviour used when putting text fields in table view cells (since table views are scroll view subclasses). If you set up a small test app, with a table view, and a text field within a table cell, if the keyboard would obscure the table view cell when it becomes first responder, the table view will automatically scroll it to be visible.
I don't understand, though, why this behaviour occurs in my example, where I'm not using a table view - just a plain scroll view.
I should also mention that my scroll view has vertical scrolling disabled and only scrolls horizontally.
I have tested in another test app that puts text fields as direct subviews of a scrollview (no view controllers or container views) and the same happens. If you tell a text field that is offscreen to become first responder, the scroll view with automatically scroll it for you.
This wouldn't normally be a problem, but it seems to screw up the paging of the scroll view. When I scroll with my finger, each view bounces and is centred properly. But when I scroll a rect to be visible with animation and tell a text field to become first responder, scroll view seems to become conflicted with itself and the view is only scrolled part of the way into view, and isn't centred.
Then, if I touch a view using my finger (not swipe, or even move), the scroll view jumps back to the first page.
My current work around for all this silly auto scrolling behaviour is to use an NSTimer
to determine when to update the first responder.
I do the manual scrolling in code using scrollRectToVisible:animated
and then after 0.3 seconds, call my method to update the text field to be first responder. (0.3 seconds was trial and error, trying to see which seemed to be the smallest amount of time to allow for the animation but still be long enough not to cause the conflict with the scrollview.
As you can see, this isn't elegant, and is likely to break.
Is there any way to disable the automatic scrolling behaviour of UIScrollView
when telling a UITextField
to becomeFirstResponder
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
调用becomeFirstResponder,然后立即将scrollview的contentOffset设置为其当前位置。
Call becomeFirstResponder, then right away, set the contentOffset of the scrollview to its current position..
不是您问题的答案,但它应该可以解决问题:
Not an answer to your question, but it should fix the problem: