54

iOS7 の UITextView は本当に奇妙です。入力してUITextViewの最後の行を入力すると、スクロールビューが本来のように一番下までスクロールせず、テキストが「クリップ」されます。clipsToBound プロパティを NO に設定しようとしましたが、それでもテキストがクリップされます。

「setContentOffset:animated」を呼び出したくありません。これは非常にハックなソリューションです。次に、カーソルがテキストビューの中央 (垂直方向) にあると、不要なスクロールが発生します。

これがスクリーンショットです。

ここに画像の説明を入力

どんな助けでも大歓迎です!

ありがとう!

4

11 に答える 11

21

ここで見つけた解決策は、UITextView を作成した後に 1 行の修正を追加することでした。

self.textview.layoutManager.allowsNonContiguousLayout = NO;

この 1 行で、iOS7 で構文を強調表示する UITextView ベースのコード エディターを作成する際に発生した3 つの問題が修正されました。

  1. 編集時にテキストを表示したままスクロールする (この投稿の問題)
  2. キーボードを閉じた後、UITextView がときどき飛び回る
  3. ビューをスクロールしようとすると、UITextView のランダム スクロール ジャンプが発生する

キーボードが表示/非表示になっているときに、UITextView全体のサイズを変更したことに注意してください。

于 2014-03-18T03:24:48.237 に答える
6

-textViewDidChangeSelection:次のように UITextViewDelegate からデリゲート メソッドを実装してみてください。

-(void)textViewDidChangeSelection:(UITextView *)textView {
    [textView scrollRangeToVisible:textView.selectedRange];
}
于 2014-01-01T20:13:53.073 に答える
2

davidisdk が選択した回答の修正版を次に示します。

- (void)textViewDidChange:(UITextView *)textView {
    NSRange selection = textView.selectedRange;

    if (selection.location + selection.length == [textView.text length]) {
        CGRect caretRect = [textView caretRectForPosition:textView.selectedTextRange.start];
        CGFloat overflow = caretRect.origin.y + caretRect.size.height - (textView.contentOffset.y + textView.bounds.size.height - textView.contentInset.bottom - textView.contentInset.top);

        if (overflow > 0.0f) {
            CGPoint offset = textView.contentOffset;
            offset.y += overflow + 7.0f;

            [UIView animateWithDuration:0.2f animations:^{
                [textView setContentOffset:offset];
            }];
        }
    } else {
        [textView scrollRangeToVisible:selection];
    }
}

textView のコンテンツ サイズが境界よりも大きく、カーソルが画面外にある場合 (キーボードを使用して矢印キーを押すなど)、textView が挿入されるテキストに合わせてアニメーション化されないというバグが発生していました。

于 2014-03-26T12:18:40.290 に答える
1

これは、iOS 7 の典型的な UITextView スクロール/キーボード関連の問題のすべてに対する決定的な答えです。クリーンで、読みやすく、使いやすく、維持しやすく、簡単に再利用できます。

基本的なトリック: コンテンツ インセットではなく、UITextView のサイズを変更するだけです。

これが実際の例です。Autolayout を使用する NIB/Storyboard ベースの UIViewController があり、UITextView が UIViewController のルート ビュー全体を埋めるのは当然のことです。そうでない場合は、必要に応じて textViewBottomSpaceConstraint を変更する方法を調整する必要があります。

方法:


次のプロパティを追加します。

@property (nonatomic, weak) IBOutlet NSLayoutConstraint *textViewBottomSpaceConstraint;
@property (nonatomic) CGFloat textViewBottomSpaceConstraintFromNIB;

Interface Builder で textViewBottomSpaceConstraint を接続します (忘れないでください! )

次にviewDidLoadで:

// Save the state of the UITextView's bottom constraint as set up in your NIB/Storyboard
self.textViewBottomSpaceConstraintFromNIB = self.textViewBottomSpaceConstraint.constant;

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShowNotification:)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillHideNotification:)
                                             name:UIKeyboardWillHideNotification
                                           object:nil];

これらのメソッドを追加して、キーボードのサイズ変更を処理します ( https://github.com/brennanMKE/Interfaces/tree/master/Keyboardingに感謝- これらのメソッドは brennan によるものです!):

- (void)keyboardWillShowNotification:(NSNotification *)notification {
    CGFloat height = [self getKeyboardHeight:notification forBeginning:TRUE];
    NSTimeInterval duration = [self getDuration:notification];
    UIViewAnimationOptions curve = [self getAnimationCurve:notification];

    [self keyboardWillShowWithHeight:height duration:duration curve:curve];
}

- (void)keyboardWillHideNotification:(NSNotification *)notification {
    CGFloat height = [self getKeyboardHeight:notification forBeginning:FALSE];
    NSTimeInterval duration = [self getDuration:notification];
    UIViewAnimationOptions curve = [self getAnimationCurve:notification];

    [self keyboardWillHideWithHeight:height duration:duration curve:curve];
}

- (NSTimeInterval)getDuration:(NSNotification *)notification {
    NSDictionary *info = [notification userInfo];

    NSTimeInterval duration;

    NSValue *durationValue = [info objectForKey:UIKeyboardAnimationDurationUserInfoKey];
    [durationValue getValue:&duration];

    return duration;
}

- (CGFloat)getKeyboardHeight:(NSNotification *)notification forBeginning:(BOOL)forBeginning {
    NSDictionary *info = [notification userInfo];

    CGFloat keyboardHeight;

    NSValue *boundsValue = nil;
    if (forBeginning) {
        boundsValue = [info valueForKey:UIKeyboardFrameBeginUserInfoKey];
    }
    else {
        boundsValue = [info valueForKey:UIKeyboardFrameEndUserInfoKey];
    }

    UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
    if (UIDeviceOrientationIsLandscape(orientation)) {
        keyboardHeight = [boundsValue CGRectValue].size.width;
    }
    else {
        keyboardHeight = [boundsValue CGRectValue].size.height;
    }

    return keyboardHeight;
}

- (UIViewAnimationOptions)getAnimationCurve:(NSNotification *)notification {
    UIViewAnimationCurve curve = [[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];

    switch (curve) {
        case UIViewAnimationCurveEaseInOut:
            return UIViewAnimationOptionCurveEaseInOut;
            break;
        case UIViewAnimationCurveEaseIn:
            return UIViewAnimationOptionCurveEaseIn;
            break;
        case UIViewAnimationCurveEaseOut:
            return UIViewAnimationOptionCurveEaseOut;
            break;
        case UIViewAnimationCurveLinear:
            return UIViewAnimationOptionCurveLinear;
            break;
    }

    return kNilOptions;
}

最後に、キーボード通知に反応するこれらのメソッドを追加し、UITextView のサイズを変更します。

- (void)keyboardWillShowWithHeight:(CGFloat)height duration:(CGFloat)duration curve:(UIViewAnimationOptions)curve
{
    CGFloat correctionMargin = 15; // you can experiment with this margin so the bottom text view line is not flush against the keyboard which doesn't look nice
    self.textViewBottomSpaceConstraint.constant = height + correctionMargin;

    [self.view setNeedsUpdateConstraints];

    [UIView animateWithDuration:duration delay:0 options:curve animations:^{
        [self.view layoutIfNeeded];
    } completion:^(BOOL finished) {

    }];
}

- (void)keyboardWillHideWithHeight:(CGFloat)height duration:(CGFloat)duration curve:(UIViewAnimationOptions)curve
{
    self.textViewBottomSpaceConstraint.constant = self.textViewBottomSpaceConstraintFromNIB;

    [self.view setNeedsUpdateConstraints];

    [UIView animateWithDuration:duration delay:0 options:curve animations:^{
        [self.view layoutIfNeeded];
    } completion:^(BOOL finished) {

    }];
}

また、これらのメソッドを追加して、ユーザーがクリックした場所に自動的にスクロールします

- (void)textViewDidBeginEditing:(UITextView *)textView
{
    [textView scrollRangeToVisible:textView.selectedRange];
}

- (void)textViewDidChangeSelection:(UITextView *)textView
{
    [textView scrollRangeToVisible:textView.selectedRange];
}
于 2014-05-09T09:40:55.927 に答える
0

この行により、テキストの最後の行が表示されなくなります。

textView.scrollEnabled = false

これを削除してみて、何が起こるか見てみましょう...

于 2016-02-13T21:01:21.833 に答える
0
textView.contentInset = UIEdgeInsetsMake(0.0, 0.0, 10.0, 0.0);

これはあなたの問題にも対処します

于 2013-12-19T09:32:44.720 に答える
0

StoryBoard を使用している場合、AutoLayout をオンのままにして (デフォルトで)、UITextView の上下の制約を設定しなかった場合にも、この動作が発生する可能性があります。File Inspector をチェックして、AutoLayout の状態を確認してください...

于 2014-03-11T02:02:15.273 に答える
-1
   textView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

これで問題は解決しました

于 2013-12-13T06:28:02.630 に答える