将UITextField
添加到UIScrollview
时,滚动视图会自动调整其contentOffset
,以便视图不会被键盘遮挡。
我有一个自定义UIControl
,当它通过分配其inputView
属性成为第一响应者时,它还会显示一个键盘。相同的滚动行为不起作用。有没有办法配置UIControl
,以便在显示键盘时滚动视图使其保持可见?
我的猜测是,可以通过覆盖协议之一中定义的属性来实现 UITextField
和此行为符合的其他类。但这些可能有点迷宫。另请注意,此处的问题与滚动视图的contentInset
属性无关。滚动视图可以滚动以显示自定义控件,只是当控件成为第一个响应者时,它不会自动执行此操作。
看起来这是由Apple使用的内部私有方法处理的,[UIFieldEditor scrollSelectionToVisible]
如本博客中所述:http://sugarrushva.my03.com/712423-disable-uiscrollview-scrolling-when-uitextfield-becomes-first-responder.html
似乎通过向上跨入视图层次结构来做到这一点,如果它找到父UIScrollView
,它会滚动视图以使UITextField
进入可见视图。当自定义控件成为第一响应者时,您需要在自定义控件上手动实现滚动,或者通过自省父视图来处理它。
@markflowers指出了正确的方向。
基于此,以下是我编写到控件中以获取所需行为的内容:
- (BOOL)becomeFirstResponder {
if ([super becomeFirstResponder]) {
[self scrollParentViewToFrame];
return YES;
}
return NO;
}
- (void)scrollParentViewToFrame {
UIScrollView *scrollView = self.parentScrollView;
CGRect frame = [scrollView convertRect:self.bounds fromView:self];
[self.parentScrollView scrollRectToVisible:frame animated:YES];
}
- (UIScrollView *)parentScrollView {
return (UIScrollView *) [self closestParentWithClass:[UIScrollView class]];
}
请注意,如果控件不是滚动视图的直接后代,则不使用 frame
属性。而是将边界转换为滚动视图的坐标空间。
还需要在调用 [super becomeFirstResponder]
后执行滚动调整,以便它与用于调整滚动视图内陷的键盘通知正确交互。
我定义了在UIView
类别中搜索最接近的父滚动视图的方法,这使得递归搜索层次结构变得更加容易。
- (UIView *)closestParentWithClass:(Class)class {
if ([self isKindOfClass:class]) {
return self;
}
// Recursively searches up the view hierarchy, returns nil if a view
// has no superview.
return [self.superview closestParentWithClass:class];
}