web-dev-qa-db-ja.com

UIScrollViewのコンテンツサイズのSizeToFit

UIViewにはSizeToFitメソッドがあり、UIViewをそのすべてのサブビューに適合させます。計算したサイズを返すだけで、ビューのフレームを変更しないようなものはありますか。

UIScrollViewにいくつかのサブビューがあり、フレームではなく、スクロールビューのcontentSizeでSizeToFitを実行したいと思います。 UIScrollViewの「実際の」サイズを大きくしたくないので、contentSizeで行う必要があります。また、コンテンツは動的かつ非同期に読み込まれるため、サブビューをUIScrollViewに追加するときに手動で行うことはできません。 。

19
Jonathan.

現時点では、これは私が持っている最高のものです:

CGRect contentRect = CGRectZero;
for (UIView *view in self.subviews)
    contentRect = CGRectUnion(contentRect, view.frame);
self.contentSize = contentRect.size;
40

関数が頻繁に呼び出される場合は、サブビューを毎回繰り返す必要はありません。代わりに、サブビューが追加されるたびに、現在のcontentSizeと新しいサブビューのフレームを結合します。

- (void)didAddSubview:(UIView *)subview {
    CGRect tmp;
    tmp.Origin = CGPointZero;
    tmp.size = self.contentSize;
    tmp = CGRectUnion(tmp,subview.frame);
    self.contentSize = tmp.size;
}
4
ughoavgfhw

ここで解決策を見つけました ScrollView ContentSize 、サブビューのサイズを見つけ、結合されたコンテンツサイズを見つけ、サブビューを水平に配置するか垂直に配置するかを指定するオプションも見つけることができます。

上記のリンクからのコードは次のとおりです。

@interface UIScrollView(auto_size)
- (void) adjustHeightForCurrentSubviews: (int) verticalPadding;
- (void) adjustWidthForCurrentSubviews: (int) horizontalPadding;
- (void) adjustWidth: (bool) changeWidth andHeight: (bool) changeHeight withHorizontalPadding: (int) horizontalPadding andVerticalPadding: (int) verticalPadding;
@end

@implementation UIScrollView(auto_size)
- (void) adjustWidth: (bool) changeWidth andHeight: (bool) changeHeight withHorizontalPadding: (int) horizontalPadding andVerticalPadding: (int) verticalPadding {
    float contentWidth = horizontalPadding;
    float contentHeight = verticalPadding;
    for (UIView* subview in self.subviews) {
        [subview sizeToFit];
        contentWidth += subview.frame.size.width;
        contentHeight += subview.frame.size.height;
    }

    contentWidth = changeWidth ? contentWidth : self.superview.frame.size.width;
    contentHeight = changeHeight ? contentHeight : self.superview.frame.size.height;

    NSLog(@"Adjusting ScrollView size to %fx%f, verticalPadding=%d, horizontalPadding=%d", contentWidth, contentHeight, verticalPadding, horizontalPadding);
    self.contentSize = CGSizeMake(contentWidth, contentHeight);
}

- (void) adjustHeightForCurrentSubviews: (int) verticalPadding {
    [self adjustWidth:NO andHeight:YES withHorizontalPadding:0 andVerticalPadding:verticalPadding];
}

- (void) adjustWidthForCurrentSubviews: (int) horizontalPadding {
    [self adjustWidth:YES andHeight:NO withHorizontalPadding:horizontalPadding andVerticalPadding:0];
}
@end

また、代替ソリューションが提供されているので、ブログページのコメントも確認してください。

-anoop

2
anoop4real

Williamの回答 は非常に便利でしたが、スクロールバーはスクロールビューのサブビューでもあるため、完全には機能しませんでした。結局のところ、コツはコンテンツサイズを計算する前にそれらを非表示にすることです。 Swift 3コードは次のようになります。

override func viewDidLayoutSubviews() {
    scrollView.layoutSubviews()

    // disable scrollbars so they don't interfere during resizing
    scrollView.showsVerticalScrollIndicator = false
    scrollView.showsHorizontalScrollIndicator = false

    scrollView.contentSize = scrollView.subViewArea()

    // re-enable the scrollbars
    scrollView.showsVerticalScrollIndicator = true
    scrollView.showsHorizontalScrollIndicator = true
}

また、プロジェクトのどこかに次の拡張機能を追加する必要があります。

extension UIScrollView {
    func subViewArea() -> CGSize {
        var rect = CGRect.zero
        for subview in subviews {
            rect = rect.union(subview.frame)
        }

        return rect.size
    }
}
1
mohak

ScrollViewのコンテンツサイズを設定する機能を1つ作ってみて楽しんでみました

まず最初にこの関数を書いてください...

-(void)setContentSizeOfScrollView:(UIScrollView*)scroll
{
    CGRect rect = CGRectZero;

    for(UIView * vv in [scroll subviews])
    {
        rect = CGRectUnion(rect, vv.frame);
    }

    [scroll setContentSize:CGSizeMake(rect.size.width, rect.size.height)];
}

次に、すべての要素を追加した後、この関数を呼び出して、スクロールビューを引数として渡します。

[self setContentSizeOfScrollView:self.YourScrollView];

私はそれがうまくいくと100%確信しています.......。

1
Nirav Gadhiya

これがSwift 3.0の答えです

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    var contentRect: CGRect = CGRect.zero
    for view in self.scrollView.subviews {
        debugPrint("view frame \(view.frame)")
        contentRect = contentRect.union(view.frame)
        debugPrint("frame \(contentRect)")
    }
    self.scrollView.contentSize = contentRect.size
    debugPrint("content size \(self.scrollView.contentSize)")
}
1

コンテンツサイズを計算するには、ユニオンフレームサイズだけでは不十分です。サブビューをオーバーラップする必要がある場合や、サブビュー間にマージンがある場合があるためです。サブビューの起源を知り、計算する必要があります。

ユニオンアプローチでは、AとBのデザインに同じコンテンツの高さが与えられます。しかし、最後の最大のサブビューを知っている場合は、適切なコンテンツの高さを計算できます。

enter image description here

この拡張機能は実際のコンテンツの高さを計算できます。

extension UIScrollView {

 func adjustContentHeight(bottomPadding: Int = 0) {

    var lastSub: CGRect = .zero
    self.subviews.forEach({
        let sub = $0.frame
        if(sub.maxY > lastSub.maxY) {
            lastSub = sub
        }
    })

    self.contentSize.height = lastSub.maxY + CGFloat(bottomPadding)
 }   
} 
0
ali6p

Swift 2.1で、これをViewControllerに追加します。

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    let aggregateView = contentView.subviews.reduce(CGRect())
        { aggRect, view in aggRect.union(view.frame) }

    scrollView.contentSize = aggregateView.size

}
0
nottombrown

UIViewを同じ幅と高さのUIScrollViewに配置し、スクロールビューではなくすべてのサブビューをITに追加します。次に、scrollviewのclipToBoundsプロパティをTRUEに設定し、UIViewでsizeToFitを呼び出します。 UIViewの背景の不透明度を0に設定して非表示にし、サブビューを表示することもできます。

0
thgc