UIKit:当子视图的宽度增加超过屏幕边缘时,UIScrollView 自动滚动

2024-01-06

在 iPhone 的背景下:

我有一个UIScrollView含有一个UIImage。当用户点击屏幕内的UIImage, a UITextField添加到用户触摸的位置。用户可以编辑此内容UITextField,并且文本字段将根据是否添加或删除文本自动调整自身大小。

当一个UITextField编辑时会增加其宽度,滚动视图会自动滚动以显示增加的宽度。

问题出现是因为文本字段的自动滚动不考虑屏幕的 y 值

例如,假设用户在图像底部添加了一个文本字段。当他们编辑该文本字段时,键盘将显示,隐藏文本字段。我有代码可以滚动屏幕以显示文本字段。当用户输入太多文本以致文本字段超出屏幕边缘时,问题就出现了。发生这种情况时,屏幕会水平滚动以适应更宽的文本,但也会垂直滚动 - 垂直滚动最终会隐藏文本字段,基本上使我为显示文本字段所做的任何操作都无效。

如果文本字段被键盘隐藏则显示该文本字段的代码:

- (void)keyboardWasShown:(NSNotification*)notification
{
    NSDictionary* info = [notification userInfo];
    CGSize keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    self.offset = self.contentOffset;

    CGRect frame = self.frame;
    // self.activeField is the name of the field that is the current first responder - this just adds a little bit of padding
    frame.size.height -= keyboardSize.height + (self.activeField.frame.size.height * 2);

    if (!CGRectContainsPoint(frame, self.activeField.frame.origin)) {
        CGPoint scrollPoint = CGPointMake(self.offset.x, self.activeField.frame.origin.y - keyboardSize.height + (activeField.frame.size.height * 2));
    [self setContentOffset:scrollPoint animated:YES];
    }
}

以下是增加文本字段大小的代码:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
    CGSize stringSize = [string sizeWithFont:textField.font];
    CGSize newSize = [newString sizeWithFont:textField.font];

    // Make textField wider if we're close to running up against it
    if (newSize.width > (textField.frame.size.width - self.widthOffset)) {
        CGRect textFieldFrame = textField.frame;
        if (stringSize.width > self.widthOffset) {
            textFieldFrame.size.width += stringSize.width;
        }
        textFieldFrame.size.width += self.widthOffset;
        textField.frame = textFieldFrame;
    }

    // Shrink the textField if there is too much wasted space
    if ((textField.frame.size.width - newSize.width) > self.widthOffset) {
        CGRect textFieldFrame = textField.frame;
        textFieldFrame.size.width = newSize.width + self.widthOffset;
        textField.frame = textFieldFrame;
    }
    return YES;
}

问题是:我如何获得UIScrollView自动滚动时尊重自身的 y 值?


基本上setFrame of UIScrollView将重新调整滚动视图offset,由_adjustContentOffsetIfNecessary。由于该方法是私有的并且没有记录,因此我们几乎无法猜测调整将如何发生。 有两种方法可以阻止不必要的滚动或错误的滚动offset正在设置:

1)重置UIScrollView offset申请后setFrame。如果您要修改框架,则可以这样做UIScrollView故意基于一些计算。

CGPoint oldOffset = [scrollView contentOffset];         
scrollView.frame = CGRectMake(newFrame);
[scrollView setContentOffset:oldOffset];        

2)申请offset没有动画的变化。在你的keyboardWasShown, 改变[self setContentOffset:scrollPoint animated:YES]; to
[self setContentOffset:scrollPoint animated:NO];

Reason:当超过一个时offset应用动画,结果offset是模棱两可的。这里是内部方法(_adjustContentOffsetIfNecessary)应用偏移量更改,另一个由您的代码完成。如果您尝试记录在中应用的所有偏移量,您会注意到这一点UIScrollView委托方法:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    NSLog(@" offset: %@", NSStringFromCGPoint(scrollView.conentOffset))
}

让我知道这是否有帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UIKit:当子视图的宽度增加超过屏幕边缘时,UIScrollView 自动滚动 的相关文章

随机推荐