ios 当 UITextField 成为第一响应者时如何使 UIScrollView 自动滚动

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13056004/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 20:56:24  来源:igfitidea点击:

How to make a UIScrollView auto scroll when a UITextField becomes a first responder

iphoneobjective-ciosuiscrollviewuitextfield

提问by Nosrettap

I've seen posts around herethat suggest that UIScrollViewsshould automatically scroll if a subview UITextFieldbecomes the first responder; however, I can't figure out how to get this to work.

我在这里看到的帖子表明,UIScrollViews如果子视图UITextField成为第一响应者,应该自动滚动;但是,我不知道如何让它发挥作用。

What I have is a UIViewControllerthat has a UIScrollViewand within the UIScrollViewthere are multiple textfields.

我已经是一个UIViewController具有UIScrollView与内UIScrollView有多个文本框。

I know how to do this manually if necessary; however, from what I've been reading, it seems possible to have it autoscroll. Help please.

如有必要,我知道如何手动执行此操作;但是,从我一直在阅读的内容来看,似乎可以让它自动滚动。请帮忙。

回答by Adeel Pervaiz

I hope this example will help you You can scroll to any point by this code.

我希望这个例子能帮助你你可以通过这段代码滚动到任何一点。

scrollView.contentOffset = CGPointMake(0,0);

So if you have textfield, it must have some x,y position on view, so you can use

所以如果你有文本框,它必须有一些 x,y 位置在视图中,所以你可以使用

CGPoint point = textfield.frame.origin ;
scrollView.contentOffset = point 

This should do the trick,

这应该可以解决问题,

But if you don't know when to call this code, so you should learn UITextFieldDelegatemethods

但是如果你不知道什么时候调用这段代码,那么你应该学习UITextFieldDelegate方法

Implement this method in your code

在您的代码中实现此方法

- (void)textFieldDidBeginEditing:(UITextField *)textField {
// Place Scroll Code here
}

I hope you know how to use delegate methods.

我希望你知道如何使用委托方法。

回答by Supertecnoboff

I know this question has already been answered, but I thought I would share the code combination that I used from @Adeel and @Basil answer, as it seems to work perfectly for me on iOS 9.

我知道这个问题已经得到了回答,但我想我会分享我从 @Adeel 和 @Basil 答案中使用的代码组合,因为它在 iOS 9 上似乎对我来说非常适合。

-(void)textFieldDidBeginEditing:(UITextField *)textField {

    // Scroll to the text field so that it is
    // not hidden by the keyboard during editing.
    [scroll setContentOffset:CGPointMake(0, (textField.superview.frame.origin.y + (textField.frame.origin.y))) animated:YES];
}

-(void)textFieldDidEndEditing:(UITextField *)textField {

    // Remove any content offset from the scroll
    // view otherwise the scroll view will look odd.
    [scroll setContentOffset:CGPointMake(0, 0) animated:YES];
}

I also used the animated method, it makes for a much smoother transition.

我还使用了动画方法,它可以实现更平滑的过渡。

回答by donmiller

Here is the Swift 4 update to @Supertecnoboff's answer. It worked great for me.

这是@Supertecnoboff 答案的 Swift 4 更新。它对我很有用。

func textFieldDidBeginEditing(_ textField: UITextField) {
    scroll.setContentOffset(CGPoint(x: 0, y: (textField.superview?.frame.origin.y)!), animated: true)
}

func textFieldDidEndEditing(_ textField: UITextField) {
    scroll.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
}

Make sure to extend UITextFieldDelegate and set the textfields' delegate to self.

确保扩展 UITextFieldDelegate 并将文本字段的委托设置为 self。

回答by Michael McGuire

There is nothing you have to do manually. It is the default behavior. There are two possibilities as to why you are not seeing the behavior

您无需手动执行任何操作。这是默认行为。关于为什么您没有看到该行为的原因有两种可能

  1. The most likely reason is that the keyboard is covering your UITextField. See below for solution
  2. The other possibility is that you have another UIScrollViewsomewhere in the view hierarchy between the UITextFieldand the UIScrollViewthat you want to auto scroll. This is less likely but can still cause problems.
  1. 最可能的原因是键盘覆盖了您的UITextField. 解决办法见下文
  2. 另一种可能性是,你有其他UIScrollView的之间的视图层次的地方UITextFieldUIScrollView要自动滚动。这不太可能,但仍然会导致问题。

For #1, you want to implement something similar to Apple's recommendations for Moving Content That Is Located Under the Keyboard. Note that the code provided by Apple does not account for rotation. For improvements on their code, check out this blog post'simplementation of the keyboardDidShowmethod that properly translates the keyboard's frame using the window.

对于 #1,您想要实现类似于 Apple 的关于移动位于键盘下的内容的建议的内容。请注意,Apple 提供的代码不考虑轮换。要改进他们的代码,请查看此博客文章的实现keyboardDidShow方法,该方法使用窗口正确转换键盘框架。

回答by George

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    CGRect rect = [textField bounds];
    rect = [textField convertRect:rect toView:self.scrollView];
    rect.origin.x = 0 ;
    rect.origin.y -= 60 ;
    rect.size.height = 400;

    [self.scrollView scrollRectToVisible:rect animated:YES];
}

回答by Basil Mariano

You can use this function for autoScroll of UITextField

您可以将此功能用于 UITextField 的 autoScroll

on UITextFieldDelegate

UITextFieldDelegate

- (void)textFieldDidBeginEditing:(UITextField *)textField {

[self autoScrolTextField:textField onScrollView:self.scrollView];
}




- (void) autoScrolTextField: (UITextField *) textField onScrollView: (UIScrollView *) scrollView { 
 float slidePoint = 0.0f;
float keyBoard_Y_Origin = self.view.bounds.size.height - 216.0f;
float textFieldButtomPoint = textField.superview.frame.origin.y + (textField.frame.origin.y + textField.frame.size.height);

if (keyBoard_Y_Origin < textFieldButtomPoint - scrollView.contentOffset.y) {
    slidePoint = textFieldButtomPoint - keyBoard_Y_Origin + 10.0f;
    CGPoint point = CGPointMake(0.0f, slidePoint);
    scrollView.contentOffset = point;
}

EDIT:

编辑:

Im now using IQKeyboardManagerKudos to the developer of this, you need to try this.

我现在使用IQKeyboardManagerKudos 向这个开发者致敬,你需要试试这个。

回答by Deep Batra

If you have multiple textfields say Textfield1, Textfield2, Textfield3and you want to scroll the scrollview along the y-axis when textfield2 becomes first responder:

如果您有多个 textfields 说Textfield1, Textfield2Textfield3并且您想在 textfield2 成为第一响应者时沿 y 轴滚动滚动视图:

if([Textfield2 isFirstResponder])
{
    scrollView.contentOffset = CGPointMake(0,yourY);
} 

回答by jsbox

As Michael McGuire mentioned in his point #2 above, the system's default behavior misbehaves when the scroll view contains another scroll view between the text field and the scroll view. I've found that the misbehavior also occurs when there's a scroll view merely nextto the text field (both embedded in the scroll view that needs to be adjusted to bring the text field into view when the text field wants to start editing. This is on iOS 12.1.

正如 Michael McGuire 在上面的第 2 点中提到的那样,当滚动视图在文本字段和滚动视图之间包含另一个滚动视图时,系统的默认行为会出现错误。我发现当仅在文本字段旁边有滚动视图时也会发生不当行为(两者都嵌入在滚动视图中,当文本字段想要开始编辑时,需要进行调整以将文本字段带入视图中。这是在 iOS 12.1 上。

But my solution is different from the above. In my top-level scroll view, which is sub-classed so I can add properties and override methods, I override scrollRectToVisible:animated:. It simply calls its [super scrollRectToVisible:animated:]unless there's a property set that tells it to adjust the rectpassed in, which is the frame of the text field. When the property is non-nil, it is a reference to the UITextFieldin question, and the rectis adjusted so that the scroll view goes further than the system thought it would. So I put this in the UIScrollView's sub-classed header file:

但我的解决方案与上述不同。在我的顶级滚动视图中,它是子类以便我可以添加属性和覆盖方法,我覆盖scrollRectToVisible:animated:. 它只是调用它,[super scrollRectToVisible:animated:]除非有一个属性集告诉它调整rect传入的,这是文本字段的框架。当该属性为非 nil 时,它是对有UITextField问题的引用,并且rect会进行调整,以便滚动视图比系统预期的更远。所以我把它放在UIScrollView子类的头文件中:

@property (nullable) UITextField *textFieldToBringIntoView;

(with appropriate @synthesize textFieldToBringIntoView;in the implementation. Then I added this override method to the implementation:

@synthesize textFieldToBringIntoView;在实现中适当。然后我将这个覆盖方法添加到实现中:

- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)how
{
    if (textFieldToBringIntoView) {
       // Do whatever mucking with `rect`'s origin needed to make it visible
       // based on context or its spatial relationship with the other
       // view that the system is getting confused by.

       textFieldToBringIntoView = nil;        // Go back to normal
       }
    [super scrollRectToVisible:rect animated:how];
}

In the delegate method for the UITextFieldfor when it's about to begin editing, just set textFieldToBringIntoViewto the textFieldin question:

在 forUITextField即将开始编辑时的委托方法中,只需设置textFieldToBringIntoView为有textField问题的:

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
    // Ensure it scrolls into view so that keyboard doesn't obscure it
    // The system is about to call |scrollRectIntoView:| for the scrolling
    // superview, but the system doesn't get things right in certain cases.

    UIScrollView *parent = (UIScrollView *)textField.superview;
    // (or figure out the parent UIScrollView some other way)

    // Tell the override to do something special just once
    // based on this text field's position in its parent's scroll view.
    parent.textFieldToBringIntoView = textField;
    // The override function will set this back to nil

    return(YES);
}

It seems to work. And if Apple fixes their bug, it seems like it might still work (fingers crossed).

它似乎工作。如果 Apple 修复了他们的错误,它似乎仍然有效(手指交叉)。