web-dev-qa-db-ja.com

UIScrollView contentSizeが機能しない

UIScrollViewをペン先のviewに入れ、IBOutletプロパティにリンクしました。

さて、viewDidLoadメソッドでこれを行うと、contentSizeには何の効果もないようです:

self.sv.backgroundColor = [UIColor yellowColor]; // this works
CGSize size =  CGSizeMake(1000.0, 1000.0); 
[self.sv setContentSize:size]; // this does not

contentSizeがフレームと同じであるかのように動作します。どうしたの?これは、AutoLayoutをオフにしたときに機能し始めました。どうして?

56
cannyboy

同じ問題がありました。 UIScrollViewの自動レイアウトが台無しです。

回避策:UIScrollViewのすべてを別のUIViewに入れ、そのUIViewUIScrollViewの唯一の子として置きます。その後、自動レイアウトを使用できます。

終わり近くのものが乱れた場合(UIScrollViewがスクロールする方向の最後)、最後の制約を変更して、可能な限り優先度を低くします。

79
yuf

私は、viewWillLayoutSubviewsを使用してscrollViewのcontentSizeを更新しましたが、うまくいきました。

- (void)viewDidLayoutSubviews
{
  [self.bgScrollView setContentSize:CGSizeMake(320, self.view.frame.size.height* 1.5)];
}

Apple Doc

-(void)viewDidLayoutSubviews

ビューがサブビューをレイアウトしたことをView Controllerに通知するために呼び出されます。

ディスカッション

ビューコントローラーのビューの境界が変更されると、ビューはそのサブビューの位置を調整し、システムはこのメソッドを呼び出します。ただし、呼び出されるこのメソッドは、ビューのサブビューの個々のレイアウトが調整されたことを示すものではありません。各サブビューは、独自のレイアウトを調整します。

ビューがサブビューをレイアウトした後、View Controllerはこのメソッドをオーバーライドして変更を加えることができます。このメソッドのデフォルト実装は何もしません。

68
HDdeveloper

最も簡単でクリーンな方法は、viewDidAppearでcontentSizeを設定して、自動レイアウトの効果を無効にすることです。これには、ランダムビューの追加は含まれません。ただし、実装が機能するためにロード順序に依存することは、最善のアイデアではない場合があります。

21
Jlam

ここには2つの問題があります。 (1)viewDidLoadが早すぎます。レイアウトが完了するまで待つ必要があります。 (2)ペン先からのスクロールビューで自動レイアウトを使用する場合は、制約を使用してcontentSizeのサイズを完全に記述する必要があります(その後、contentSizeを設定しませんまたは、コードで設定する場合は、スクロールビューのサブビューの制約がcontentSizeを指定しないように防止する必要があります。後者を行いたいようです。これを行うには、スクロールビューの唯一のトップレベルのサブビューとして機能するUIViewが必要です。コードでは、それをnotに設定し、autoresizingMaskを有効にする自動レイアウトを使用する必要があります他の外部制約を削除します。ここで、その方法の例を示します。

https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/ch20p573scrollViewAutoLayout/ch20p573scrollViewAutoLayout/ViewController.m

ただし、制約を完全に使用する方法を示す次の例にも注意してください。insteadof contentSize

14
matt

Interface Builder内のUIScrollViewsでAutoLayoutを使用する非常に簡単な方法:

ステップ1:UIScrollViewを作成する

ステップ2:スクロールビューの子であるUIViewを作成します:

-UIScrollView
---UIView
-----Your other content

(これをcontentViewと呼びます)。

ステップ3:サイズインスペクターで、このビューに高さと幅(320x700など)を指定します。

ステップ4(AutoLayoutを使用):contentViewからそのスーパービュー(UIScrollView)に明確な制約を作成します:4つのエッジ(上、前、後、下を接続します) )、スクロールしたい幅と高さを定義します。

例:スクロールビューが画面全体に広がる場合、コンテンツビューに[デバイス幅]の幅と600の高さを指定できます。次に、UIScrollViewのコンテンツサイズを一致するように設定します。

または:

ステップ4(AutoLayoutを使用しない): IBを使用して、これらの新しいコントロールの両方をView Controllerに接続します(各コントロールからView Controllerの.h @implementationまでCtrlキーを押しながらドラッグします)。それぞれがそれぞれscrollViewcontentViewと呼ばれると仮定しましょう。次のようになります。

@interface YourViewController : UIViewController

@property (strong, nonatomic) IBOutlet UIScrollView *scrollView;
@property (strong, nonatomic) IBOutlet UIView *contentView;

@end

ステップ5(AutoLayoutを使用しない): View Controllerの.hファイルで、次のメソッドを追加(実際にはオーバーライド)します。

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    self.scrollView.contentSize = self.contentView.frame.size;
}
14
brandonscript

このコードを使用してください。 ScrollView setContentSizeは、メインスレッドで非同期と呼ばれる必要があります。

迅速:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    DispatchQueue.main.async {
        var contentRect = CGRect.zero

        for view in self.scrollView.subviews {
           contentRect = contentRect.union(view.frame)
        }

        self.scrollView.contentSize = contentRect.size
    }
}

目標C:

 - (void)viewDidLayoutSubviews {
     [super viewDidLayoutSubviews];

     dispatch_async(dispatch_get_main_queue(), ^ {
                        CGRect contentRect = CGRectZero;

                        for(UIView *view in scrollView.subviews)
                           contentRect = CGRectUnion(contentRect,view.frame);

                           scrollView.contentSize = contentRect.size;
                       });
}
12

このコード行を* .mファイルに使用できます

- (void)viewDidLoad{
   [scroll setContentSize:CGSizeMake(320, 800)]   ;
   [scroll setScrollEnabled:TRUE];
   [scroll setShowsVerticalScrollIndicator:NO];
   [scroll setShowsHorizontalScrollIndicator:YES];
}    

そのためには、UIScrollViewのIBOutletプロパティを* .hファイルに次のように取り込む必要があります。

IBOutlet UIScrollView *scroll;

これをStoryboardから接続します。

または、

このメソッドを* .mファイルに使用できます。

-(void)viewDidLayoutSubviews 
{
  [scroll setContentSize:CGSizeMake(320, self.view.frame.size.height* 1.5)];
   // this will pick height automatically from device's height and multiply it with 1.5  
}

この両方のソリューションは、xcode-5、xcode-6、xcode-6.1、xcode-6.2で私のために機能します

5
imti

ContentSizeをviewDidAppearに設定することが重要です。

しかし、3.5インチ画面と4インチ画面で動作するもののバリエーションもありました。 4インチの画面は機能しましたが、古い画面は機能しません。 iOS 7とBizarreはどちらも控えめな表現です!

3
PostCodeism

AutoLayoutを使用している場合、contentSizeUIScrollViewを設定する非常に簡単な方法は、次のようなものを追加することです。

CGFloat contentWidth = YOUR_CONTENT_WIDTH;

NSLayoutConstraint *constraintWidth = 
 [NSLayoutConstraint constraintWithItem:self.scrollView 
                              attribute:NSLayoutAttributeTrailing 
                              relatedBy:NSLayoutRelationEqual 
                                 toItem:self.scrollView 
                              attribute:NSLayoutAttributeLeading 
                             multiplier:1 
                               constant:contentWidth];

[self.scrollView addConstraint:constraintWidth];
1
korovyev

以前はプログラムでuiscrollviewを設定していましたが、次のすばらしいチュートリアルを見て、uiscrollviewとuiviewを機能させる方法を順を追って見てきました。 https://www.youtube.com/watch?v=PgeNPRBrB18 =

ビデオを見た後、きっとあなたはInterface Builderを好きになるでしょう。

投票する

1
oabarca

ラベルの動的な高さがビューの高さを超えている場合でもスクロールしない

上記の正しいとマークされたyufの答えを実行しました(スクロールビューにコンテンツビューを追加し、コンテンツビューからスクロールビューまでの幅を先頭、末尾、上下、および等しい幅に設定しました)が、それでも私のビューは内部コントロールの高さがスクロールビューの高さを超えたときにスクロールしない。

enter image description here

コンテンツビュー内には、画像とその下に3つのラベルがあります。各ラベルは、その中に含まれるテキストの量に応じて、独自の高さを調整します(これを実現するために、ワードラップとnumberoflines = 0に設定されます)。

私が抱えていた問題は、スクロールビュー/メインビューの高さを超えると、コンテンツビューの高さがラベルの動的な高さで調整されないことでした。

これを修正するには、ボトムラベルとコンテンツビューの間にBottom Space to Container制約を設定し、値を40に設定する必要があると言いました下部のマージン)。これは、私のコンテンツビューが最後のラベルの下部とそれ自体の間にスペースがあるように高さを調整し、完全にスクロールすることを意味します

わーい!

1
Guy Lowe

制約に基づいた自動レイアウトを機能させることはできませんでした。私のビューはすでにサブクラスのUIScrollViewであったため、setContentView:をオーバーライドし、高さゼロのsetContentSize:メッセージの自動レイアウトを無視することで解決しました。

@interface MyView : UIScrollView {}
@end

@implementation MyView
- (void)setContentSize:(CGSize)aSize {
    if (aSize.height > 0)
        [super setContentSize:aSize];
}
@end
1
Conor

これを試してみてください...
UIViewの場合と同じようにすべての制約を追加します(ストーリーボードのViewControlerのscreenShotを参照してください
enter image description here
今、トリックが始まります。最後のオブジェクトを選択し、その下の制約を選択します。 (上記のscreenShot、Instagramボタンの下部の制約(黄色の線)を参照)および以下のスクリーンショットのようにサイズインスペクターの定数を変更します。

enter image description here

constant = 8が必要ですが、要件に応じて変更できます。この定数は、そのオレンジ色のボタンの下部とscrollViewの間のスペースです。

[〜#〜] edit [〜#〜]

ビューの階層を確認してください。

0)ViewController.view(optional
1)UIScrollView
2)UIView(「contentView」に名前を変更)
3)UIView(このビューは、scrollViewスクロールするコンテンツです)

1
Vatsal Shukla

ページが画面の全幅を占めるページ分割されたスクロールビューで自動レイアウトが機能するようにしました。 ページはスクロールビューのサイズに応じて自動的にサイズ変更されます。幅の狭いスクロールビューではこれをテストしていませんが、機能する場合はコメントを削除します。 iOS 9を対象として、Swift 2でコードを記述し、awakeFromNibでIBとカスタムコードを組み合わせて使用​​しました。

手順:

  • 全画面スクロールビューを定義します。
  • スクロールビュー内に、スクロールビューの上端、後端、下端、および前端がすべてゼロであるUIView(私の名前はcontentView)を追加します。高さはスクロールビューのものと同じです。 ただし、幅はスクロールビューの幅にページ数を掛けたものです。これを視覚的に行うと、コンテンツビューがInteface Builderのスクロールビューを超えて表示されます。
  • contentView内のすべての「ページ」に対して、Autolayoutルールを追加して互いに並べますが、最も重要なことは、それぞれの幅がスクロールと等しくなるように制約を与えますコンテンツビューではなくビューです。

以下のサンプルコード。 embedChildViewControllerは、子VCを追加するための私の便利な方法です。setupLayoutRulesForPagesを見てください。正確に2ページあるため、機能は単純すぎますが、必要に応じて拡張できます。

私のView Controllerで:

override func loadView() {
    self.view = self.customView
}

override func viewDidLoad() {
super.viewDidLoad()

self.embedChildViewController(self.addExpenseVC, toView: self.customView.contentView, fillSuperview: false)
self.embedChildViewController(self.addCategoryVC, toView: self.customView.contentView, fillSuperview: false)
self.customView.setupLayoutRulesForPages(self.addExpenseVC.view, secondPage: self.addCategoryVC.view)
}

私のカスタムビュー:

class __AMVCView: UIView {

    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var contentView: UIView!
    @IBOutlet weak var pageControl: UIPageControl!

    override func awakeFromNib() {
        super.awakeFromNib()

        self.scrollView.pagingEnabled = true
        self.scrollView.bounces = true
        self.scrollView.showsHorizontalScrollIndicator = false
        self.scrollView.showsVerticalScrollIndicator = false

        self.pageControl.numberOfPages = 2

        self.contentView.backgroundColor = UIColor.blueColor()
        self.scrollView.backgroundColor = UIColor.clearColor()
        self.backgroundColor = UIColor.blackColor()
    }

    func setupLayoutRulesForPages(firstPage: UIView, secondPage: UIView) {
        guard self.contentView.subviews.contains(firstPage) && self.contentView.subviews.contains(secondPage)
            else {
                return
        }

        let rules = [
            "H:|-0-[firstPage]-0-[secondPage]-0-|",
            "V:|-0-[firstPage]-0-|",
            "V:|-0-[secondPage]-0-|"
        ]
        let views = [
            "firstPage" : firstPage,
            "secondPage" : secondPage
        ]
        let constraints = NSLayoutConstraint.constraintsWithVisualFormatArray(rules, metrics: nil, views: views)

        UIView.disableAutoresizingMasksInViews(firstPage, secondPage)
        self.addConstraints(constraints)

        // Add the width Autolayout rules to the pages.
        let widthConstraint = NSLayoutConstraint(item: firstPage, attribute: .Width, relatedBy: .Equal, toItem: self.scrollView, attribute: .Width, multiplier: 1, constant: 0)
        self.addConstraint(widthConstraint)
    }

}
0
Matthew Quiros