2014-05-16 174 views
0

我正在實施自動增長UITextView。我打算在Whatsapp中使用類似的消息框行爲,當文本超過1行時自動填充。Animate UITextView使用自動佈局調整大小

我正在使用下面描述的方法,將高度約束存儲在UITextView子類中,並在文本更改時對其進行修改。

當我按下輸入鍵時,我的解決方案可以正確動畫,但在輸入行結束時它不起作用。在這種情況下,它只是立即改變大小。

代表執行動畫- (void)textViewDidChange:(UITextView *)textView方法產生相同的結果。

如何使用自動佈局系統正確地爲TextView高度設置動畫效果?

我採取這樣的:

@interface OEAutoGrowingTextView() 

@property (strong, nonatomic) NSLayoutConstraint *heightConstraint; 

@end 


@implementation OEAutoGrowingTextView 

- (id)initWithFrame:(CGRect)frame 
{ 
    if (!(self = [super initWithFrame:frame])) 
    { 
     return nil; 
    } 

    [self commonInit]; 

    return self; 
} 

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

- (void)commonInit 
{ 
    // If we are using auto layouts, than get a handler to the height constraint. 
    for (NSLayoutConstraint *constraint in self.constraints) 
    { 
     if (constraint.firstAttribute == NSLayoutAttributeHeight) 
     { 
      self.heightConstraint = constraint; 
      break; 
     } 
    } 

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChange:) name:UITextViewTextDidChangeNotification object:self]; 
} 

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

- (void)textDidChange:(NSNotification *)notification 
{ 
    self.heightConstraint.constant = self.contentSize.height; 
    [UIView animateWithDuration:1.0f animations:^ 
    { 
     [self layoutIfNeeded]; 
    }]; 
} 

@end 

注:執行以下操作並沒有幫助。

- (void)textDidChange:(NSNotification *)notification 
{ 
    self.heightConstraint.constant = self.contentSize.height; 
    [UIView animateWithDuration:1.0f animations:^ 
    { 
     [self layoutIfNeeded]; 
     for (UIView *view in self.subviews) 
     { 
      [view layoutIfNeeded]; 
     } 
    }]; 
} 

進一步更新:這似乎是在iOS的7.x中的一個錯誤,我認爲這是固定在iOS 8.0。

回答

1

好了,問題是,作爲ios7的,.contentSize不是UITextViews正確的。我有這個功能,你需要自己計算contentSize。我向UITextView添加了一個類別方法-contentHeight,並用它來計算contentSize。

看到這兩個鏈接。

UITextView Content Size

SO on the same question

這裏是修復它的代碼:

@implementation UITextView (Sizing) 

- (CGFloat)contentHeight { 
    if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) { 
     // This is the code for iOS 7. contentSize no longer returns the correct value, so 
     // we have to calculate it. 
     // 
     // This is partly borrowed from HPGrowingTextView, but I've replaced the 
     // magic fudge factors with the calculated values (having worked out where 
     // they came from) 

     CGRect frame = self.bounds; 

     // Take account of the padding added around the text. 

     UIEdgeInsets textContainerInsets = self.textContainerInset; 
     UIEdgeInsets contentInsets = self.contentInset; 

     CGFloat leftRightPadding = textContainerInsets.left + textContainerInsets.right + self.textContainer.lineFragmentPadding * 2; 
     leftRightPadding += contentInsets.left + contentInsets.right; 

     CGFloat topBottomPadding = textContainerInsets.top + textContainerInsets.bottom + contentInsets.top + contentInsets.bottom; 

     frame.size.width -= leftRightPadding; 
     frame.size.height -= topBottomPadding; 

     NSString* textToMeasure = self.text; 
     if(![textToMeasure isNotEmpty]) 
      textToMeasure = @"-"; 

     if ([textToMeasure hasSuffix:@"\n"]) { 
      textToMeasure = [NSString stringWithFormat:@"%@-", self.text]; 
     } 

     // NSString class method: boundingRectWithSize:options:attributes:context is 
     // available only on ios7.0 sdk. 

     NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; 
     [paragraphStyle setLineBreakMode:NSLineBreakByWordWrapping]; 

     NSDictionary* attributes = @{NSFontAttributeName : self.font, 
            NSParagraphStyleAttributeName : paragraphStyle}; 

     CGRect size = [textToMeasure boundingRectWithSize:CGSizeMake(CGRectGetWidth(frame), MAXFLOAT) 
                options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) 
               attributes:attributes 
                context:nil]; 

     CGFloat measuredHeight = ceilf(CGRectGetHeight(size) + topBottomPadding); 
     return measuredHeight; 
    } else { 
     return self.contentSize.height; 
    } 
} 

@end 

相反contentSize的,用這個來計算內容的高度。你也根本不需要動畫 - 我的計算很簡單,所以你應該確保你確實需要動畫。

4

我試圖在包裝一個UIView動畫塊的heightConstraint變化,沒有工作

這不是你如何動畫約束的變化。您可以通過改變約束,然後動畫布局自己的行爲,這樣做:

// change the text view constraint here 
[UIView animateWithDuration:duration animations:^{ 
    [self.textView layoutIfNeeded]; 
}]; 
+0

是的,但是如何在UITextView的autoLayout方法中自動發生約束更改時觸發動畫? –

+0

它不會自動發生。如果你的文本視圖正在改變大小,那是因爲你正在改變它的大小。所以如果你可以直接改變它的約束,你可以用動畫改變它的約束。 – matt

+0

在'layoutSubviews'裏面設置'layoutIfNeeded'的動畫看起來不太好。並且它也不能按預期工作。我想問的是,在'UITextView'的'layoutSubviews'中發生heightConstraint變化的情況下,我應該在哪裏爲'layoutIfNeeded'設置動畫? –

相關問題