编辑嵌入的 UITextView 时 UITableView 滚动太远

发布于 2024-11-19 07:48:33 字数 6517 浏览 5 评论 0原文

我已成功将 UITextView 嵌入 UITableViewCell 中,并且大部分表格工作正常。但是,当我在 UITextView 上启用编辑并开始编辑时,表格向上移动太多,遮挡了光标。有没有办法控制tableview滚动的距离?手动将视图滚动到单元格是可行的,但视图在向下滚动回视图之前仍然会向上滚动。

这是我的意思的一个例子: 编辑 UITextField - 该字段整齐地放置在键盘正上方。 http://imageshack.us/photo/my-images/13/textfield。 png/

编辑 UITextView - 该字段明显位于键盘上方,从键盘上删除工具栏不会影响任何内容) http://imageshack.us/photo/my-images/809/textview。 png/

这是与 UITableViewController 对象中的 UITextView 相关的所有代码:

- (void)viewDidLoad
{
    [super viewDidLoad];    

    self.navigationItem.rightBarButtonItem = self.editButtonItem;

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

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
    viewTargetedForEditing = (UIView *)textView;
    return YES;
}

- (void)textViewDidBeginEditing:(UITextView *)textView
{
    [self.navigationController setNavigationBarHidden:YES animated:YES];


    // shrink the textView to fit on-screen
    originalTextViewFrame = textView.frame;
    CGRect keyboardRect = [[keyboardUserinfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGFloat keyboardHeight = keyboardRect.size.height;


    CGRect newViewFrame = textView.frame;
    CGFloat spaceAboveKeyboard = self.containerView.frame.size.height - keyboardHeight;
    newViewFrame.size.height = (spaceAboveKeyboard < textView.frame.size.height) ? spaceAboveKeyboard : textView.frame.size.height;


    /* animate the calculations */

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[[keyboardUserinfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];

    textView.frame = newViewFrame;

    [UIView commitAnimations];



    // recalculate the keyboard height, in case we aren't in portrait mode
    CGFloat toolbarHeight;
    if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
        toolbarHeight = 44.0;
    } else {
        toolbarHeight = 32.0;
    }

    CGRect frame = textView.inputAccessoryView.frame;
    frame.size.height = toolbarHeight;
}

- (void)endTextViewEditing
{
    [viewTargetedForEditing resignFirstResponder];
}

- (void)textViewDidEndEditing:(UITextView *)textView
{
    [self.navigationController setNavigationBarHidden:NO animated:YES];
}

#pragma mark - Keyboard Notifications

- (void)keyboardWillShow:(NSNotification *)notification
{
    [keyboardUserinfo release];
    keyboardUserinfo = [[notification userInfo] retain];
    [self viewDidBeginEditing:viewTargetedForEditing];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
    [keyboardUserinfo release];
    keyboardUserinfo = [[notification userInfo] retain];
    [self viewDidEndEditing:viewTargetedForEditing];
}

- (void)viewDidBeginEditing:(id)aView
{
    // called 2nd

    UITableViewCell *cell = (UITableViewCell *)[aView superview];
    [self.tableView scrollToRowAtIndexPath:[self.tableView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
- (void)viewDidEndEditing:(id)aView
{   
    NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)[viewTargetedForEditing superview]];

    gallupAppDelegate *appDelegate = (gallupAppDelegate *)[[UIApplication sharedApplication] delegate];

    switch (indexPath.section) {
        case SectionDescription:
            if (![[(UITextField *)aView text] isEqualToString:self.plan.Description]) {
                self.plan.Description = [(UITextField *)aView text];
                [appDelegate saveManagedContext];
            }
            break;

        case SectionNotes:
            if (![[(UITextView *)aView text] isEqualToString:self.plan.Notes]) {
                self.plan.Notes = [(UITextView *)aView text];
                [appDelegate saveManagedContext];
            }
            break;

        case SectionLocation:
            if (![[(UITextField *)aView text] isEqualToString:self.plan.Location]) {
                self.plan.Location = [(UITextField *)aView text];
                [appDelegate saveManagedContext];
            }
            break;
    }
}

TextViewCell 是 UITableViewCell 的子类,它是给我带来问题的单元格滚动。这是实现:

@implementation TextViewCell

@synthesize contents=_contents;

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        _contents = [[UITextView alloc] initWithFrame:CGRectZero];
        [self addSubview:_contents];
        self.contents.font = [UIFont systemFontOfSize:17];
        self.contents.dataDetectorTypes = UIDataDetectorTypeAll;


        CGRect frame = CGRectMake(0, 0, self.window.frame.size.width, 44.0);
        UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
        UIBarButtonItem *done = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(endTextViewEditing)];
        UIToolbar *textViewToolbar = [[UIToolbar alloc] initWithFrame:frame];
        textViewToolbar.barStyle = UIBarStyleBlackOpaque;
        [textViewToolbar setItems:[NSArray arrayWithObjects:spacer, done, nil]];

        self.contents.inputAccessoryView = textViewToolbar;
    }
    return self;
}

- (void)endTextViewEditing
{
    [self.contents resignFirstResponder];
}

#define LEFT_MARGIN 15
#define TOP_MARGIN 5
- (void)layoutSubviews
{
    [super layoutSubviews];

    CGFloat width = self.frame.size.width - (LEFT_MARGIN *2);
    CGFloat height = self.frame.size.height - (TOP_MARGIN *2);
    self.contents.frame = CGRectMake(LEFT_MARGIN, TOP_MARGIN, width, height);
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    //[super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

- (void)dealloc
{
    [super dealloc];
}

@end

I've successfully embedded a UITextView inside a UITableViewCell, and most of the table is working fine. However, when I enable editing on the UITextView and start editing, the table shifts up too far, obscuring the cursor. Is there a way to control how far the tableview scrolls? Manually scrolling the view to the cell works, but the view still scrolls up before scrolling back down and into view.

Here is an example of what I mean:
editing a UITextField - the field is neatly placed directly above the keyboard.
http://imageshack.us/photo/my-images/13/textfield.png/

editing a UITextView - the field is placed significantly above the keyboard removing the toolbar from the keyboard doesn't affect anything)
http://imageshack.us/photo/my-images/809/textview.png/

Here's all the code that is relevant to the UITextView in the UITableViewController object:

- (void)viewDidLoad
{
    [super viewDidLoad];    

    self.navigationItem.rightBarButtonItem = self.editButtonItem;

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

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
    viewTargetedForEditing = (UIView *)textView;
    return YES;
}

- (void)textViewDidBeginEditing:(UITextView *)textView
{
    [self.navigationController setNavigationBarHidden:YES animated:YES];


    // shrink the textView to fit on-screen
    originalTextViewFrame = textView.frame;
    CGRect keyboardRect = [[keyboardUserinfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGFloat keyboardHeight = keyboardRect.size.height;


    CGRect newViewFrame = textView.frame;
    CGFloat spaceAboveKeyboard = self.containerView.frame.size.height - keyboardHeight;
    newViewFrame.size.height = (spaceAboveKeyboard < textView.frame.size.height) ? spaceAboveKeyboard : textView.frame.size.height;


    /* animate the calculations */

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[[keyboardUserinfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];

    textView.frame = newViewFrame;

    [UIView commitAnimations];



    // recalculate the keyboard height, in case we aren't in portrait mode
    CGFloat toolbarHeight;
    if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
        toolbarHeight = 44.0;
    } else {
        toolbarHeight = 32.0;
    }

    CGRect frame = textView.inputAccessoryView.frame;
    frame.size.height = toolbarHeight;
}

- (void)endTextViewEditing
{
    [viewTargetedForEditing resignFirstResponder];
}

- (void)textViewDidEndEditing:(UITextView *)textView
{
    [self.navigationController setNavigationBarHidden:NO animated:YES];
}

#pragma mark - Keyboard Notifications

- (void)keyboardWillShow:(NSNotification *)notification
{
    [keyboardUserinfo release];
    keyboardUserinfo = [[notification userInfo] retain];
    [self viewDidBeginEditing:viewTargetedForEditing];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
    [keyboardUserinfo release];
    keyboardUserinfo = [[notification userInfo] retain];
    [self viewDidEndEditing:viewTargetedForEditing];
}

- (void)viewDidBeginEditing:(id)aView
{
    // called 2nd

    UITableViewCell *cell = (UITableViewCell *)[aView superview];
    [self.tableView scrollToRowAtIndexPath:[self.tableView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
- (void)viewDidEndEditing:(id)aView
{   
    NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)[viewTargetedForEditing superview]];

    gallupAppDelegate *appDelegate = (gallupAppDelegate *)[[UIApplication sharedApplication] delegate];

    switch (indexPath.section) {
        case SectionDescription:
            if (![[(UITextField *)aView text] isEqualToString:self.plan.Description]) {
                self.plan.Description = [(UITextField *)aView text];
                [appDelegate saveManagedContext];
            }
            break;

        case SectionNotes:
            if (![[(UITextView *)aView text] isEqualToString:self.plan.Notes]) {
                self.plan.Notes = [(UITextView *)aView text];
                [appDelegate saveManagedContext];
            }
            break;

        case SectionLocation:
            if (![[(UITextField *)aView text] isEqualToString:self.plan.Location]) {
                self.plan.Location = [(UITextField *)aView text];
                [appDelegate saveManagedContext];
            }
            break;
    }
}

The TextViewCell is a subclass of UITableViewCell, and it is the cell that is giving me the problem with scrolling.Here's the implementation:

@implementation TextViewCell

@synthesize contents=_contents;

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        _contents = [[UITextView alloc] initWithFrame:CGRectZero];
        [self addSubview:_contents];
        self.contents.font = [UIFont systemFontOfSize:17];
        self.contents.dataDetectorTypes = UIDataDetectorTypeAll;


        CGRect frame = CGRectMake(0, 0, self.window.frame.size.width, 44.0);
        UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
        UIBarButtonItem *done = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(endTextViewEditing)];
        UIToolbar *textViewToolbar = [[UIToolbar alloc] initWithFrame:frame];
        textViewToolbar.barStyle = UIBarStyleBlackOpaque;
        [textViewToolbar setItems:[NSArray arrayWithObjects:spacer, done, nil]];

        self.contents.inputAccessoryView = textViewToolbar;
    }
    return self;
}

- (void)endTextViewEditing
{
    [self.contents resignFirstResponder];
}

#define LEFT_MARGIN 15
#define TOP_MARGIN 5
- (void)layoutSubviews
{
    [super layoutSubviews];

    CGFloat width = self.frame.size.width - (LEFT_MARGIN *2);
    CGFloat height = self.frame.size.height - (TOP_MARGIN *2);
    self.contents.frame = CGRectMake(LEFT_MARGIN, TOP_MARGIN, width, height);
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    //[super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

- (void)dealloc
{
    [super dealloc];
}

@end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

红颜悴 2024-11-26 07:48:33

事实证明,子类化 UITableView 并实现以下解决了问题:

- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated
{
    [super setContentOffset:contentOffset animated:animated];
    return;



    static int i = 0;
    if (0 == i) {
        i++;
    } else {
        i = 0;
        [super setContentOffset:contentOffset animated:animated];
    }
    return;
}

显然 -setContentOffset:animated: 消息发送了 2 次,并且如果允许第一个消息第二次运行则无法正常工作。

有没有人有任何关于为什么这可以解决问题的现场信息?

As it turns out, subclassing the UITableView and implementing the following fixed the problem:

- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated
{
    [super setContentOffset:contentOffset animated:animated];
    return;



    static int i = 0;
    if (0 == i) {
        i++;
    } else {
        i = 0;
        [super setContentOffset:contentOffset animated:animated];
    }
    return;
}

Apparently the -setContentOffset:animated: message was sent 2x, and if the first one is allowed to run the second time round doesn't do it's job properly.

Does anyone have any insite as to why this would fix the problem?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文