1

我有一个 Tableview,用户可以在其中将值输入到 textField 作为自定义单元格之一

Apple 有一些关于如何通过将视图重新定位到键盘的垂直尺寸(此处)来调整视图内容的文档,但它依赖于将视图放入 UIScrollView。我不能用 tableview 做到这一点。

我可以重新设计应用程序,以便使用通常的导航控制器在单独的详细视图中完成输入,但如果可能的话,我宁愿用户不必执行额外的触摸(并被运送到另一个屏幕)。我喜欢“在我们所在的地方”做事的想法

所以我的解决方法是在底部有一些额外的 tableview 单元格包含 %20 左右,正常使用不应该注册奇怪,因为它们只关注可见的内容。我必须将空格存储在我的数据源数组中,然后按降序排序,但这没关系

问题是,这是好的做法吗?更有可能的是,反对苹果的HIG足以拒绝吗?

4

3 回答 3

2

UITableView is a subclass of UIScrollView, so should be able to adjust the content and scroll view insets just like in the example you linked.

于 2013-01-02T23:45:32.627 回答
2

The way I've solved this issue is to subclass UITableView. Here's what I've done:

// AOTableView.h file

typedef enum
{
    AOKeyboardStateUnknown = 0,
    AOKeyboardStateShowing,
    AOKeyboardStateHidden
} AOKeyboardState;

#import <UIKit/UIKit.h>
#import "AOKeyboardState.h"

@interface AOTableView : UITableView
@property (nonatomic) BOOL observeKeyboardNotifications;
@property (nonatomic) AOKeyboardState keyboardState;
@end


// AOTableView.m file

#import "AOTableView.h"

@interface AOTableView(Private)
@property (nonatomic) CGRect frame0;
- (void)setup;
- (void)keyboardWillShow:(NSNotification *)notification;
- (void)keyboardWillHide:(NSNotification *)notification;
@end

@implementation AOTableView

#pragma mark - Object lifecycle

- (void)awakeFromNib
{       
    [self setup];
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];

    if (self)
    {
        [self setup];
    }
    return self;
}

- (void)setup
{
    self.contentSize = self.frame.size;
    self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    _keyboardState = AOKeyboardStateUnknown;
    _frame0 = self.frame;
    _observeKeyboardNotifications = NO;
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

#pragma mark - Custom setters

- (void)setObserveKeyboardNotifications:(BOOL)observeKeyboardNotifications
{
    if (_observeKeyboardNotifications == observeKeyboardNotifications)
        return;

    _observeKeyboardNotifications = observeKeyboardNotifications;

    if (_observeKeyboardNotifications)
    {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
    }
    else
    {
         [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
        [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
    }
}

#pragma mark - UIKeyboard Notifications

- (void)keyboardWillShow:(NSNotification *)notification
{
    if (self.keyboardState == AOKeyboardStateShowing)
        return;

    self.frame0 = self.frame;
    self.keyboardState = AOKeyboardStateShowing;

    NSDictionary* info = [notification userInfo];
    CGRect keyboardFrame = CGRectZero;
    [[info objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrame];

    CGRect frame = self.frame0;    
    frame.size.height = CGRectGetMinY(keyboardFrame) - CGRectGetMinY(frame);
    self.frame = frame;

    [self scrollToRowAtIndexPath:self.indexPathForSelectedRow atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
    [self deselectRowAtIndexPath:self.indexPathForSelectedRow animated:NO];
}

- (void)keyboardWillHide:(NSNotification *)notification
{
    if (self.keyboardState == AOKeyboardStateHidden)
        return;

    self.keyboardState = AOKeyboardStateHidden;
    self.frame = self.frame0;
}
@end

After creation (or loading the view from an IBOutlet), you call this method to tell the class to start listening for keyboard notifications:

[tableViewInstance setObserveKeyboardNotifications:YES];

Whenever a user clicks on a cell, it becomes the self.indexPathForSelectedRow cell... so its scrolled to by the AOTableView instance automatically.

For this to work, though, I've had to turn off userInteraction on the UITextField within the cell (otherwise, the device can get confused about if the user is clicking on the cell or on the text field). Instead, when a user selects a cell that has a text field, I tell the text field to the become first responder, like this:

[cell.textField becomeFirstResponder];

I hope this helps.

于 2013-01-02T23:46:44.450 回答
1

你不需要额外的细胞或任何花哨的东西。

由于您的文本字段位于表格视图单元格内,因此您可以使用以下内容:

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
    UITableViewCell *cell = (UITableViewCell *)textField.superview.superview;
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
    return YES;
}

这意味着每次文本字段成为第一响应者时,键盘都会适当地滚动。这利用了作为滚动视图子类的表格视图。

请注意,这假设:

  • 您的(表)视图控制器是文本字段的代表。
  • 您的文本字段是单元格内容视图的子视图,而不是单元格本身。
    • 如果文本字段是单元格的子视图,则上述方法的第一行应该只引用一个超级视图(即 textField.superview)。
于 2013-01-03T00:16:20.277 回答