在UITableViewCell中编辑UITextField时禁用UITableView的自动滚动

时间:2012-03-09 15:58:28

标签: ios uitableview uiscrollview uitextfield

我在UITableViewCell内使用自定义UITableView。这些UITableViewCell中的每一个都非常高,顶部包含UITextField

当用户点击UITextField进行编辑时,会出现一个键盘,UITableView会自动滚动,以便单元格位于屏幕顶部。

问题是,这会将UITableView滚动到UITableViewCell的底部,而不是顶部。当UITableViewCell为高并且已编辑时,UITextField位于顶部,因此您无法看到UITextField。我知道如何以编程方式滚动UITableView,但我只是不知道如何禁用此自动滚动,以便我可以自己滚动UITableView。我怎么能这样做?

9 个答案:

答案 0 :(得分:66)

autoscroll-behavior位于UITableViewController功能。

要禁用自动滚动,我发现了两种方法:

  1. 使用UITableViewController而不是UIViewController - 自行设置数据源和委托。
  2. 覆盖viewWillAppear方法,不要拨打[super viewWillAppear: animated]
  3. 使用这两种解决方案,您不仅可以禁用Autoscroll,还可以禁用其他一些不错但非必要的功能,这些功能在Apple的类参考概述中有所描述:

    https://developer.apple.com/documentation/uikit/uitableviewcontroller

答案 1 :(得分:8)

定义UITableViewController的属性:

@property (nonatomic) BOOL scrollDisabled;
@property (nonatomic) CGFloat lastContentOffsetY;

致电becomeFirstResponder之前:

// Save the table view's y content offset 
lastContentOffsetY = tableViewController.tableView.contentOffset.y;
// Enable scrollDisabled
scrollDisabled = YES;

将以下代码添加到表视图控制器:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (self.scrollDisabled) {
        [self.tableView setContentOffset:CGPointMake(0, lastContentOffsetY)];
    }
    ...
}

致电resignFirstResponder后,请设置scrollDisabled = NO

答案 2 :(得分:4)

您可以执行以下操作:

- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardDidShow:)
                                                 name:UIKeyboardDidShowNotification object:nil];
}

- (void)unregisterForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
}

- (void)keyboardWillShow:(NSNotification *)notification
{
    self.tableView.scrollEnabled = NO;
}

- (void)keyboardDidShow:(NSNotification *)notification
{
    double delayInSeconds = 0.3;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            self.tableView.scrollEnabled = YES;
    });
}

然后实现此UIScrollViewDelegate方法

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (! self.tableView.scrollEnabled)
        [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
}

!!!但请注意,如果用户点击UITextField中将被键盘覆盖的位置,则它将不会滚动。

从我的角度来看,最好的办法是确保所有单元格从顶部到包含UITextField的单元格将在键盘显示时显示。

答案 3 :(得分:1)

对我而言,问题不在于滚动,而是在屏幕上编辑了文本视图。

因此,我只是在触发编辑时将tableview重新滚动到我想要的位置,而不是阻止滚动,如下所示:

public func textViewShouldBeginEditing(textView: UITextView) -> Bool {            
  dispatch_async(dispatch_get_main_queue()) {
    tableViewController.tableView.scrollToRowAtIndexPath(self.indexPath!, atScrollPosition: UITableViewScrollPosition.Middle, animated: true)
  }
  return true
}

答案 4 :(得分:1)

不幸的是,覆盖-viewWillAppear:在iOS 8中对我不起作用。

这是我的解决方案(如在UITableViewController实现中):

- (void)viewDidLoad {

[super viewDidLoad];

[[NSNotificationCenter defaultCenter] removeObserver:self.tableView name:UIKeyboardWillShowNotification object:nil];

[[NSNotificationCenter defaultCenter] removeObserver:self.tableView name:UIKeyboardWillHideNotification object:nil];
}

由于UIKeyboard的显示/隐藏通知会调用自动滚动行为,因此请勿观察它们。

答案 5 :(得分:1)

最好的方法是继承UITableView,然后覆盖setContentOffset(_ contentOffset: CGPoint, animated: Bool),而不是调用super.setContentOffset(_ contentOffset: CGPoint, animated: Bool)。在此方法中,视图控制器正在执行自动滚动。

override func setContentOffset(_ contentOffset: CGPoint, animated: Bool)
{
    //Do nothing
}

答案 6 :(得分:0)

您可以像这样禁用自动内容插入调整:

tableView.contentInsetAdjustmentBehavior = .never

答案 7 :(得分:-2)

您是否尝试将“scrollsToTop” - tableview的属性设置为NO。默认情况下为YES。

答案 8 :(得分:-5)

您可以尝试执行以下操作:

self.tableView.scrollEnabled = NO;

这应禁用tableview中的scrollview。