web-dev-qa-db-ja.com

UIScrollViewのコンテンツサイズを動的に設定する方法

UIScrollviewについて質問がありました。

ストーリーは、ChartsViewという名前のUIViewがあり、それをオーバーライドメソッドdrawRect()によって自分で再描画することです。描画のコンテンツは動的に生成されました。そのため、実行時までそのサイズはわかりません。問題は、スーパービュー(scrollView)のコンテンツサイズをどのように/どこで動的に設定できますか?

    - (void)viewDidLoad
    {
        [super viewDidLoad];

// not this way. it's fixed size.....
        ChartsView *chartsView = [[ChartsView alloc]initWithFrame:CGRectMake(0, 0, 320, 800)]; 

        self.scrollView.contentSize = chartsView.frame.size;

        [self.scrollView addSubview:chartsView];

    }
29
Roger Lee

もう1つの簡単な方法

- (void)viewDidLoad
{
    float sizeOfContent = 0;
    UIView *lLast = [scrollView.subviews lastObject];
    NSInteger wd = lLast.frame.Origin.y;
    NSInteger ht = lLast.frame.size.height;

    sizeOfContent = wd+ht;

    scrollView.contentSize = CGSizeMake(scrollView.frame.size.width, sizeOfContent);
}
59
IOS Rocks

ScrollView.subviews配列の最後のオブジェクトがスクロールビューで最も高いy-Originオブジェクトを返すことは100%保証されていません。サブビュー配列はZ-Indexによって配列されます(つまり、サブビュー配列の最後のオブジェクトは、一番上にスタックされ、スクロールビューのサブビューの一番上のサブビューになります。代わりに、基本的な並べ替え関数を使用する方が正確です)サブビューを反復処理し、y-Originが最も高いオブジェクトを取得します。

Swift 4

extension UIScrollView {
    func updateContentView() {
        contentSize.height = subviews.sorted(by: { $0.frame.maxY < $1.frame.maxY }).last?.frame.maxY ?? contentSize.height
    }
}

使用法(viewDidLayoutSubviews内、またはコンテンツサイズが更新されるたび):

myScrollView.updateContentView()
11

Swift(2.0)

@IBOutlet weak var btnLatestButton: UIButton!

override func viewDidLoad() {
    super.viewDidLoad()

    let height = btnLatestButton.frame.size.height
    let pos = btnLatestButton.frame.Origin.y
    let sizeOfContent = height + pos + 10
    scrollview.contentSize.height = sizeOfContent

}

もちろん、スクロールビューに表示されるビューの数が決まっている場合です。 IOS Rocksメソッドは利用可能ですが、私にとっては良くありませんでした。必要以上のスペースを作成しました。

    let lastView : UIView! = scrollview.subviews.last
    let height = lastView.frame.size.height
    let pos = lastView.frame.Origin.y
    let sizeOfContent = height + pos + 10
    scrollview.contentSize.height = sizeOfContent
6
CularBytes

IOS Rocks and CularBytesのおかげで、これについてのリードが得られました。上記のソリューションには2つの問題(私にとって)が見つかりました。

  1. 私は常にUIScrollViewの唯一の子としてコンテナUIViewを持っているので、その子UIViewで最後のビューを検索する方法を更新する必要がありました(以下を参照)
  2. 私はUIScrollViewのコンテンツをオフセットしていますので、その最後のUIViewの絶対位置を計算するために必要です(したがって、親ビューではなくウィンドウを基準にして)

また、UIScrollViewの側面を固定するために自動レイアウトを使用しているため、幅(CularBytesのように)を心配する必要はありません。

ここに私が思いついたものがあります(Swift 3.0)):

_func setScrollViewContentSize() {

    var height: CGFloat
    let lastView = self.myScrollView.subviews[0].subviews.last!
    print(lastView.debugDescription) // should be what you expect

    let lastViewYPos = lastView.convert(lastView.frame.Origin, to: nil).y  // this is absolute positioning, not relative
    let lastViewHeight = lastView.frame.size.height

    // sanity check on these
    print(lastViewYPos)
    print(lastViewHeight)

    height = lastViewYPos + lastViewHeight

    print("setting scroll height: \(height)")

    myScrollView.contentSize.height = height
}
_

viewDidAppear()メソッドでこれを呼び出します。

4
the_dude_abides
override func viewDidAppear(_ animated: Bool) {
    var height: CGFloat
    let lastView = self.scrollView.subviews[0].subviews.last!

    let lastViewYPos = lastView.convert(lastView.frame.Origin, to: nil).y  
    let lastViewHeight = lastView.frame.size.height

    height = lastViewYPos + lastViewHeight
    scrollView.contentSize.height = height
}
1
Asad Jamil

これを試して -

- (void)viewDidLoad
    {
        [super viewDidLoad];

// not this way. it's fixed size.....
        ChartsView *chartsView = [[ChartsView alloc]initWithFrame:CGRectMake(0, 0, 320, 800)]; 

        //self.scrollView.contentSize = chartsView.frame.size;
        [self.scrollView setContentSize:CGSizeMake(chartsView.frame.size.width, chartsView.frame.size.height)];
        [self.scrollView addSubview:chartsView];

    }
1
Abhishek Mishra

これを試して

- (void)viewDidLoad
        {
            [super viewDidLoad];

    // not this way. it's fixed size.....
            ChartsView *chartsView = [[ChartsView alloc]initWithFrame:CGRectMake(0, 0, 320, 800)]; 

            self.scrollView.contentSize = chartsView.frame.size;
            [self.scrollView setNeedsDisplay];
            [self.scrollView addSubview:chartsView];

    }
1
MrWaqasAhmed

UIScrollview contentSizeを動的に計算します(サブビューフレームに依存)

迅速:

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;
                       });
}
0

これは、Swift 3

extension UIScrollView {
    func updateContentViewSize() {
        var newHeight: CGFloat = 0
        for view in subviews {
            let ref = view.frame.Origin.y + view.frame.height
            if ref > newHeight {
                newHeight = ref
            }
        }
        let oldSize = contentSize
        let newSize = CGSize(width: oldSize.width, height: newHeight + 100)
        contentSize = newSize
    }
}
0
Bogdan Ustyak

ストーリーボードでスクロールビューを使用する場合、コンテンツのサイズを静的な値でプログラムで指定するよりも、スクロールビューに存在するビューの数に応じてコンテンツのサイズを計算する方が適切です。コンテンツサイズを動的に取得する手順は次のとおりです。

ステップ1:Scrollviewを追加してストーリーボードに表示し、先頭、末尾、上部および下部の制約を追加します(すべての値はゼロです)。

ステップ2:直接scrollviewで必要なビューを直接追加しないでください。最初に1つのビューをscrollviewに追加します(すべてのUIのコンテンツビューになります)要素)。このビューに以下の制約を追加します。先頭、末尾、上部および下部の制約(すべての値はゼロです)。メインビュー(つまり、スクロールビューを含む)に同じ高さ、同じ幅を追加します。高さが等しい場合は、優先度を低に設定します。 (これは、コンテンツサイズを設定するための重要な手順です)。このコンテンツビューの高さは、ビューに追加されたビューの数に応じて決まります。最後に追加したビューが1つのラベルで、Yの位置が420、高さが20の場合、コンテンツビューは440になります。

ステップ3:要件に従ってコンテンツビュー内に追加したすべてのビューに制約を追加します。

enter image description here

enter image description here

参照: https://medium.com/@javedmultani16/uiscrollview-dynamic-content-size-through-storyboard-in-ios-fb873e9278e

0