使用自定义 UIControl 自动调整 UIScrollView 内容偏移

Posted

技术标签:

【中文标题】使用自定义 UIControl 自动调整 UIScrollView 内容偏移【英文标题】:Automatic adjustment of UIScrollView content offset with custom UIControl 【发布时间】:2014-11-24 16:28:53 【问题描述】:

UITextField 被添加到UIScrollview 时,滚动视图会自动调整其contentOffset,这样视图就不会被键盘遮挡。

我有一个自定义的UIControl,当它通过分配其inputView 属性成为第一响应者时,它也会显示一个键盘。相同的滚动行为不起作用。有没有办法配置 UIControl 以便在显示键盘时滚动视图保持可见?

我的猜测是,可以通过覆盖协议之一中定义的属性 UITextField 和此行为符合的其他类。但这些可能有点像迷宫。另请注意,这里的问题与滚动视图的contentInset 属性无关。滚动视图可以滚动以显示自定义控件,只是当控件成为第一响应者时它不会自动执行此操作。

【问题讨论】:

【参考方案1】:

看起来这是由 Apple 使用 [UIFieldEditor scrollSelectionToVisible] 的内部私有方法处理的,如本博客所述:http://sugarrushva.my03.com/712423-disable-uiscrollview-scrolling-when-uitextfield-becomes-first-responder.html

它似乎是通过逐步返回视图层次结构来做到这一点的,如果它找到父UIScrollView,它会滚动视图以将UITextField 带入可见视图。当您的自定义控件成为第一响应者时,您需要手动实现滚动,或者通过自省父视图来处理它。

【讨论】:

完美。提升视图层次结构对我来说似乎有点不舒服,但如果它有效,并且如果 API 没有提供预期的方法,它对我有用。我会用特定的 sn-ps 添加一个答案。【参考方案2】:

@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];

【讨论】:

以上是关于使用自定义 UIControl 自动调整 UIScrollView 内容偏移的主要内容,如果未能解决你的问题,请参考以下文章

突出显示 UIControl 子类

子类 UIControl 来制作自定义选择器

如何:在iOS中使用StackView View从XIB自我调整自定义视图

自定义 UIControl(滑块)在与交互之前不遵守约束

如何为自定义 UIControl 添加触摸事件并在 swift 5 中确定触摸的项目

在自定义 UIControl 对象中定义自定义触摸区域