3

我正在尝试创建 Any.DO 应用程序的副本。这tableHeaderView是一个“NewTaskCell”视图,其中包含一个带有UITextField. 出于某种原因,在键盘出现后,tableView 无法一直滚动到底部。这是我尝试过的:

  1. 更改 tableView 的框架
  2. 更改 tableView 的边界
  3. 更改 tableView 的 contentSize
  4. 键盘关闭后更新页脚视图

它必须与键盘或文本字段有关,因为它仅在键盘出现时才会发生。

在下面的动画中,您可以看到如果我单击加号按钮并显示键盘,则 tableView 无法滚动到底部。之后,如果我单击加号按钮并且显示键盘,那么它可以滚动到底部。

这是整个项目的源代码:Any.DO

这就是我的 viewDidLoad 方法中的内容。

- (void)viewDidLoad
{
    [super viewDidLoad];

    [[self tableView] setAllowsSelection: YES];
    [[self tableView] setShowsVerticalScrollIndicator: NO];

    // Make sure there aren't any empty cells showing at the bottom
    // Caused initial error [[self tableView] setTableFooterView: [UIView new]];

    // Fixes error at first, until the keyboard shows up
    UIView *footer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 45)];
footer.backgroundColor = [UIColor clearColor];
self.tableView.tableFooterView = footer;

    // Make the separators look right
    [[self tableView] setSeparatorStyle: UITableViewCellSeparatorStyleSingleLine];
    [[self tableView] setSeparatorColor: [UIColor colorWithWhite: 0.95 alpha: 1]];

    UINib *nibTwo = [UINib nibWithNibName: @"TaskCell" bundle: nil];
    [[self tableView] registerNib: nibTwo forCellReuseIdentifier: @"TaskCell"];

    // Create the new task cell to go above the tableView
    // --------------------------------------------------
    NewTaskCell *myNewTaskCell = [[NewTaskCell alloc] init];

    // Need to access it later to show the keyboard
    [self setTheNewTaskCell: myNewTaskCell];

    [[theNewTaskCell view] setFrame: CGRectMake(0, 0, 320, 44)];
    [[[theNewTaskCell reminderButton] layer] setOpacity: 0];
    [[[theNewTaskCell locationButton] layer] setOpacity: 0];
    [[[theNewTaskCell addTaskButton] layer] setOpacity: 0];

    // Assign a method for each button
    [[theNewTaskCell reminderButton] addTarget:self action:@selector(addReminder)     forControlEvents: UIControlEventTouchUpInside];
    [[theNewTaskCell locationButton] addTarget:self action:@selector(addLocationReminder) forControlEvents: UIControlEventTouchUpInside];
    [[theNewTaskCell addTaskButton] addTarget:self action:@selector(addTaskToList) forControlEvents: UIControlEventTouchUpInside];

    // Separator view
    UIView *separatorView = [[UIView alloc] initWithFrame: CGRectMake(0, 43, 320, 1)];
    [separatorView setBackgroundColor: [UIColor colorWithWhite: 0.5 alpha: 0.2]];
    [[theNewTaskCell view] addSubview: separatorView];

    [[self tableView] setTableHeaderView: [theNewTaskCell view]];
    [[self tableView] setContentInset: UIEdgeInsetsMake(-44, 0, 0, 0)];
    // ---------------------------------------------------
    // For Reordering
    [[self tableView] setEditing: YES];

    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget: self action: @selector(longPress:)];
    [longPress setMinimumPressDuration: 0.3];
    [longPress setDelaysTouchesBegan: YES];

    [self setLongPressGesture: longPress];
    [[self tableView] addGestureRecognizer: longPress];
}

单击 + 按钮时的代码

-(void)makeNewTask
{
    // Create the fromPosition and toPosition of the label animation
    CGRect fromPosition;
    CGRect toPosition = CGRectMake(todayDayLabel.frame.origin.x +     todayDayLabel.superview.frame.origin.x, todayDayLabel.frame.origin.y + todayDayLabel.superview.frame.origin.y, todayDayLabel.frame.size.width, todayDayLabel.frame.size.height);

    if ([self dayType] == TaskDayTypeToday)
        fromPosition = toPosition;
    else if ([self dayType] == TaskDayTypeTomorrow)
        fromPosition = CGRectMake(tomorrowDayLabel.frame.origin.x + tomorrowDayLabel.superview.frame.origin.x, tomorrowDayLabel.frame.origin.y + tomorrowDayLabel.superview.frame.origin.y, tomorrowDayLabel.frame.size.width, tomorrowDayLabel.frame.size.height);
    else if ([self dayType] == TaskDayTypeUpcoming)
        fromPosition = CGRectMake(upcomingDayLabel.frame.origin.x + upcomingDayLabel.superview.frame.origin.x, upcomingDayLabel.frame.origin.y + upcomingDayLabel.superview.frame.origin.y, upcomingDayLabel.frame.size.width, upcomingDayLabel.frame.size.height);
    else
        fromPosition = CGRectMake(somedayDayLabel.frame.origin.x + somedayDayLabel.superview.frame.origin.x, somedayDayLabel.frame.origin.y + somedayDayLabel.superview.frame.origin.y, somedayDayLabel.frame.size.width, somedayDayLabel.frame.size.height);
    // -------------------------------------------------------------

    isLoading = YES;

    [[self tableView] reloadData];

    // Make sure the scroller doesn't show up on the side
    [[self tableView] setShowsVerticalScrollIndicator: NO];

    // Create the label and animate it -------------------------
    UILabel *lbl = [[[[[NSBundle mainBundle] loadNibNamed: @"DayCell" owner: self options:nil] objectAtIndex: 0] subviews] objectAtIndex: 0];

    if ([self dayType] == TaskDayTypeToday)
        [lbl setText: @"TODAY"];
    if ([self dayType] == TaskDayTypeTomorrow)
        [lbl setText: @"TOMORROW"];
    if ([self dayType] == TaskDayTypeUpcoming)
        [lbl setText: @"UPCOMING"];
    if ([self dayType] == TaskDayTypeSomeday)
        [lbl setText: @"SOMEDAY"];

    [self setTheDayLabel: lbl];
    [theDayLabel setFrame: fromPosition];

    [theDayLabel setTranslatesAutoresizingMaskIntoConstraints: YES];
    [[self tableView] addSubview: theDayLabel];

    // animate it moving to the right position
    if (!animateContentInset) {
        [[self tableView] setContentInset: UIEdgeInsetsMake(0, 0, 0, 0)];
        [[self tableView] setScrollEnabled: NO];
    }
    else {
        [UIView animateWithDuration: 0.4 delay: 0 options: UIViewAnimationOptionCurveEaseOut animations: ^{
            [[self tableView] setContentInset: UIEdgeInsetsMake(0, 0, 0, 0)];
            [theDayLabel setFrame: toPosition];
        } completion: ^(BOOL done){
            [[self tableView] setScrollEnabled: NO];
        }];
    }
    // ----------------------------------------------------------
    // Create the UIButton to get back to the tableView
    UIButton *backToTableView = [UIButton buttonWithType: UIButtonTypeCustom];
    [backToTableView setFrame: CGRectMake(1, 45, 320, 480)];
    [backToTableView addTarget: self action: @selector(showTableView) forControlEvents: UIControlEventTouchUpInside];

    [[self tableView] addSubview: backToTableView];

    // Show the keyboard
    [[theNewTaskCell theNewTaskTextField] setDelegate: self];
    //[[theNewTaskCell theNewTaskTextField] becomeFirstResponder];
}

backToTableView 按钮的代码

-(void)showTableView
{
    [theDayLabel setHidden: YES];

    [[self tableView] setScrollEnabled: YES];

    [UIView animateWithDuration: 0.4 animations:^{
        // self.tableView.contentInset = UIEdgeInsetsZero;
        [[self tableView] setContentInset: UIEdgeInsetsMake(-REFRESH_HEADER_HEIGHT, 0, 0, 0)];

        // Get the newTaskCell view, then get the textfield from that view
        [[theNewTaskCell theNewTaskTextField] setText: @""];
        [[theNewTaskCell addTaskButton] setAlpha: 0];
        [[theNewTaskCell reminderButton] setAlpha: 0];
        [[theNewTaskCell locationButton] setAlpha: 0];

        [[theNewTaskCell theNewTaskTextField] resignFirstResponder];

        // Remove the button to go back to the tableView
        for (UIView *v in [[self tableView] subviews]) {
            if (v.frame.origin.x == 1)
                [v removeFromSuperview];
        }

        isLoading = NO;

        [[self tableView] reloadData];
    }];
}

这就是问题的样子:

问题

4

7 回答 7

2

看起来你的 UITableView 被状态栏偏移了 20px。您应该将 UITableView 的高度降低 20px,它会被修复。

于 2013-04-26T15:14:51.743 回答
1

无法理解您要在代码中执行的操作。

但是,看看动画,我认为,你只需要将 tableview.frame 的高度降低 10-20 点。

当内容和框架高度大于可见区域时,通常会看到此行为。设置框架高度以匹配可见区域的高度将使您的表格视图滚动。

于 2013-04-26T16:49:43.543 回答
1

我通过将此代码添加到 showTableView 方法中解决了这个问题:

[[self tableView] setContentInset: UIEdgeInsetsMake(REFRESH_HEADER_HEIGHT, 0, 0, 0)];
[[self tableView] setContentInset: UIEdgeInsetsMake(0, 0, 0, 0)];
于 2013-04-27T02:41:55.843 回答
0

如果该偏移量是问题 - 一个解决它的选项是为您的整个应用程序全屏而不是仅针对该 ViewController。

这个问题如何回答你 -这是让 iPad 应用全屏显示的正确方法吗?

于 2013-04-26T16:40:48.513 回答
0

对于未来,在iOS7上遇到类似问题的任何人都可以做这样的事情

 [[self tableView] setContentInset: UIEdgeInsetsMake(0, 0, self.bottomLayoutGuide.length, 0)];

topLayoutGuide并且bottomLayoutGuide是自动布局的一部分,length两者都可以使用,这是一个很棒的功能。

于 2014-04-30T15:36:56.503 回答
0

有一个类似的问题,并通过删除 viewWillLayoutSubviews 中设置 TableVC 的 contentInset 的代码来解决它,如下所示:

UIEdgeInsets insets = UIEdgeInsetsMake([self.topLayoutGuide length], 0, 0, 0);
[myTableViewController.view setContentInset:insets];

我不明白的是,为什么要设置插图,特别是当不设置如上所示的底部时,会有什么不同?因此,通过根本不设置它们,大概将插图设置为 UIEdgeInsetsZero 的默认值,它以某种方式解决了这个问题。我认为这可能是一个 iOS 错误。我注意到我只在 32 位设备上遇到这个问题。

于 2016-02-17T15:50:00.463 回答
-1

您可能会将 tableView 框架设置为整个屏幕,其中还包括状态栏。将 tableView 的高度降低到 20px

[[self tableView] setFrame:CGRectOffset(self.tableView.frame, 0, -20)];

或将框架设置为 self.view.frame

于 2013-04-26T14:58:33.987 回答