কোনও ইউআইটিএবলভিউসেল - গতিশীল উচ্চতার ভিতরে ইউআইকিলেকশনভিউ?


125

আমাদের অ্যাপ্লিকেশন স্ক্রিনগুলির একটিতে একটি এর UICollectionViewঅভ্যন্তর স্থাপন করা দরকার UITableViewCell। এই UICollectionViewআইটেম একটি গতিশীল সংখ্যা উচ্চতা পাশাপাশি পরিবর্তনশীল গণনা করা উচিত নয় যা ফলে অধিকারী হবে না। যাইহোক, আমি এম্বেডের উচ্চতা গণনা করতে গিয়ে সমস্যায় পড়ছি UICollectionView

আমাদের ওভারারচিং UIViewControllerস্টোরিবোর্ডে তৈরি হয়েছিল এবং অটো লেআউট ব্যবহার করে না। তবে, আমি জানি না কীভাবে গতির উচ্চতার UITableViewCellউপর ভিত্তি করে উচ্চতা বাড়ানো যায় UICollectionView

কীভাবে এটি সম্পাদন করা যায় সে সম্পর্কে কেউ কিছু পরামর্শ বা পরামর্শ দিতে পারেন?


আপনি যে বিন্যাসটি সম্পন্ন করার চেষ্টা করছেন সে সম্পর্কে আপনি আরও কিছু বলতে পারেন? UITableViewCellএর একিউটাল টেবিলভিউ থেকে উচ্চতা কি আলাদা? আপনি উভয় দিকের উলম্ব স্ক্রলিং প্রয়োজন UICollectionViewএবংUITableView
apouche

3
ইউআইটিবেলভিউসিলের উচ্চতাটি গতিশীল বলে মনে করা হচ্ছে, টেবিল ভিউ ঘরের অংশ ইউআইসিএল্লেশনভিউয়ের উচ্চতার উপর ভিত্তি করে। আমার ইউআইসিকলিকেশনভিউয়ের লেআউটটি 4 টি কলাম এবং একটি গতিশীল সংখ্যক সারি। সুতরাং, 100 আইটেম সহ, আমার 4 টি কলাম এবং 25 টি সারি আমার ইউআইকোলিকেশনভিউতে থাকবে। নির্দিষ্ট কক্ষের উচ্চতা - যেমন ইউআইটিএবলভিউ'র উচ্চতাফোর্ডঅ্যান্ড ইন্ডেক্সপথ দ্বারা নির্দেশিত - সেই ইউআইসি কলিকেশনভিউয়ের আকারের ভিত্তিতে সামঞ্জস্য করতে সক্ষম হওয়া দরকার। এটা কি আরও কিছুটা পরিষ্কার?
শ্যাডোম্যান

@ শ্যাডোম্যান, দয়া করে আমাকে এই পরিস্থিতির সমাধানের পরামর্শ দিন
রবি ওঝা

উত্তর:


127

সঠিক উত্তর হ্যাঁ , আপনি এটি করতে পারেন

আমি কয়েক সপ্তাহ আগে এই সমস্যাটি পেরিয়ে এসেছি। এটি আপনি যা ভাবেন তার চেয়ে আসলে সহজ। আপনার সেলগুলিকে NIBs (বা স্টোরিবোর্ড) এ রাখুন এবং অটো লেআউটটিকে সমস্ত কাজ করতে দিতে সেগুলি পিন করুন

নিম্নলিখিত কাঠামো দেওয়া:

TableView

TableViewCell

CollectionView

CollectionViewCell

CollectionViewCell

CollectionViewCell

[... কক্ষ বা বিভিন্ন কক্ষের আকারের পরিবর্তনশীল সংখ্যা]

সমাধানটি হ'ল অটো লেআউটটিকে প্রথমে সংগ্রহের ভিউসেল আকারগুলি গণনা করতে বলা হয়, তারপরে সংগ্রহটি কন্টেন্টসাইজটি দেখে এবং এটি আপনার ঘরের আকার হিসাবে ব্যবহার করে। এটি ইউআইভিউ পদ্ধতি যা "যাদু করে":

-(void)systemLayoutSizeFittingSize:(CGSize)targetSize 
     withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority 
           verticalFittingPriority:(UILayoutPriority)verticalFittingPriority

আপনাকে এখানে টেবিলভিউসেলের আকার নির্ধারণ করতে হবে, যা আপনার ক্ষেত্রে কালেকশন ভিউজের সামগ্রী আকার রয়েছে।

CollectionViewCell

CollectionViewCell আপনি প্রতিটি সময় আপনি মডেল লেআউট পরিবর্তন করুন সেল জানাতে হবে (যেমন: আপনাকে একটি পাঠ্য সঙ্গে একটি UILabel সেট, তারপর সেল আবার বিন্যাস করা হয়েছে)।

- (void)bindWithModel:(id)model {
    // Do whatever you may need to bind with your data and 
    // tell the collection view cell's contentView to resize
    [self.contentView setNeedsLayout];
}
// Other stuff here...

TableViewCell

TableViewCell জাদু আছে। এটিতে আপনার সংগ্রহে ভিউতে একটি আউটলেট রয়েছে, ইউআইকোলিকেশনভিউ ফ্লোলয়আউটটির আনুমানিক আইটেম সাইজ ব্যবহার করে সংগ্রহ ভিউ সেলগুলির জন্য স্বয়ংক্রিয় বিন্যাস সক্ষম করে ।

তারপরে, কৌশলটি হ'ল সিস্টেমটি লেআউটসাইজফিটিংসাইজ ... পদ্ধতিতে আপনার টেবিলভিউ সেলটির আকার নির্ধারণ করুন । (দ্রষ্টব্য: iOS8 বা তারপরে)

উল্লেখ্য: আমি tableView এর প্রতিনিধি কোষের উচ্চতা পদ্ধতি ব্যবহার করার চেষ্টা -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath.কিন্তু এটা খুব দেরি স্বয়ংক্রিয় বিন্যাস সিস্টেম গনা CollectionView contentSize জন্য এবং কখনও কখনও আপনি ভুল আকৃতিটিকে সবদিক থেকে কোষ খুঁজে পেতে পারেন।

@implementation TableCell

- (void)awakeFromNib {
    [super awakeFromNib];
    UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;

    // Configure the collectionView
    flow.minimumInteritemSpacing = ...;

    // This enables the magic of auto layout. 
    // Setting estimatedItemSize different to CGSizeZero 
    // on flow Layout enables auto layout for collectionView cells.
    // https://developer.apple.com/videos/play/wwdc2014-226/
    flow.estimatedItemSize = CGSizeMake(1, 1);

    // Disable the scroll on your collection view
    // to avoid running into multiple scroll issues.
    [self.collectionView setScrollEnabled:NO];
}

- (void)bindWithModel:(id)model {
    // Do your stuff here to configure the tableViewCell
    // Tell the cell to redraw its contentView        
    [self.contentView layoutIfNeeded];
}

// THIS IS THE MOST IMPORTANT METHOD
//
// This method tells the auto layout
// You cannot calculate the collectionView content size in any other place, 
// because you run into race condition issues.
// NOTE: Works for iOS 8 or later
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority {

    // With autolayout enabled on collection view's cells we need to force a collection view relayout with the shown size (width)
    self.collectionView.frame = CGRectMake(0, 0, targetSize.width, MAXFLOAT);
    [self.collectionView layoutIfNeeded];

    // If the cell's size has to be exactly the content 
    // Size of the collection View, just return the
    // collectionViewLayout's collectionViewContentSize.

    return [self.collectionView.collectionViewLayout collectionViewContentSize];
}

// Other stuff here...

@end

TableViewController

আপনার টেবিলভিউ কনট্রোলারের টেবিলভিউ কক্ষগুলির জন্য অটো লেআউট সিস্টেমটি সক্রিয় করতে মনে রাখবেন :

- (void)viewDidLoad {
    [super viewDidLoad];

    // Enable automatic row auto layout calculations        
    self.tableView.rowHeight = UITableViewAutomaticDimension;
    // Set the estimatedRowHeight to a non-0 value to enable auto layout.
    self.tableView.estimatedRowHeight = 10;

}

ক্রেডিট: @ বারবার এইটিকে বাছাই করতে সহায়তা করেছে


4
হ্যাঁ। এইটা কাজ করে. এটি গ্রহণযোগ্য উত্তর হওয়া উচিত।
সিএসটিরিউ

1
কোনও শরীর কী আমাকে এর জন্য একটি নমুনা কোড সরবরাহ করতে পারে? আমি টেবিলভিউ ঘরের অভ্যন্তরে উল্লম্ব সংগ্রহ দর্শনে একাধিক চিত্র দেখাতে চাই ..
রবি ওঝা

4
অবশেষে এটি আমার জন্য কাজ করা হয়েছে, তবে আমাকে অন্য কৌশল করতে হয়েছিল: cell.bounds = CGRectMake(0, 0, CGRectGetWidth(tableView.bounds), 10000);এটি একটি দীর্ঘ সংগ্রহ ভিউ সহ একটি দীর্ঘ কক্ষটি "অনুকরণ" করবে, সুতরাং কালেকশনভিউ এর সমস্ত কক্ষের আকারের গণনা করবে। অন্যথায় সংগ্রহভিউ কেবলমাত্র দৃশ্যমান কক্ষের আকারগুলি গণনা করে এবং ভুলভাবে তালবেভিউচেল উচ্চতা নির্ধারণ করে।
ইনগাহাম

20
ফ্রেমের উচ্চতা সর্বাধিক স্থানে স্থাপন করার systemLayoutSizeFittingSizeসময়, সেলটি পুনরায় লোড করার সময় আমি দ্রুতগতিতে একটি সমস্যায় পড়ি, অ্যাপসটি মনে হয় এটির পরে আটকে আছে self.collectionView.layoutIfNeeded()। আমি সর্বোচ্চ উচ্চতার চেয়ে 1 এর সাথে ফ্রেমের উচ্চতা নির্ধারণ করে এটি ঠিক করেছি। আশা করি কেউ যদি এই সমস্যায় হোঁচট খায় তবে এর সাহায্য করবে।
টাইটান

6
এটি আমার জন্য এটি স্থির করে দিয়েছে - ইন systemLayoutSizeFitting, বর্তমানে উত্তরে যা দেখানো হয়েছে তার collectionView.layoutIfNeeded()collectionView.frame = CGRect.init(origin: .zero, size: CGSize.init(width: targetSize.width, height: 1))
ক্রমটি

101

আমি মনে করি আমার পাবলিকেশন @ পাবলোরোমিউ প্রস্তাবিতের চেয়ে অনেক সহজ।

ধাপ 1 থেকে নালী তৈরি করুন UICollectionViewথেকে UITableViewCell subclass, যেখানে UICollectionViewস্থাপন করা হয়। যাক, এটি নাম হবেcollectionView

পদক্ষেপ 2. UICollectionViewউচ্চতার সীমাবদ্ধতার জন্য আইবিতে যুক্ত করুন এবং UITableViewCell subclassখুব সহজেই আউটলেট তৈরি করুন । যাক, এটি নাম হবে collectionViewHeight

পদক্ষেপ 3. tableView:cellForRowAtIndexPath:কোড যুক্ত করুন:

// deque a cell
cell.frame = tableView.bounds;
[cell layoutIfNeeded];
[cell.collectionView reloadData];
cell.collectionViewHeight.constant = cell.collectionView.collectionViewLayout.collectionViewContentSize.height;

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

2
আমি এটা কাজ আছে। আমি collectionViewচারপাশে সীমাবদ্ধতা যুক্ত করেছি UITableViewCellএবং সেট করেছি tableView.estimatedRowHeight = 44;এবংtableView.rowHeight = UITableViewAutomaticDimension;
ইগোর

3
এটি চ্যাম্পের মতো কাজ করে ... সহজ এবং দক্ষ ... আপনাকে ধন্যবাদ। যদি কারও পক্ষে এটি কাজ না করে থাকে তবে সম্ভবত কারণটি হতে পারে, আমাদের সংগ্রহের ভিউটির নীচে টেবিল ভিউ সেলটির সাথে আবদ্ধ করতে হবে। তারপরে এটি কাজ শুরু করবে। শুভ কোডিং .. :)
সেবিন রায়

2
আইপ্যাড ঘোরানোর মাধ্যমে বলুন, স্ক্রিনটি পুনরায় আকার দেওয়া হলে এই কাজ করবে? এটি সম্ভাব্যভাবে সংগ্রহের দৃশ্যের উচ্চতা এবং সেইজন্য ঘরের উচ্চতা পরিবর্তন করতে পারে তবে অন-স্ক্রিনে সেলটি টেবিল ভিউ দ্বারা অগত্যা পুনরায় লোড করা নাও যেতে পারে, এভাবে সেলফোর্ডওএটিআইডেক্সপথকে কল না করে: পদ্ধতি এবং আপনাকে সুযোগ না দেওয়ার জন্য সীমাবদ্ধ ধ্রুবক পরিবর্তন। যদিও পুনরায় লোডডাটা জোর করে নেওয়া সম্ভব হতে পারে।
কার্ল লিন্ডবার্গ

2
আপনি কি বিভিন্ন সংগ্রহ ভিউ ঘরের আকারগুলি চেষ্টা করে দেখেছেন? আমার সমস্যা ছিল। আপনার কাছে যদি বিভিন্ন
সংগ্রহভিউর

22

উভয় সারণী দর্শন এবং সংগ্রহের দর্শনগুলি UIScrollViewসাবক্লাস এবং সুতরাং তারা সামগ্রীর আকারগুলি, পুনরায় ব্যবহারের ঘর ইত্যাদি গণনা করার চেষ্টা করার সাথে অন্য স্ক্রোল ভিউয়ের মধ্যে এম্বেড করা পছন্দ করে না they

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

আপনি এটি বিভাগগুলিতে বিভক্ত করতে পারেন এবং কিছু বিভাগের বিন্যাসকে একটি সারণী দর্শন হিসাবে এবং অন্যকে সংগ্রহের দৃশ্যের হিসাবে "ট্রিট" করতে পারেন। সর্বোপরি কোনও সংগ্রহের দৃশ্য দিয়ে আপনি অর্জন করতে পারবেন না এমন কোনও কিছুই নেই যা আপনি টেবিল দর্শন দিয়ে করতে পারেন।

আপনার সংগ্রহের "পার্টস" দেখার জন্য যদি আপনার গ্রিড বিন্যাস থাকে তবে আপনি সেগুলি হ্যান্ডেল করার জন্য নিয়মিত টেবিল কোষও ব্যবহার করতে পারেন। তবুও আপনার যদি আইওএস 5 সমর্থন প্রয়োজন না হয় আপনার আরও ভালভাবে সংগ্রহের ভিউগুলি ব্যবহার করা উচিত।


1
আপনি উদ্ধৃতিগুলিতে "ট্রিট" রেখেছেন, কেননা আপনি সংগ্রহেভিউ বিভাগে আলাদা আলাদা লেআউট সংজ্ঞায়িত করতে পারবেন না, তাই না? বিভিন্ন সংগ্রহ ভিউ বিভাগের জন্য আলাদা লেআউট সংজ্ঞায়িত করার বিকল্প আমি খুঁজে পাইনি। আমি কি কিছু উপেক্ষা করছি বা আপনি আমার নিজস্ব কাস্টম সাবক্লাসের ইউআইসি কলিকেশনভিউলাউআউটের বিভিন্ন বিভাগের জন্য 'লেআউটএট্রিবিউটস ফর আইটেমএটিএন্ডেক্সপথ' তে আলাদাভাবে প্রতিক্রিয়া দেওয়ার কথা বলছেন?
অ্যালেক্স দা ফ্র্যাঙ্কা

হ্যাঁ -> আপনি layoutAttributesForItemAtIndexPathআমার নিজস্ব কাস্টম সাবক্লাসের বিভিন্ন বিভাগের জন্য আলাদাভাবে প্রতিক্রিয়া দেওয়ার কথা বলছেন UICollectionViewLayout?
রিভেরা 14

2
@ রিভেরা, আপনার উত্তরটি সবচেয়ে যুক্তিসঙ্গত এবং ঠিক সঠিক বলে মনে হচ্ছে। আমি এই পরামর্শটি অনেক জায়গায় পড়েছি। আপনি কীভাবে এটি সম্পাদন করতে পারেন সে সম্পর্কে নমুনা বা টুটের কিছু লিঙ্ক ভাগ করে নিতে পারেন বা কমপক্ষে কিছু পয়েন্টার। টিআইএ
থিমস্মার্গাইন

3
আপনার উত্তর ধরে নিয়েছে যে আপনি স্ক্র্যাচ থেকে শুরু করছেন এবং ইতিমধ্যে আপনার কোনও বৃহত জটিল টেবিলভিউ নেই যা আপনাকে ফিট করতে হবে। সারণীদর্শনটিতে একটি কালেকটিভিউ রাখার বিষয়ে প্রশ্নটি বিশেষভাবে জিজ্ঞাসা করেছিল। IMO আপনার প্রতিক্রিয়া কোনও "উত্তর" নয়
xaphod

2
এটি একটি খারাপ উত্তর। সারণী দর্শনগুলির মধ্যে সংগ্রহের ভিউগুলি থাকা এমন একটি সাধারণ কাজ, প্রায় প্রতিটি অ্যাপ্লিকেশন এটি করে।
ক্র্যাশওভারাইড 777

10

উপরের পাবলো রোমুর উত্তর ( https://stackoverflow.com/a/33364092/2704206 ) আমার সমস্যাটিতে আমাকে অসীম সাহায্য করেছে। আমার সমস্যার জন্য এই কাজটি করার জন্য আমাকে কিছু আলাদাভাবে করতে হয়েছিল। প্রথমবার, আমাকে layoutIfNeeded()প্রায়শই কল করতে হয়নি । আমি শুধু তে এটি কল করতে ছিল collectionViewমধ্যে systemLayoutSizeFittingফাংশন।

দ্বিতীয়ত, আমার কিছু সংগ্রহের জন্য টেবিল ভিউ সেলটিতে আমার সংগ্রহ ভিউতে স্বয়ংক্রিয় বিন্যাসের সীমাবদ্ধতা ছিল। সুতরাং আমাকে এর প্রশস্ততা targetSize.widthনির্ধারণের সময় থেকে অগ্রণী এবং পেছনের মার্জিনগুলি বিয়োগ করতে হয়েছিল collectionView.frame। আমাকে ফেরতের মান CGSizeউচ্চতায় শীর্ষ এবং নীচের মার্জিনগুলিও যুক্ত করতে হয়েছিল ।

এই প্রতিবন্ধকতাগুলির ধ্রুবকগুলি পেতে, আমার কাছে হয় সীমাবদ্ধতায় আউটলেটগুলি তৈরি করা, তাদের ধ্রুবকগুলিকে কঠোর কোডিং করা বা কোনও সনাক্তকারী দ্বারা তাদের সন্ধানের বিকল্প ছিল। আমি আমার কাস্টম টেবিল ভিউ সেল ক্লাসটিকে সহজেই পুনরায় ব্যবহারযোগ্য করে তোলার জন্য তৃতীয় বিকল্পের সাথে যাওয়ার সিদ্ধান্ত নিয়েছি। শেষ পর্যন্ত, এটি কাজ করার জন্য আমার যা প্রয়োজন তা ছিল:

class CollectionTableViewCell: UITableViewCell {

    // MARK: -
    // MARK: Properties
    @IBOutlet weak var collectionView: UICollectionView! {
        didSet {
            collectionViewLayout?.estimatedItemSize = CGSize(width: 1, height: 1)
            selectionStyle = .none
        }
    }

    var collectionViewLayout: UICollectionViewFlowLayout? {
        return collectionView.collectionViewLayout as? UICollectionViewFlowLayout
    }

    // MARK: -
    // MARK: UIView functions
    override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
        collectionView.layoutIfNeeded()

        let topConstraintConstant = contentView.constraint(byIdentifier: "topAnchor")?.constant ?? 0
        let bottomConstraintConstant = contentView.constraint(byIdentifier: "bottomAnchor")?.constant ?? 0
        let trailingConstraintConstant = contentView.constraint(byIdentifier: "trailingAnchor")?.constant ?? 0
        let leadingConstraintConstant = contentView.constraint(byIdentifier: "leadingAnchor")?.constant ?? 0

        collectionView.frame = CGRect(x: 0, y: 0, width: targetSize.width - trailingConstraintConstant - leadingConstraintConstant, height: 1)

        let size = collectionView.collectionViewLayout.collectionViewContentSize
        let newSize = CGSize(width: size.width, height: size.height + topConstraintConstant + bottomConstraintConstant)
        return newSize
    }
}

সনাক্তকারী দ্বারা সীমাবদ্ধতা পুনরুদ্ধার করতে সহায়তাকারী হিসাবে আমি নিম্নলিখিত এক্সটেনশনটি যুক্ত করি:

extension UIView {
    func constraint(byIdentifier identifier: String) -> NSLayoutConstraint? {
        return constraints.first(where: { $0.identifier == identifier })
    }
}

দ্রষ্টব্য: আপনার স্টোরিবোর্ডে বা যেখানে যেখানেই তৈরি হচ্ছে সেখানে এই সীমাবদ্ধতার উপর আপনাকে সনাক্তকারী সেট করতে হবে। তাদের যদি 0 টি ধ্রুবক না থাকে তবে তা বিবেচনা করে না। এছাড়াও, পাবলোর প্রতিক্রিয়া অনুসারে, UICollectionViewFlowLayoutআপনার সংগ্রহ দর্শনটির জন্য আপনাকে বিন্যাস হিসাবে ব্যবহার করতে হবে । অবশেষে, নিশ্চিত করুন যে আপনি collectionViewআইবিআউটলেটটিকে আপনার স্টোরিবোর্ডের সাথে সংযুক্ত করেছেন।

উপরের কাস্টম টেবিল ভিউ সেল সহ, আমি এখন এটিকে অন্য যে কোনও টেবিল ভিউ সেলে সাবক্লাস করতে পারি যার জন্য সংগ্রহের ভিউ প্রয়োজন এবং এটি UICollectionViewDelegateFlowLayoutএবং UICollectionViewDataSourceপ্রোটোকলগুলি প্রয়োগ করতে পারে । আশা করি এটি অন্য কারও পক্ষে সহায়ক!


5

আমি সমস্ত উত্তর দিয়ে পড়েছি। এটি সমস্ত ক্ষেত্রে পরিবেশন করে বলে মনে হচ্ছে।

override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
        collectionView.layoutIfNeeded()
        collectionView.frame = CGRect(x: 0, y: 0, width: targetSize.width , height: 1)
        return collectionView.collectionViewLayout.collectionViewContentSize
}

3

পাবলো রোমিউর সমাধানের বিকল্প হ'ল টেবিল ভিউ সেলটিতে কাজ না করে নিজেই ইউআইসিএল্লেশনভিউটি কাস্টমাইজ করা।

অন্তর্নিহিত সমস্যাটি হ'ল ডিফল্টরূপে সংগ্রহের ভিউয়ের কোনও অভ্যন্তরীণ আকার থাকে না এবং ব্যবহারের জন্য মাত্রাগুলির স্বয়ংক্রিয় বিন্যাসকে অবহিত করতে পারে না। আপনি একটি কাস্টম সাবক্লাস তৈরি করে এটি প্রতিকার করতে পারেন যা দরকারী অভ্যন্তরীণ আকার দেয়।

ইউ আই সি কালেকশনভিউয়ের একটি সাবক্লাস তৈরি করুন এবং নিম্নলিখিত পদ্ধতিগুলিকে ওভাররাইড করুন

override func intrinsicContentSize() -> CGSize {
    self.layoutIfNeeded()

    var size = super.contentSize
    if size.width == 0 || size.height == 0 {
        // return a default size
        size = CGSize(width: 600, height:44)
    }

    return size
 }

override func reloadData() {
    super.reloadData()
    self.layoutIfNeeded()
    self.invalidateIntrinsicContentSize()
}

(আপনারও সম্পর্কিত পদ্ধতিগুলি ওভাররাইড করা উচিত: পুনরায় লোড করার জন্য একই পদ্ধতিতে রিলোডসেকশনস, রিলোডলোডসটিএন্টেক্সপেটস)

কলিং লেআউটআইএফএনপিড সংগ্রহের ভিউটিকে সামগ্রীর আকারটিকে পুনরায় গণনা করতে বাধ্য করে যা তারপরে নতুন অভ্যন্তরীণ আকার হিসাবে ব্যবহার করা যেতে পারে।

এছাড়াও, আপনি টেবিল ভিউ নিয়ন্ত্রকের মধ্যে দৃশ্য আকারের (উদাহরণস্বরূপ ডিভাইস রোটেশনে) পরিবর্তনগুলি হ্যান্ডেল করা দরকার

    override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
{
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
    dispatch_async(dispatch_get_main_queue()) {
        self.tableView.reloadData()
    }
}

ভাই আপনি কি দয়া করে আমার সমস্যার সাহায্য করতে পারবেন stackoverflow.com/questions/44650058/… ?
মে ফায়ু

3

আমি সম্প্রতি একই সমস্যার মুখোমুখি ছিলাম এবং আমি উত্তরগুলির প্রায় প্রতিটি সমাধান চেষ্টা করেছি, তাদের মধ্যে কিছু কাজ করেছে এবং অন্যরা @ পাবলোরোমিউ পদ্ধতির বিষয়ে আমার প্রধান উদ্বেগ নয় যে হ'ল যদি আপনার ঘরে অন্য বিষয়বস্তু থাকে (সংগ্রহের দৃশ্য ব্যতীত) আপনাকে তাদের উচ্চতা এবং তাদের সীমাবদ্ধতার উচ্চতা গণনা করতে হবে এবং অটো লেআউটটি সঠিকভাবে পেতে ফলাফলটি ফিরে আসতে হবে এবং আমি আমার কোডটিতে ম্যানুয়ালি জিনিস গণনা করতে পছন্দ করি না। সুতরাং এখানে আমার কোডটিতে কোনও ম্যানুয়াল গণনা না করে সমাধানটি আমার পক্ষে ভাল কাজ করেছে।

মধ্যে cellForRow:atIndexPathটেবিল ভিউ আমি নিচের কাজগুলো করুন:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    //do dequeue stuff
    //initialize the the collection view data source with the data
    cell.frame = CGRect.zero
    cell.layoutIfNeeded()
    return cell
}

আমি মনে করি এখানে কী ঘটে তা হ'ল সংগ্রহ দেখার উচ্চতা গণনা করার পরে আমি টেবিলভিউ সেলটিকে তার উচ্চতা সামঞ্জস্য করতে বাধ্য করি। (তথ্য উত্সে সংগ্রহের ভিউ তারিখ সরবরাহ করার পরে)


2

আমি সংগ্রহের ভিউ ক্লাসে একটি স্ট্যাটিক পদ্ধতি রাখব যা এতে থাকা সামগ্রীর উপর ভিত্তি করে একটি আকার ফিরিয়ে দেবে। তারপরে heightForRowAtIndexPathসঠিক আকারটি ফিরিয়ে আনতে সেই পদ্ধতিটি ব্যবহার করুন ।

এছাড়াও মনে রাখবেন যে আপনি যখন এই ধরণের ভিউ কনট্রোলারগুলি এম্বেড করেন তখন আপনি কিছু অদ্ভুত আচরণ পেতে পারেন। আমি এটি একবার করেছিলাম এবং কিছু অদ্ভুত স্মৃতি সমস্যা ছিল যা আমি কখনই কাজ করি নি।


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

2

হয়তো আমার রূপটি কার্যকর হবে; আমি গত দুই ঘন্টা এই কাজটি সিদ্ধান্ত নিয়েছি। আমি এটি 100% সঠিক বা সর্বোত্তম হওয়ার ভান করি না তবে আমার দক্ষতা এখনও খুব ছোট এবং আমি বিশেষজ্ঞদের কাছ থেকে মন্তব্য শুনতে চাই। ধন্যবাদ. একটি গুরুত্বপূর্ণ নোট: এটি স্থির টেবিলের জন্য কাজ করে - এটি আমার বর্তমান কাজ দ্বারা নির্দিষ্ট করা হয়েছে। সুতরাং, আমি ব্যবহার viewWillLayoutSubviews এর tableView । এবং আরও কিছুটা।

private var iconsCellHeight: CGFloat = 500 

func updateTable(table: UITableView, withDuration duration: NSTimeInterval) {
    UIView.animateWithDuration(duration, animations: { () -> Void in
        table.beginUpdates()
        table.endUpdates()
    })
}

override func viewWillLayoutSubviews() {
    if let iconsCell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 1)) as? CategoryCardIconsCell {
        let collectionViewContentHeight = iconsCell.iconsCollectionView.contentSize.height
        if collectionViewContentHeight + 17 != iconsCellHeight {
            iconsCellHeight = collectionViewContentHeight + 17
            updateTable(tableView, withDuration: 0.2)
        }
    }
}

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    switch (indexPath.section, indexPath.row) {
        case ...
        case (1,0):
            return iconsCellHeight
        default:
            return tableView.rowHeight
    }
}
  1. আমি জানি, যে সংগ্রহেভিউটি দ্বিতীয় বিভাগের প্রথম সারিতে অবস্থিত;
  2. সারিটির উচ্চতা 17 পি। এর সামগ্রীর উচ্চতার চেয়ে বড়;
  3. আইকনসেলহাইট প্রোগ্রামটি শুরু হওয়ার সাথে সাথে একটি এলোমেলো সংখ্যা (আমি জানি, প্রতিকৃতি আকারে এটি ঠিক 392 হওয়া উচিত, তবে এটি গুরুত্বপূর্ণ নয়)। যদি সংগ্রহ ভিউ + 17 এর সামগ্রীগুলি এই সংখ্যাটির সমান না হয়, তবে এর মানটি পরিবর্তন করুন। এই পরিস্থিতিতে পরবর্তী বারের জন্য শর্তটি মিথ্যা দেয়;
  4. সর্বোপরি টেবিলভিউ আপডেট করুন। আমার ক্ষেত্রে এটি দুটি ক্রিয়াকলাপের সংমিশ্রণ (সারি বাড়ানোর জন্য সুন্দর আপডেটের জন্য);
  5. এবং অবশ্যই, উচ্চতার জন্যRowAtIndexPath কোডে একটি সারি যুক্ত করুন।

2

আমি এ পর্যন্ত সবচেয়ে সহজ পদ্ধতির সাথে হাজির হয়েছি, উপরের উত্তরগুলিতে ক্রেডিট,

আপনার টেবিলভিউসেল ক্লাসে এটি সন্নিবেশ করান

override func layoutSubviews() {
    self.collectionViewOutlet.constant = self.postPoll.collectionViewLayout.collectionViewContentSize.height
}

এবং অবশ্যই, কক্ষের শ্রেণিতে আপনার আউটলেট দিয়ে কালেকশন ভিউলেটকে পরিবর্তন করুন


1
কক্ষের উচ্চতা সঠিকভাবে গণনা করে না
নিক কোভ

2

আমি @ ইগর পোস্ট থেকে ধারণা পেয়েছি এবং দ্রুততার সাথে আমার প্রকল্পের জন্য এটিতে আমার সময় বিনিয়োগ করি invest

এই গত আপনার

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    //do dequeue stuff
    cell.frame = tableView.bounds
    cell.layoutIfNeeded()
    cell.collectionView.reloadData()
    cell.collectionView.heightAnchor.constraint(equalToConstant: cell.collectionView.collectionViewLayout.collectionViewContentSize.height)
    cell.layoutIfNeeded()
    return cell
}

সংযোজন: কক্ষগুলি লোড করার সময় আপনি যদি আপনার ইউআইসিএল্লেশনভিউ চপ্পি দেখেন।

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {       
  //do dequeue stuff
  cell.layer.shouldRasterize = true
  cell.layer.rasterizationScale = UIScreen.main.scale
  return cell
}

0

পাবলো এর সমাধানটি আমার পক্ষে খুব ভাল কাজ করে নি, আমার অদ্ভুত ভিজ্যুয়াল এফেক্ট ছিল (সংগ্রহটি দেখুন সঠিকভাবে সামঞ্জস্য করা হচ্ছে না)।

যা কাজ করেছিল তা হ'ল কালেকশনভিউয়ের উচ্চতা সীমাবদ্ধতাটি (এনএসএলআউটআউট কনস্ট্রেন্ট হিসাবে) সংগ্রহের সময় ভিউ কন্টেন্টসাইজের সাথে সামঞ্জস্য করা layoutSubviews()। যখন সেলটিতে অটোলেআউট প্রয়োগ করা হয় তখন এ পদ্ধতিটি বলা হয়।

// Constraint on the collectionView height in the storyboard. Priority set to 999.
@IBOutlet weak var collectionViewHeightConstraint: NSLayoutConstraint!


// Method called by autolayout to layout the subviews (including the collectionView).
// This is triggered with 'layoutIfNeeded()', or by the viewController
// (happens between 'viewWillLayoutSubviews()' and 'viewDidLayoutSubviews()'.
override func layoutSubviews() {

    collectionViewHeightConstraint.constant = collectionView.contentSize.height
    super.layoutSubviews()
}

// Call `layoutIfNeeded()` when you update your UI from the model to trigger 'layoutSubviews()'
private func updateUI() {
    layoutIfNeeded()
}

-3

আপনার ইউআইটিএবল ভিউডেলিগেটে:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return ceil(itemCount/4.0f)*collectionViewCellHeight;
}

আসল মান সহ বিকল্প আইটেমকাউন্ট এবং সংগ্রহ ভিউচেলহাইট। আপনার যদি অ্যারে আইটেমের একটি অ্যারে থাকে তবে এটি হতে পারে:

self.items[indexPath.row].count

বা যাই হোক না কেন.


আমি মনে করি মূল প্রশ্নটি collectionViewCellHeight রেন্ডার হওয়ার আগে কীভাবে গণনা করা যায় to
থিমস্মাইনগাইন

-3

1. ডামি সেল তৈরি করুন।
২. বর্তমান তথ্য ব্যবহার করে ইউআইসিক্লিকেশনভিউয়ের ইউআইকোলিকেশনভিউ লেলআউটে সংগ্রহেভিউ কনটেন্টটাইজ পদ্ধতিটি ব্যবহার করুন।


এটি সর্বোত্তম উত্তর হওয়া উচিত ... যেহেতু ডামি কোষে সামগ্রীটি না রেখে 'ইউিকোলিকেশনভিউ' দিয়ে ঘরের উচ্চতা নির্ধারণের সম্ভাবনা নেই, উচ্চতা পাবেন এবং তারপরে এটি আবার সঠিক কোষে সেট করুন
বার্তোমিয়েজ সেম্যাকজেক

আমি কীভাবে এই পদ্ধতিটি ব্যবহার করব?
xtrinch

একটি উদাহরণ যুক্ত করুন।
নিক কোভ

-5

তোমার মত তার সম্পত্তি উপর ভিত্তি করে সংগ্রহ উচ্চতা নিরূপণ করতে পারেন itemSize, sectionInset, minimumLineSpacing, minimumInteritemSpacing, আপনার যদি collectionViewCellএকটি নিয়ম সীমানা হয়েছে।

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