web-dev-qa-db-ja.com

Swift UIScrollView-垂直スクロールのみの正しい実装

事前に、私はiOSプログラミングの初心者であると言って謝罪します。

表示するコンテンツが画面の高さを超えているため、UIScrollViewを使用します。したがって、水平スクロールではなく、垂直スクロールのみが必要です。

ストーリーボードを使用して、AutoLayoutでビューを描画しています。

これは私のUIViewControllerUIScrollViewのスクリーンショットです:

enter image description hereenter image description here

次に、ラベルをそのような大きなテキストに変更します

override func viewDidLoad() {
    super.viewDidLoad()

    self.label1Label.text = "Seize jours après la chute du président Blaise Compaoré, le Burkina Faso a un nouveau chef d'EtatA l'issue d'ultimes tractions, civils et militaires se sont accordés, lundi 17 novembre, sur le nom du diplomate Michel KafandoSeize jours après la chute du président Blaise Compaoré, le Burkina Faso a un nouveau chef d'EtatA l'issue d'ultimes tractions, civils et militaires se sont accordés, lundi 17 novembre, sur le nom du diplomate Michel Kafando"
    self.label1Label.numberOfLines = 0
    self.label1Label.sizeToFit()

私の問題は、contentViewの幅(UIScrollView内)を手動で設定しないと、スクロールが垂直ではなく水平になることです。 (下のスクリーンショットをご覧ください):

enter image description here

私は多くのGoogleの投稿で見たようにcontentSizeを設定しようとしましたが、成功しませんでした:

self.scrollView.contentSize = CGSizeMake(400.0, 600.0)

Contentviewの幅を手動で設定した場合(i.e : 320pts)、スクロールは垂直(GOOD)になりますが、iPhoneのサイズによっては、次のスクリーンショットに示すように画面の幅全体をカバーしません。

enter image description here

問題は、自動レイアウト制約を尊重するUIScrollViewを持つためにcontentViewを使用する正しい実装は何ですか(full screen : 0top - 0bottom - 0left - 0right)および垂直方向のみのスクロール。

ご協力ありがとうございました!

15
fabdarice

Mike Woelmerが、Atomic ObjectブログのInterface Builderでこれを正しく行う方法を示しています。

http://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/

また、githubには独自のコードのみ(ストーリーボードの実装はありません)があります。

https://github.com/nadthevlad/AutolayotScrollview

コンテンツまたはビューの高さまたは幅を設定する必要はありません。代わりに、Autolayoutsピンと制約を使用して、スクロールビューの動作を設定します。

  1. UIScrollView * scrollViewを作成します。

  2. 1つのUIView * contentViewを作成して、残りのビュー要素を配置します。

    [self.view addSubview:scrollView];
    [scrollView addSubview:contentView];
    [contentView addSubview:_label1];
    [contentView addSubview:_label2];
    [contentView addSubview:_label3];
    [contentView addSubview:_label4];
    [contentView addSubview:_label5];
    [contentView addSubview:_label6];
    
  3. ScrollViewの4つのエッジをself.viewの4つのエッジに固定します

  4. ContentViewの上端と下端をscrollViewの上端と下端に固定します。

  5. これは難しい部分です。水平方向のサイズを設定するには、contentViewのリーディング(右)およびトレーリング(左)エッジをscrollViewではなくリーディングおよびトレーリングエッジself.viewに固定する必要があります。 contenViewはscrollViewのサブビューですが、その水平方向の制約はscrollViewの外部に到達し、self.viewに接続します。

  6. 他のビュー要素を通常どおりcontentViewに固定します。

38
NadtheVlad

UIScrollViewを一方向にのみスクロールできるようにする秘Theは、制限されたディメンションのUIScrollViewのコンテンツサイズを、同じディメンションのUIScrollViewのフレームのサイズと同じにすることです。したがって、この場合、scrollview.contentSize.widthscrollview.frame.size.widthと等しくなければなりません。

それを念頭に置いて、次のことを試してください。

  1. this answer で説明されているのと同じ方法で制約を設定してください。

  2. View Controllerに次のコードを追加します。

    override func viewWillLayoutSubviews()
    {
        super.viewWillLayoutSubviews();
        self.scrollView.contentSize.height = 3000; // Or whatever you want it to be.
    }
    

個人的に、私は実際には自動レイアウトのファンではありません。自動レイアウトなしでこれを試すことに興味がある場合-すなわち。制約の代わりにコードを使用するだけで、View Controllerのビューの自動レイアウトをオフにし、viewWillLayoutSubviewsメソッドを次のように変更できます。

override func viewWillLayoutSubviews()
{
    super.viewWillLayoutSubviews();

    self.scrollView.frame = self.view.bounds; // Instead of using auto layout
    self.scrollView.contentSize.height = 3000; // Or whatever you want it to be.
}
22
gavdotnet

これは、制約のあるストーリーボードから垂直にスクロールするために常に行う方法です:

ビューコントローラーを1回ドラッグ

制約L = 0、T = 0、T = 0、およびB = 0を使用して、コントローラーのメインビューでスクロールビューをスーパービュー(コントローラーのメインビュー)に2ドラッグします。

UIVIewをスクロールビューにドラッグして、スーパービュー(スクロールビュー)に制約L-0、T = 0、T = 0、B = 0のコンテンツビューとして機能させる

  • スクロールビューのコンテンツサイズを設定する時間です。これは、水平方向と垂直方向の両方のスクロールを次のように制御します。

4-水平スクロールを停止するために、コンテンツビューを制約付きのスクロールビューと同じ幅にします。

5-コンテンツビューの高さをコントローラーのビューの高さと等しくする、これは一時で、スクロール可能なコンテンツで埋めます

終了するまで、コンテンツビューに6つのコントロールを追加します。

7-最も重要なのは、コンテンツビューの高さのポイント5で作成した制約を削除し、代わりにコンテンツビューの下部のコントロールから制約を作成して、下部に配置することです。これは、コンテンツビューの高さを最初のコントロールから最初のコントロールまで、最後のコントロールまで下にするのに役立ちます(すべてこのステップに依存します)。

8-ちょうど実行し、結果は期待どおりでなければなりません、そうでなければ私に知らせてください。

お役に立てれば!

4
IsPha

通常はScrollViewを定義し、通常はScrollViewのプロパティを制限できます。

        let scrollView = UIScrollView()
    scrollView.translatesAutoresizingMaskIntoConstraints = false
    scrollView.backgroundColor = .white
    self.view.addSubview(scrollView)

    scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0.0).isActive = true
    scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0.0).isActive = true
    scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0.0).isActive = true
    scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0.0).isActive = true

しかし、トリックは、画面よりも広いラベル(または他のビュー)を定義する方法にあります。代わりに

myLabel.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: -10.0).isActive = true

あなたが使用する必要があります

myLabel.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -10.0).isActive = true

この2行目は、そのビューが水平スクロールを引き起こさないようにします。すべてのサブビューでこれを行うと、水平にスクロールしません。 (計画どおり垂直にスクロールします。)

また、UIScrollviewが垂直にスクロールするように、最後のサブビューに下部の制約を設定することを忘れないでください。

labelX.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -10.0).isActive = true
1
Vette

@NadtheVladのおかげで、ついに光を見ました。さらにいじって、contentViewをscrollViewのTop、Bottom、およびWidthに固定する必要があることを教えてくれました。 self.viewを参照する必要はありません。

EasyPeasy の場合、これは単純に:

scrollView <- Edges()
contentView <- [Top(), Bottom(), Width().like(scrollView)]
0
jazzgil

Objective-Cではありますが、水平/垂直スクロールビューにのみこの実装を使用します。何か不明な点がある場合は、ロジックの説明を試みます。

//Getting iDevice's screen width
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;

//Setting the right content size - only height is being calculated depenging on content.
CGSize contentSize = CGSizeMake(screenWidth, HEIGHT_OF_YOUR_CONTENT);
self.scrollView.contentSize = contentSize;

スクロールビューのcontentSizeプロパティの幅は、デバイスの画面の実際の幅にアタッチされているため、スクロールビューは垂直方向にのみスクロールします。

0
Richard Topchiy