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をオフにしたときに機能し始めました。どうして?
同じ問題がありました。 UIScrollView
の自動レイアウトが台無しです。
回避策:UIScrollView
のすべてを別のUIView
に入れ、そのUIView
をUIScrollView
の唯一の子として置きます。その後、自動レイアウトを使用できます。
終わり近くのものが乱れた場合(UIScrollView
がスクロールする方向の最後)、最後の制約を変更して、可能な限り優先度を低くします。
私は、viewWillLayoutSubviewsを使用してscrollViewのcontentSizeを更新しましたが、うまくいきました。
- (void)viewDidLayoutSubviews
{
[self.bgScrollView setContentSize:CGSizeMake(320, self.view.frame.size.height* 1.5)];
}
-(void)viewDidLayoutSubviews
ビューがサブビューをレイアウトしたことをView Controllerに通知するために呼び出されます。
ディスカッション
ビューコントローラーのビューの境界が変更されると、ビューはそのサブビューの位置を調整し、システムはこのメソッドを呼び出します。ただし、呼び出されるこのメソッドは、ビューのサブビューの個々のレイアウトが調整されたことを示すものではありません。各サブビューは、独自のレイアウトを調整します。
ビューがサブビューをレイアウトした後、View Controllerはこのメソッドをオーバーライドして変更を加えることができます。このメソッドのデフォルト実装は何もしません。
最も簡単でクリーンな方法は、viewDidAppearでcontentSizeを設定して、自動レイアウトの効果を無効にすることです。これには、ランダムビューの追加は含まれません。ただし、実装が機能するためにロード順序に依存することは、最善のアイデアではない場合があります。
ここには2つの問題があります。 (1)viewDidLoadが早すぎます。レイアウトが完了するまで待つ必要があります。 (2)ペン先からのスクロールビューで自動レイアウトを使用する場合は、制約を使用してcontentSize
のサイズを完全に記述する必要があります(その後、contentSize
を設定しませんまたは、コードで設定する場合は、スクロールビューのサブビューの制約がcontentSize
を指定しないように防止する必要があります。後者を行いたいようです。これを行うには、スクロールビューの唯一のトップレベルのサブビューとして機能するUIViewが必要です。コードでは、それをnotに設定し、autoresizingMask
を有効にする自動レイアウトを使用する必要があります他の外部制約を削除します。ここで、その方法の例を示します。
ただし、制約を完全に使用する方法を示す次の例にも注意してください。insteadof contentSize
。
ステップ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キーを押しながらドラッグします)。それぞれがそれぞれscrollView
とcontentView
と呼ばれると仮定しましょう。次のようになります。
@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;
}
このコードを使用してください。 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;
});
}
このコード行を* .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で私のために機能します
ContentSizeをviewDidAppear
に設定することが重要です。
しかし、3.5インチ画面と4インチ画面で動作するもののバリエーションもありました。 4インチの画面は機能しましたが、古い画面は機能しません。 iOS 7とBizarreはどちらも控えめな表現です!
AutoLayout
を使用している場合、contentSize
のUIScrollView
を設定する非常に簡単な方法は、次のようなものを追加することです。
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];
以前はプログラムでuiscrollviewを設定していましたが、次のすばらしいチュートリアルを見て、uiscrollviewとuiviewを機能させる方法を順を追って見てきました。 https://www.youtube.com/watch?v=PgeNPRBrB18 =
ビデオを見た後、きっとあなたはInterface Builderを好きになるでしょう。
投票する
ラベルの動的な高さがビューの高さを超えている場合でもスクロールしない
上記の正しいとマークされたyufの答えを実行しました(スクロールビューにコンテンツビューを追加し、コンテンツビューからスクロールビューまでの幅を先頭、末尾、上下、および等しい幅に設定しました)が、それでも私のビューは内部コントロールの高さがスクロールビューの高さを超えたときにスクロールしない。
コンテンツビュー内には、画像とその下に3つのラベルがあります。各ラベルは、その中に含まれるテキストの量に応じて、独自の高さを調整します(これを実現するために、ワードラップとnumberoflines = 0に設定されます)。
私が抱えていた問題は、スクロールビュー/メインビューの高さを超えると、コンテンツビューの高さがラベルの動的な高さで調整されないことでした。
これを修正するには、ボトムラベルとコンテンツビューの間にBottom Space to Container制約を設定し、値を40に設定する必要があると言いました下部のマージン)。これは、私のコンテンツビューが最後のラベルの下部とそれ自体の間にスペースがあるように高さを調整し、完全にスクロールすることを意味します!
わーい!
制約に基づいた自動レイアウトを機能させることはできませんでした。私のビューはすでにサブクラスのUIScrollViewであったため、setContentView:をオーバーライドし、高さゼロのsetContentSize:メッセージの自動レイアウトを無視することで解決しました。
@interface MyView : UIScrollView {}
@end
@implementation MyView
- (void)setContentSize:(CGSize)aSize {
if (aSize.height > 0)
[super setContentSize:aSize];
}
@end
これを試してみてください...UIView
の場合と同じようにすべての制約を追加します(ストーリーボードのViewControlerのscreenShotを参照してください)
今、トリックが始まります。最後のオブジェクトを選択し、その下の制約を選択します。 (上記のscreenShot、Instagramボタンの下部の制約(黄色の線)を参照)および以下のスクリーンショットのようにサイズインスペクターの定数を変更します。
constant = 8が必要ですが、要件に応じて変更できます。この定数は、そのオレンジ色のボタンの下部とscrollViewの間のスペースです。
[〜#〜] edit [〜#〜]
ビューの階層を確認してください。
0)ViewController.view(optional)
1)UIScrollView
2)UIView(「contentView」に名前を変更)
3)UIView(このビューは、scrollViewスクロールするコンテンツです)
ページが画面の全幅を占めるページ分割されたスクロールビューで自動レイアウトが機能するようにしました。 ページはスクロールビューのサイズに応じて自動的にサイズ変更されます。幅の狭いスクロールビューではこれをテストしていませんが、機能する場合はコメントを削除します。 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)
}
}