253

表示できるビューを UIStackView に追加したとしましょうUIStackView。スクロールを行うにはどうすればよいですか?

4

21 に答える 21

54

Apple の Auto Layout Guide には、Working with Scroll Views に関するセクション全体が含まれています。関連するスニペット:

  1. コンテンツ ビューの上端、下端、リーディング エッジ、およびトレーリング エッジを、スクロール ビューの対応するエッジに固定します。コンテンツ ビューは、スクロール ビューのコンテンツ領域を定義するようになりました。
  2. (オプション) 水平スクロールを無効にするには、コンテンツ ビューの幅をスクロール ビューの幅と同じに設定します。コンテンツ ビューがスクロール ビューを水平方向に埋めるようになりました。
  3. (オプション) 垂直スクロールを無効にするには、コンテンツ ビューの高さをスクロール ビューの高さと同じに設定します。コンテンツ ビューがスクロール ビューを水平方向に埋めるようになりました。

さらに:

レイアウトでは、コンテンツ ビューのサイズを完全に定義する必要があります (手順 5 と 6 で定義されている場合を除く)。…コンテンツビューがスクロールビューよりも高い場合、スクロールビューは垂直スクロールを有効にします。コンテンツ ビューがスクロール ビューよりも広い場合、スクロール ビューは水平スクロールを有効にします。

要約すると、スクロール ビューのコンテンツ ビュー (この場合はスタック ビュー) を端に固定し幅や高さを制限する必要があります。つまり、スタック ビューのコンテンツは、スクロールが必要な方向に (直接的または間接的に) 制限する必要があります。これは、たとえば、垂直方向にスクロールするスタック ビュー内の各ビューに高さの制限を追加することを意味する場合があります。以下は、スタック ビューを含むスクロール ビューの垂直スクロールを許可する方法の例です。

// Pin the edges of the stack view to the edges of the scroll view that contains it
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true

// Set the width of the stack view to the width of the scroll view for vertical scrolling
stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
于 2016-09-12T17:20:55.173 に答える
18

2020年最新。

100% ストーリーボードまたは 100% コード。

この例は垂直です。


最も簡単な説明は次のとおりです。

  1. 空白のフルスクリーン シーンを用意する

  2. スクロール ビューを追加します。スクロール ビューからベース ビューにControl キーを押しながらドラッグし、すべてゼロの left-right-top-bottom を追加します。

  3. スクロール ビューにスタック ビューを追加します。スタック ビューからスクロール ビューにControl キーを押しながらドラッグし、すべてゼロの left-right-top-bottom を追加します。

  4. スタック ビュー内に 2 つまたは 3 つのラベルを配置します。

わかりやすくするために、ラベルの背景色を赤にします。ラベルの高さを 100 に設定します。

  1. 各 UILabelのを設定します。

    驚くべきことに、スタック ビューではなくUILabelスクロール ビューにコントロール ドラッグし、等幅を選択します。

繰り返す:

UILabel から UILabel の親へのドラッグを制御しないでください。祖父母に移動してください。(つまり、スタック ビューには移動せず、スクロール ビューまで移動します。)

それはとても簡単です。それが秘密です。

秘密のヒント - Apple のバグ:

1点だけじゃダメ!いくつかのラベルを追加して、デモを機能させます。

あなたは終わった。

ヒント:すべての新しいアイテムに高さを追加する必要があります。スクロール スタック ビュー内のすべてのアイテムは、固有のサイズ (ラベルなど) を持つか、明示的な高さの制約を追加する必要があります。


別のアプローチ:

上記のアプローチを要約すると、驚くべきことに、ラベルの幅を (スタック ビューではなく) スクロール ビューの幅に設定します。

ここに別のアプローチがあります...

スタック ビューからスクロール ビューにドラッグし、「幅が等しい」という制約を追加します。すでに left-right を固定しているので、これは奇妙に思えますが、それがあなたのやり方です。どんなに奇妙に見えても、それが秘密です。

したがって、次の 2 つのオプションがあります。

  1. 驚くべきことに、スタック ビューの各項目の幅を、スクロール ビューの親の親 (スタック ビューの親ではなく) の幅に設定します。

また

  1. 驚くべきことに、スタックビューの左端と右端がスクロールビューに固定されていて、スタックビューの「幅が等しい」をスクロールビューに設定します。

明確にするために、これらの方法のいずれかを実行し、両方を実行しないでください。

于 2016-12-05T15:18:35.917 に答える
18

ここでの上位投票の回答の制約は私にとってはうまくいきました。ストーリーボードで作成したように、以下の制約の画像を貼り付けました。

他の人が知っておくべき2つの問題に遭遇しました:

  1. 受け入れられた回答にあるものと同様の制約を追加した後、赤い autolayout error が発生しますNeed constraints for: X position or width。これは、スタック ビューのサブビューとして UILabel を追加することで解決されました。

    サブビューをプログラムで追加しているので、もともとストーリーボードにはサブビューがありませんでした。自動レイアウト エラーを取り除くには、サブビューをストーリーボードに追加し、実際のサブビューと制約を追加する前にロード時に削除します。

  2. 私はもともとUIButtonsUIStackViewに追加しようとしました。ボタンとビューはロードされますが、スクロール ビューはスクロールしませんUILabelsこれは、ボタンの代わりにスタック ビューに追加することで解決されました。同じ制約を使用すると、UILabels を持つこのビュー階層はスクロールしますが、UIButtons はスクロールしません。

    UIButtonsには IntrinsicContentSize (スタック ビューで使用される) があるように見えるため、この問題に混乱しています。ボタンが機能しない理由を誰かが知っている場合は、その理由を知りたいです。

参考までに、ビューの階層と制約を次に示します。

スクロール ビューでのスタック ビューの制約[1]

于 2016-04-22T18:24:15.530 に答える
16

Eik が言うように、UIStackView一緒UIScrollViewにうまくプレイするには、こちらを参照してください。

重要なのは、 がUIStackViewさまざまなコンテンツの可変の高さ/幅を処理し、UIScrollViewそのコンテンツのスクロール/バウンスを適切に行うことです。

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    scrollView.contentSize = CGSize(width: stackView.frame.width, height: stackView.frame.height)       
}
于 2015-07-29T05:05:01.520 に答える
6

これをに追加するだけviewdidloadです:

let insets = UIEdgeInsetsMake(20.0, 0.0, 0.0, 0.0)
scrollVIew.contentInset = insets
scrollVIew.scrollIndicatorInsets = insets

ソース: https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/LayoutUsingStackViews.html

于 2015-12-15T13:35:28.370 に答える
2

macOS Catalyst に新しいパースペクティブを追加します。macOS アプリはウィンドウのサイズ変更をサポートしているUIStackViewため、スクロールできない状態からスクロール可能な状態に、またはその逆に遷移する可能性があります。ここには 2 つの微妙な点があります。

  • UIStackView可能な限りすべての領域に適合するように設計されています。
  • 移行中、 はUIScrollView、ナビゲーション バー (または macOS アプリの場合はツールバー) の下に新しく獲得/喪失した領域を考慮して、境界のサイズを変更しようとします。

残念ながら、これは無限ループを作成します。UIScrollViewとそのについてはあまり詳しくありませんadjustedContentInsetが、そのメソッドのログから、layoutSubviews次の動作が見られます。

  • 1 つは、ウィンドウを拡大します。
  • UIScrollViewその境界を縮小しようとします (ツールバーの下の領域は必要ないため)。
  • UIStackView続きます。
  • どういうわけかUIScrollView満足できず、より大きな境界に戻すことにしました。ログから見ているのはUIScrollView.bounds.height == UIStackView.bounds.height.
  • UIStackView続きます。
  • その後、ステップ 2 にループします。

次の 2 つの手順で問題が解決するようです。

  • に合わせUIStackView.topますUIScrollView.topMargin
  • に設定contentInsetAdjustmentBehavior.neverます。

ここでは、垂直方向に成長する垂直方向にスクロール可能なビューに関心がありますUIStackView。水平ペアの場合は、それに応じてコードを変更します。

それが将来誰にも役立つことを願っています。インターネット上でこれに言及している人を見つけることができず、何が起こったのかを理解するのにかなりの時間がかかりました.

于 2020-05-18T00:44:11.420 に答える
2

ScrollableStackViewを試すことができます: https://github.com/gurhub/ScrollableStackView

Objective-C および Swift 互換のライブラリです。CocoaPodsから入手できます。

サンプルコード (Swift)

import ScrollableStackView

var scrollable = ScrollableStackView(frame: view.frame)
view.addSubview(scrollable)

// add your views with 
let rectangle = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 55))
rectangle.backgroundColor = UIColor.blue
scrollable.stackView.addArrangedSubview(rectangle)
// ...

サンプルコード (Objective-C)

@import ScrollableStackView

ScrollableStackView *scrollable = [[ScrollableStackView alloc] initWithFrame:self.view.frame];
scrollable.stackView.distribution = UIStackViewDistributionFillProportionally;
scrollable.stackView.alignment = UIStackViewAlignmentCenter;
scrollable.stackView.axis = UILayoutConstraintAxisVertical;
[self.view addSubview:scrollable];

UIView *rectangle = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 55)];
[rectangle setBackgroundColor:[UIColor blueColor]];

// add your views with
[scrollable.stackView addArrangedSubview:rectangle]; 
// ...
于 2016-12-20T19:52:21.097 に答える
0

スタック ビューをスクロール ビューの垂直方向の中央に配置するという制約がある場合は、それを削除してください。

于 2016-10-10T15:57:07.420 に答える
0

私の場合、stackView 内のビューの数は可変で、アイテムを中央に配置したいと考えていました。たとえば、stackView の 1 つのビューで、このビューを画面の中央に配置し、すべてのビューが画面内に収まらない場合は、ビューをスクロール可能にしたいと考えました。

これが私の見解の階層です。

ここに画像の説明を入力

そこで、ボタンに固定幅を設定してから、stackViewに次のように設定します。

  • ボタンと同じ固定幅ですが、優先度は 650 です。
  • X 中心を containerView に揃えます
  • 末尾 >= 0 および先頭 >= 0 から containerView
  • 下部と上部のスペースを containerView に

ここに画像の説明を入力

containerViewの場合:

  • トレーリング、リーディング、ボトム、トップ、等高、等幅 (優先度 250) スーパービューへ
  • 高さ固定

ここに画像の説明を入力

scrollViewの場合:

  • トレーリング、リーディング、ボトム、トップからスーパービューへ

scrollView は、先頭と末尾の制約を持つビューにも埋め込まれています。

ここに画像の説明を入力

そして、これにアプローチするために使用したコードについて:

for index in 0...array.count - 1 {

      if index == 0 {
          firstButton.setTitle(title, for: .normal)
      } else {
          let button = UIButton()
          button.setTitle(title, for: .normal)
          stackView.addArrangedSubview(button)
          stackView.setNeedsLayout()
      }
}
containerView.layoutIfNeeded()
        
stackView.distribution = .fillEqually
stackView.spacing = 10
stackView.alignment = .fill
于 2021-03-25T16:35:54.283 に答える
0

縦軸スクロールと横軸スクロールの両方で動作するサンプル プロジェクトを作成しました。

https://gitlab.com/muhasturk/bmh.example.stackinsidescroll.ios

于 2021-03-31T14:25:42.173 に答える