web-dev-qa-db-ja.com

UITextViewはロード時に上部にスクロールされません

UITextViewを満たさないテキストがある場合、意図したとおりに動作して上部にスクロールします。画面に収まらないほど多くのテキストがある場合、UITextViewは上部ではなくテキストの中央にスクロールされます。

関連する可能性のある詳細を次に示します。

ViewDidLoadで、UITextViewの上部と下部にパディングを追加します。

self.mainTextView.textContainerInset = UIEdgeInsetsMake(90, 0, 70, 0);

UITextViewは自動レイアウトを使用して、画面の上下左右(IBで行われます)から20pxを固定し、さまざまな画面サイズと向きを可能にします。

ロードしたら、指でスクロールできます。

編集私は、自動レイアウト制約を削除してから幅を修正するだけで問題が解決するように見えましたが、その画面幅のみです。

47

UITextViewはUIScrollViewのサブクラスであるため、そのメソッドを使用できます。あなたがしたいことは、それが一番上にスクロールされることを確認するだけであるなら、テキストが追加されるところはどこでも試してください:

[self.mainTextView setContentOffset:CGPointZero animated:NO];

編集:あらゆる種類のスクロールビューでの自動レイアウトは、途方もなく速くなります。固定幅を設定することで解決することは驚くことではありません。 -viewDidLayoutSubviewsで機能しない場合、それは奇妙です。レイアウト制約を手動で設定すると機能する場合があります。まず、IBで制約を作成します。

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewWidthConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewHeightConstraint;

その後、ViewController

    -(void)updateViewConstraints {
            self.textViewWidthConstraint.constant = self.view.frame.size.width - 40.0f;
            self.textViewHeightConstraint.constant = self.view.frame.size.height - 40.0f;
            [super updateViewConstraints];
        }

-viewDidLayoutSubviewsのContentOffsetを設定する必要がある場合があります。

(もう1つの方法は、textViewとそのsuperViewの間に「-40」の定数を使用して「等しい」幅と「等しい」高さのレイアウト制約を作成することです。定数がゼロの場合のみ「等しい」 、そうでない場合は定数によって調整されます。ただし、この制約は両方のビューを制約するビューにしか追加できないため、IBでこれを行うことはできません。

私がこれをしなければならない場合、AutoLayoutのポイントは何ですか?私はAutoLayoutを詳細に研究しましたが、それは素晴らしい質問です。

18
Mike Sand

view Controllerクラスに次の関数を追加します...

Swift

override func viewDidLayoutSubviews() {
    self.mainTextView.setContentOffset(.zero, animated: false)
}

Swift 2.1

override func viewDidLayoutSubviews() {
    self.mainTextView.setContentOffset(CGPointZero, animated: false)
}

目的C

- (void)viewDidLayoutSubviews {
    [self.mainTextView setContentOffset:CGPointZero animated:NO];
}
115

スイフト

self.textView.scrollRangeToVisible(NSMakeRange(0, 0))

Objective-C

[self.textView scrollRangeToVisible:(NSMakeRange(0, 0))];
11
AlessandroDP

私は同じ問題を抱えていました!推奨される制約にリセットして、配置するだけ(yオフセット)

@IBOutlet weak var textContent: UITextView!

    override func viewDidLoad() {
        textContent.scrollsToTop = true
        var contentHeight = textContent.contentSize.height
        var offSet = textContent.contentOffset.x
        var contentOffset = contentHeight - offSet
        textContent.contentOffset = CGPointMake(0, -contentOffset)
    }
9
Ruso

IOS9以降では、viewWillAppear:のtextviewもCGRect(0,0,1000,1000)に付属しています。これが機能するには、viewWillAppearで呼び出す必要があります。

[self.view setNeedsLayout];
[self.view layoutIfNeeded];
// * Your code here

その後、textviewには正しいCGRectデータが含まれ、必要なスクロール操作を実行できます。

6
iPav

ViewDidLayoutSubviewsおよびviewWillLayoutSubviewsにコードを配置する際の問題は、これらのメソッドが頻繁に呼び出されることです(デバイスの回転中、ビューのサイズ変更中など)。テキストビューから何かを読んでいて、デバイスを回転させると、表示しているコンテンツの一部が画面に表示されたままになることが期待されます。トップに戻るとは思わないでしょう。コンテンツを一番上にスクロールする代わりに、テキストビューのscrollEnabledプロパティをNO(false)に設定したままにして、viewDidAppearで再び有効にしてください。

2
Jovan Stankovic

制約を台無しにしたくない場合:

override func updateViewConstraints() {
    super.updateViewConstraints()
}

override func viewDidLayoutSubviews() {
    self.textLabel.setContentOffset(CGPointZero, animated: false)
}
1
Gustavo Severo

私にとってこれは別の方法で動作します。上記のすべてを試しましたが、func viewWillAppear(_ animated: Bool)で動作するものはありませんでした。最終的にはtextViewが上にスクロールし、func viewDidAppear(_ animated: Bool)では画面が表示された後にスクロールします。

以下は私のために働いたが、キーボードの上下にいくつかの制約関連の問題がありました。

override func viewDidLayoutSubviews() {
    self.textView.setContentOffset(.zero, animated: false)
}

以下は期待どおりに機能しました:

override func viewDidLoad() {
    super.viewDidLoad()

    self.textView.scrollsToTop = true
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    self.view.layoutIfNeeded()
    self.textView.setContentOffset(.zero, animated: false)
}
1
Swapnil Dhotre

これは興味深いバグです。私たちのプロジェクトでは、これはiPhone 5-サイズの画面。 textview contentOffsetは、View Controllerのライフサイクルのある時点で変化するようです。 viewDidLoadおよびviewWillAppearでは、textviewのcontentOffset0,0、およびviewDidAppearによって変更されます。 viewWillLayoutSubviewsで発生していることがわかります。制約が正しく設定されているようです。

これにより、必要でない限り、スクロールメソッドを呼び出さないようになります。

if textView.contentOffset.y > 0 {
    textView.contentOffset = CGPoint(x: 0, y: 0)
    // Or use scrollRectToVisible, scrollRangeToVisible, etc.
}
1
Evan R

スイフト

override func viewDidLoad() {
    super.viewDidLoad()  
    textView.isScrollEnabled = false  
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    textView.isScrollEnabled = true
}

A.View Controllerがミスを犯していないか、何か間違ったことをしていないため、B、誤ってスクロールされたテキストを持つView Controllerが複数ある場合、View Controllerのコードでこの問題を処理するのはひどいアイデアのようです表示すると、冗長なコードになります。解決策は、テキストビュークラスに存在するコードを記述することです。私のソリューションは、UITextViewのカスタムクラスを選択してこのクラスを使用するInterface Builderで動作します。

import Foundation
import UIKit

class TopTextView: UITextView {
    var scrolled = false

    override func layoutSubviews() {
        super.layoutSubviews()
        if scrolled { return }
        setContentOffset(.zero, animated: false)
        scrolled = true
    }
}

これは私のために働いた。 ViewControllerの子としてUITextViewではなく、UITextViewをそのビューの子として持つ子ビューを持つView Controllerがあります。テキストビューが上部または下部のバーの下にある場合、これがどのように機能するかはわかりませんが、エッジインセットに触れないため、これは機能するはずです。

0
David Rector