开发者

UITableView scrolls too far when editing embedded UITextView

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)textVie开发者_开发知识库wDidEndEditing:(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


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?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜