কীভাবে ইউআইএক্লোলিকেশনভিউয়ের উচ্চতা নির্ধারণ করবেন ফ্লোএলআউট সহ


118

আমি একটি UICollectionViewদিয়ে একটি পেয়েছি UICollectionViewFlowLayoutএবং আমি এর সামগ্রীর আকার গণনা করতে চাই ( intrinsicContentSizeঅটোলাউটের মাধ্যমে এর উচ্চতা সামঞ্জস্য করার জন্য প্রয়োজনীয় বিনিময়ের জন্য)।

সমস্যাগুলি হ'ল: সমস্ত কক্ষের জন্য আমার একটি নির্দিষ্ট এবং সমান উচ্চতা থাকলেও আমি জানি না যে আমার মধ্যে কতগুলি "সারি" / রেখা রয়েছে UICollectionView। আমি আমার ডেটা উত্সে আইটেমের সংখ্যা অনুসারেও এটি নির্ধারণ করতে পারি না, যেহেতু ডেটা আইটেমগুলির প্রতিনিধিত্বকারী ঘরগুলি প্রস্থে পৃথক হয়, ফলস্বরূপ আমার এক আই লাইনে থাকা আইটেমের সংখ্যাও হয় না UICollectionView

যেহেতু অফিসিয়াল ডকুমেন্টেশনে আমি এই বিষয়টিতে কোনও ইঙ্গিত খুঁজে পাইনি এবং গুগলিং আমাকে আর আনেনি, তাই কোনও সহায়তা এবং ধারণাগুলি খুব প্রশংসা হবে।

উত্তর:


255

ওহো! কিছু কারণে গবেষণার কয়েক ঘন্টা পরে, আমি এখন আমার প্রশ্নের একটি খুব সহজ উত্তর পেয়েছি: আমি সম্পূর্ণরূপে ভুল জায়গায় অনুসন্ধান করছিলাম, আমি যে ডকুমেন্টে সন্ধান করতে পারছিলাম সেগুলি খনন করেছিলাম UICollectionView

অন্তর্নিহিত লেআউট সহজ এবং সহজ সমাধান মিথ্যা: শুধু কল collectionViewContentSizeআপনার এর উপর myCollectionView.collectionViewLayoutসম্পত্তি এবং আপনি উচ্চতা এবং যেমন বিষয়বস্তুর প্রস্থ পেতে CGSize। তার যে হিসাবে হিসাবে সহজ.


1
ওহো, আমি চাই ইউআইটিএবলভিউর কিছু মিল রয়েছে
ক্রিস চেন

1
ইগনেটাস, @ জবান্দি, ক্রিস এট আল, আপনি কি এটির উপর প্রসারিত করতে পারেন? যখন আমি একটি বৃহত আন্ত-আইটেম ফাঁক দিয়ে অনুভূমিক স্ক্রোলের দিক দিয়ে পরীক্ষা করেছি (যাতে আইটেমগুলি অনুভূমিকভাবে ছড়িয়ে যায়), সংগ্রহের ভিউটি একটি অবৈধ অভ্যন্তরীণ সামগ্রী আকার (-1, -1) ফিরিয়ে দিয়েছে এবং ভিউকন্টেন্টসাইজ কার্যকরভাবে যা ফিরিয়ে দিয়েছে সংগ্রহ দেখার সীমানা - জায়গাটি ঘিরে কেবল একটি সারি ছিল তা বিবেচনা করে নিই না। সংক্ষেপে, এটি খুব অভ্যন্তরীণ ছিল না। ধন্যবাদ!
ক্রিস কনভারের

8
সংগ্রহেভিউ কনটেন্টসাইজ এবং কন্টেন্টসাইজ স্ক্রোল ভিউয়ের মধ্যে পার্থক্য কী?
রওনাক

আপনি যখন ভিডডিডোডে সংগ্রহের ভিউটির কন্টেন্টসাইজকে কল করেন, এটি সংগ্রহের দৃশ্যের ফ্রেম দেয়, কালেকশনভিউ কনটেন্টসাইজ সঠিক সামগ্রীর আকার দেয়।
10:40

1
যার জন্য এটি সহায়তা করতে পারে: এর আগে আমাকে একটি "লেআউটআইফনেড ()" করতে হয়েছিল যাতে আমি এটি কাজ করতে পারি।
asanli

37

আপনি যদি অটো লেআউট ব্যবহার করছেন তবে আপনি এর একটি সাবক্লাস তৈরি করতে পারেনUICollectionView

আপনি যদি নীচের কোডটি ব্যবহার করেন তবে সংগ্রহ ভিউটির সামগ্রীর উপর ভিত্তি করে এটির পরিবর্তনের জন্য আপনাকে সংগ্রহের দৃশ্যের জন্য কোনও উচ্চতার সীমাবদ্ধতা নির্দিষ্ট করতে হবে না।

নীচে দেওয়া হল বাস্তবায়ন:

@interface DynamicCollectionView : UICollectionView

@end

@implementation DynamicCollectionView

- (void) layoutSubviews
{
    [super layoutSubviews];

    if (!CGSizeEqualToSize(self.bounds.size, [self intrinsicContentSize]))
    {
        [self invalidateIntrinsicContentSize];
    }
}

- (CGSize)intrinsicContentSize
{
    CGSize intrinsicContentSize = self.contentSize;

    return intrinsicContentSize;
}

@end

11
আমার জন্য কাজ করে নি ... আমি একটি UITableViewCell ভিতরে আমার CollectionView ব্যবহার করছি এবং tableview উচ্চতা বাড়া হিসাবে সংগ্রহ দেখুন iOS8 UITableViewAutomaticDimension ব্যবহার উচ্চতায় বৃদ্ধি কিন্তু আমার collectionview থাকার বিষয়টি মতেই ছোট চাই :(
গেয়র্গ

অসাধারণ. কোনও ইউআইএসক্রোলভিউয়ের অভ্যন্তরে আমার ইউআইসি কলিকেশনভিউয়ের সংক্ষিপ্ত এবং মিষ্টি সমাধান!
ডটটোস্ট্রিং 30:15

2
একটি গুরুত্বপূর্ণ বিষয় সংগ্রহ ভিউতে স্ক্রোলিং এবং স্ক্রোলবারগুলি অক্ষম করা
জর্জি

1
জর্জ হিসাবে একই সমস্যা, উচ্চতা প্রায় 50px যখন এটি 400 এর বেশি হওয়া উচিত
xtrinch

3
হ্যাঁ, আমি সংগ্রহের ভিউটি "স্ক্রোলবেল নয়, কোনও স্কোলবার নয়" এ সেট করেছি এবং তারপরে এটি পুনরায় লোড করে টেবিল ভিউয়ের সামগ্রী সেট করা আছে। এছাড়াও কালেকশনভিউ একটি সাবক্লাস যা এটির সামগ্রী আকারকে আন্তঃসৌনিক আকার হিসাবে ফিরিয়ে দেয়। আশা করি এইটি কাজ করবে!
গেয়র্গ

25

viewDidAppearযদি আপনি এটি দ্বারা পেতে পারেন:

float height = self.myCollectionView.collectionViewLayout.collectionViewContentSize.height;

হতে পারে আপনি যখন ডেটা পুনরায় লোড করেন তখন নতুন ডেটা দিয়ে একটি নতুন উচ্চতা গণনা করা দরকার তবে আপনি এটি পেতে পারেন: আপনার CollectionViewসমাপ্ত পুনরায় লোড ডেটা যখন শুনবে তখন পর্যবেক্ষক যুক্ত করুন viewdidload:

[self.myCollectionView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionOld context:NULL];

তারপরে নতুন উচ্চতা পেতে বেলো ফাংশন যুক্ত করুন বা সংগ্রহ ভিউ পুনরায় লোড শেষ হওয়ার পরে কিছু করুন:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary  *)change context:(void *)context
{
    //Whatever you do here when the reloadData finished
    float newHeight = self.myCollectionView.collectionViewLayout.collectionViewContentSize.height;    
}

এবং পর্যবেক্ষক অপসারণ করতে ভুলবেন না:

[self.myCollectionView removeObserver:self forKeyPath:@"contentSize" context:NULL];

11

ব্যবহারকারী 1046037 উত্তর সুইফটে ...

class DynamicCollectionView: UICollectionView {
    override func layoutSubviews() {
        super.layoutSubviews()
        if bounds.size != intrinsicContentSize() {
            invalidateIntrinsicContentSize()
        }
    }

    override func intrinsicContentSize() -> CGSize {
        return self.contentSize
    }
}

এটি নিখুঁতভাবে কাজ করছে তবে যদি UILabelউপরের মতো কিছু থাকে তবে উপরের collectionViewউপাদানগুলির উপরের উপাদানগুলি থেকে যায়, আপনার কি অন্য সমাধান আছে?
কোলাচেন

11

ব্যবহারকারী 1046037 উত্তরের জন্য 3 টি সুইফ্ট করুন

import UIKit

class DynamicCollectionView: UICollectionView {

    override func layoutSubviews() {
        super.layoutSubviews()
        if !__CGSizeEqualToSize(bounds.size, self.intrinsicContentSize) {
            self.invalidateIntrinsicContentSize()
        }

    }

    override var intrinsicContentSize: CGSize {
        return contentSize
    }

}

আমি একজন ফ্রেশার, এবং আমার ভিউকন্ট্রোলারে কোথায় এবং কীভাবে এটি ব্যবহার করব তা সম্পর্কে আমি নিশ্চিত নই, আপনি কি উত্তর দিয়ে একটি সম্পাদনা করতে পারেন .....?
আবিরামি বালা 16'17

1
এই ক্লাসটি কেবল স্টোরিবোর্ডে আপনার সংগ্রহে দেখার জন্য সেট করুন
মোহাম্মদ সাদিক শায়খ

7

সুইফট 4

class DynamicCollectionView: UICollectionView {
  override func layoutSubviews() {
    super.layoutSubviews()
    if !__CGSizeEqualToSize(bounds.size, self.intrinsicContentSize) {
      self.invalidateIntrinsicContentSize()
    }
  }

  override var intrinsicContentSize: CGSize {
    return collectionViewLayout.collectionViewContentSize
  }
}

1
আমি দেখতে পেয়েছি যে এটি আইফোন 6/7 প্লাস এবং এক্সআর, এক্সএস-ম্যাক্স
রাহুল কে রাজনে

7

সুইফট 4.2

class DynamicCollectionView: UICollectionView {
    override func layoutSubviews() {
        super.layoutSubviews()
        if bounds.size != intrinsicContentSize {
            invalidateIntrinsicContentSize()
        }
    }

    override var intrinsicContentSize: CGSize {
        return self.contentSize
    }
}

4

এই প্রশ্নের উত্তর দিতে দেরি হয়ে গেছে তবে আমি সম্প্রতি এই সমস্যাটি দিয়েছি।
@ লির উপরের উত্তরগুলি আমার উত্তর পেতে আমাকে অনেক সহায়তা করে। তবে এই উত্তরটি উদ্দেশ্য-সি এর মধ্যে সীমাবদ্ধ এবং আমি দ্রুত কাজ করছি ।
@ উত্তর আপনার উত্তরের রেফারেন্স সহ, আমাকে দ্রুত ব্যবহারকারীকে এই সমস্যাটি সহজে সমাধান করার অনুমতি দিন। তার জন্য, দয়া করে নীচের পদক্ষেপগুলি অনুসরণ করুন:

CGFloatঘোষণা বিভাগে একটি পরিবর্তনশীল ঘোষণা করুন:

var height : CGFloat!

viewDidAppearযদি আপনি এটি দ্বারা পেতে পারেন:

height = self.myCollectionView.collectionViewLayout.collectionViewContentSize().height

আপনার reloadডেটা যখন তখন নতুন ডেটা দিয়ে একটি নতুন উচ্চতা গণনা করা প্রয়োজন তখন আপনি এটি পেতে পারেন: addObserverআপনার CollectionViewসমাপ্ত পুনরায় লোড ডেটা কখন শুনতে হবে viewWillAppear:

override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(true)
        ....
        ....
        self.shapeCollectionView.addObserver(self, forKeyPath: "contentSize", options: NSKeyValueObservingOptions.Old, context: nil)
    }

তারপরে নতুন উচ্চতা পেতে বেলো ফাংশন যুক্ত করুন বা collectionviewসমাপ্ত পুনঃলোডের পরে কিছু করুন :

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
        let newHeight : CGFloat = self.myCollectionView.collectionViewLayout.collectionViewContentSize().height

        var frame : CGRect! = self.myCollectionView.frame
        frame.size.height = newHeight

        self.myCollectionView.frame = frame
    }

এবং পর্যবেক্ষক অপসারণ করতে ভুলবেন না:

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(true)
    ....
    ....
    self.myCollectionView.removeObserver(self, forKeyPath: "contentSize")
}

আমি আশা করি এটি আপনার সমস্যাটি দ্রুতগতিতে সমাধান করতে সহায়তা করবে।


@ শিখাশর্মা: আপনি "ভিউডিডডিস্পিয়ার" পদ্ধতির মধ্যে অপসারণকারী কোডটি যুক্ত করতে পারেন, যা দর্শকের অপসারণের বিষয়টি নিশ্চিত হওয়ার পরেই পর্যবেক্ষককে সরিয়ে ফেলবে। দয়া করে আপডেট করা উত্তরটি পরীক্ষা করুন।
এর। বিহার

এই ত্রুটিটি পাচ্ছি: একটি -অভিজারভ্যালিউফোর্ডকি পেথ: অফজেক্ট: পরিবর্তন: প্রসঙ্গ: বার্তাটি প্রাপ্ত হয়েছিল তবে পরিচালনা করা হয়নি।
শিখা শর্মা

@ শিখাশর্মা: দুঃখিত, পদ্ধতিটি উল্লেখ করা আমার ভুল। ViewWillDisappear এ অপসারণের কোডটি রাখার চেষ্টা করুন।
এর। বিহার

1

এই উত্তরটি @ ইআর ভিত্তিক। বিহারের উত্তর। আপনি সহজেই আরএক্সএসউফ্ট ব্যবহার করে সমাধানটি কার্যকর করতে পারেন

     collectionView.rx.observe(CGSize.self , "contentSize").subscribe(onNext: { (size) in
        print("sizer \(size)")
    }).disposed(by: rx.disposeBag)

0

@ ব্যবহারকারী 1046037 এর সুইফ্ট সংস্করণ:

public class DynamicCollectionView: UICollectionView {

    override public func layoutSubviews() {
        super.layoutSubviews()
        if !bounds.size.equalTo(intrinsicContentSize) {
            invalidateIntrinsicContentSize()
        }
    }

    override public var intrinsicContentSize: CGSize {
        let intrinsicContentSize: CGSize = contentSize
        return intrinsicContentSize
    }
}

0

সুইফট 4.2, এক্সকোড 10.1, আইওএস 12.1:

কোনও কারণে, collectionView.contentSize.heightআমার সংগ্রহ দর্শনের সমাধানের উচ্চতার চেয়ে ছোট উপস্থিত ছিল। প্রথমত, আমি তদারকির উচ্চতার 1/2 অংশের তুলনায় একটি স্বয়ং-বিন্যাস সীমাবদ্ধতা ব্যবহার করছিলাম। এটি ঠিক করতে, আমি দৃশ্যের "নিরাপদ অঞ্চল" এর সাথে সম্পর্কিত হিসাবে সীমাবদ্ধতা পরিবর্তন করেছি।

এটি আমাকে ব্যবহার করে আমার সংগ্রহ ভিউ পূরণের জন্য ঘরের উচ্চতা সেট করার অনুমতি দিয়েছে collectionView.contentSize.height:

private func setCellSize() {
    let height: CGFloat = (collectionView.contentSize.height) / CGFloat(numberOfRows)
    let width: CGFloat = view.frame.width - CGFloat(horizontalCellMargin * 2)

    let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
    layout.itemSize = CGSize(width: width, height: height)
}

আগে

তত্ত্বাবধানের তুলনায় উচ্চতার সীমাবদ্ধতা খারাপ সিমুলেটর ফলাফল

পরে

নিরাপদ অঞ্চলের তুলনায় উচ্চতার সীমাবদ্ধতা ভাল সিমুলেটর ফলাফল


0

আপনার collectionView অভিমানী নামকরণ করা হয় যেমন collectionView আপনি উচ্চতা নিম্নরূপ গ্রহণ করতে পারেন।

let height = collectionView.collectionViewLayout.collectionViewContentSize.height

0

এছাড়াও reloadData- উচ্চতা পাওয়ার আগে আপনি আরও ভাল কল করেছিলেন:

theCollectionView.collectionViewLayout.collectionViewContentSize;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.