UITextView in a UITableViewCell smooth auto-resize shows and hides keyboard on iPad, but works on iPhone

后端 未结 2 583
别那么骄傲
别那么骄傲 2020-12-07 11:02

I have implemented a custom UITableViewCell which includes a UITextView that auto-resizes as the user types, similar to the \"Notes\" field in the Contacts app. It is workin

相关标签:
2条回答
  • 2020-12-07 11:28

    you should return NO in:

     -(BOOL) textViewShouldEndEditing:(UITextView *)textView
    

    if you would like to show keyboard at all times. You should handle cases, which keyboard should be hidden, by returning YES to this delegate function.

    edit:

    I dug a little more, when [tableView endUpdates] called, it basically does 3 things :

    1. Disables user interaction on the tableView
    2. Updates cell changes
    3. Enables user interaction on the tableView

    The difference between SDKs(platforms) is at [UIView setUserInteractionEnabled] method. As UITableView does not overrite setUserInteractionEnabled method, it is called from super (UIView).

    iPhone when setUserInteractionEnabled called, looks for a private field _shouldResignFirstResponderWithInteractionDisabled which returns NO as default, so does not resign the first responder (UITextView)

    But on iPad there is no such check AFAIK, so it resignes UITextView on step 1, and sets focus and makes it first responder on step 3

    Basically, textViewShouldEndEditing, which allows you to keep focus, according to SDK docs, is your only option ATM.

    This method is called when the text view is asked to resign the first responder status. This might occur when the user tries to change the editing focus to another control. Before the focus actually changes, however, the text view calls this method to give your delegate a chance to decide whether it should.

    0 讨论(0)
  • 2020-12-07 11:33

    I had the same issue for an iPad app and came up with another solution without having calculating the height of the text itself.

    First create a custom UITableViewCell in IB with an UITextField placed in the cell's contentView. It's important to set the text view's scrollEnabled to NO and the autoresizingMask to flexibleWidth and flexibleHeight.


    In the ViewController implement the text view's delegate method -textViewDidChanged: as followed, where textHeight is a instance variable with type CGFloat and -tableViewNeedsToUpdateHeight is a custom method we will define in the next step.

    - (void)textViewDidChange:(UITextView *)textView
    {
        CGFloat newTextHeight = [textView contentSize].height;
    
        if (newTextHeight != textHeight)
        {
            textHeight = newTextHeight;
            [self tableViewNeedsToUpdateHeight];
        }
    }
    

    The method -tableViewNeedsToUpdateHeight calls the table view's beginUpdates and endUpdates, so the table view itself will call the -tableView:heightForRowAtIndexPath: delegate method.

    - (void)tableViewNeedsToUpdateHeight
    {
        BOOL animationsEnabled = [UIView areAnimationsEnabled];
        [UIView setAnimationsEnabled:NO];
        [table beginUpdates];
        [table endUpdates];
        [UIView setAnimationsEnabled:animationsEnabled];
    }
    

    In the table view's -tableView:heightForRowAtIndexPath: delegate method we need to calculate the new height for the text view's cell based on the textHeight.

    First we need to resize the text view cells height to the maximum available height (after subtracting the height of all other cells in the table view). Then we check if the textHeight is bigger than the calculated height.

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {   
        CGFloat heightForRow = 44.0;
    
        if ([indexPath row] == kRowWithTextViewEmbedded)
        {
            CGFloat tableViewHeight = [tableView bounds].size.height;
            heightForRow = tableViewHeight - ((kYourTableViewsNumberOfRows - 1) * heightForRow);
    
            if (heightForRow < textHeight) 
            {
                heightForRow = textHeight;
            }
        }
    
        return heightForRow;
    }
    

    For a better user experience set the table view's content insets for bottom to e.g. 50.0.

    I've tested it on the iPad with iOS 4.2.1 and works as expected.

    Florian

    0 讨论(0)
提交回复
热议问题