ইউআইকোলিকেশনভিউ অটো লেআউট সহ সেলফ সাইজিং সেলগুলি দেখুন


207

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

আমি চেষ্টা করেছি সেটআপ এখানে:

  • UICollectionViewCellক সঙ্গে কাস্টমUITextView তার contentView হবে।
  • জন্য স্ক্রোলিং UITextViewপ্রতিবন্ধীদের অক্ষম।
  • কনটেন্টভিউয়ের অনুভূমিক সীমাবদ্ধতা হ'ল: "এইচ: | [_টেক্সটভিউ (320)]", অর্থাৎ UITextView 320 স্পষ্ট প্রস্থের সাথে ঘরের বাম দিকে পিন করা হয়েছে।
  • কনটেন্টভিউয়ের উল্লম্ব সীমাবদ্ধতা হ'ল: "ভি: | -0 - [_ পাঠ্য ভিউ]", অর্থাত্ UITextView ঘরের শীর্ষে পিন করা।
  • UITextViewউচ্চতা বাধ্যতা একটি ধ্রুবক যা এ সেট করা আছে UITextViewরিপোর্ট টেক্সট মাপসই করা হবে।

কক্ষের ব্যাকগ্রাউন্ডটি লাল সেট করা এবং UITextViewপটভূমিটি ব্লুতে সেট করা এর সাথে দেখতে দেখতে এটি এখানে : সেল ব্যাকগ্রাউন্ড লাল, UITextView ব্যাকগ্রাউন্ড নীল

আমি যে প্রকল্পটি নিয়ে গিটহাবের সাথে খেলছি তা এখানে রেখেছি ।


আপনি কি আকারের আইটেমএটিএন্ডেক্সপথ পদ্ধতিটি প্রয়োগ করছেন?
ড্যানিয়েল গালাস্কো

পছন্দ করুন আমার বোধগম্যতা হ'ল আইওএস 8-এ নতুন স্ব-আকারের কোষগুলির বৈশিষ্ট্যটির জন্য আপনাকে আর এটি করার দরকার নেই।
কাঁচাবি

আপনি কোথা থেকে এই তথ্যটি পেয়েছেন তা নিশ্চিত নন তবে আপনার এখনও দরকার, ডাব্লুডাব্লুডিসি সংক্ষিপ্ত বিবরণ
ড্যানিয়েল গালাস্কো

তবে আবার এটি আপনার ব্যবহারের ক্ষেত্রে নির্ভর করে, আপনি আনুমানিক
আইটেম সাইজ

1
2019 - এটি দেখার জন্য এটি প্রয়োজনীয়: stackoverflow.com/a/58108897/294884
ফ্যাটি

উত্তর:


309

সুইফট 5-এর জন্য আপডেট হয়েছে

preferredLayoutAttributesFittingAttributesপুনঃনামকরণ preferredLayoutAttributesFittingএবং অটো সাইজিং ব্যবহার করুন


সুইফট 4-র জন্য আপডেট হয়েছে

systemLayoutSizeFittingSize নামকরণ systemLayoutSizeFitting


আইওএস 9 এর জন্য আপডেট হয়েছে

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

টি এল; ডিআর

আমার গিটহাব প্রকল্পটি দেখুন


স্ব-আকার দেওয়ার ঘরগুলি কেবল প্রবাহের বিন্যাসের সাহায্যে সমর্থিত তাই আপনি যা ব্যবহার করছেন তা নিশ্চিত হন।

সেলফ সাইজিং সেলগুলি কাজ করার জন্য আপনাকে দুটি জিনিস সেটআপ করতে হবে।

1. সেট estimatedItemSizeকরুনUICollectionViewFlowLayout

আপনি estimatedItemSizeসম্পত্তি সেট করার পরে ফ্লো লেআউট প্রকৃতির গতিশীল হয়ে উঠবে ।

self.flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize

২. আপনার সেল সাবক্লাসে আকার দেওয়ার জন্য সমর্থন যোগ করুন

এটি 2 স্বাদে আসে; স্ব-লেআউট বা কাস্টম ওভাররাইড preferredLayoutAttributesFittingAttributes

অটো লেআউট দিয়ে সেলগুলি তৈরি এবং কনফিগার করুন

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

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

বাস্তবায়ন preferredLayoutAttributesFittingAttributesআপনার কাস্টম ঘরে

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

//forces the system to do one layout pass
var isHeightCalculated: Bool = false

override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
    //Exhibit A - We need to cache our calculation to prevent a crash.
    if !isHeightCalculated {
        setNeedsLayout()
        layoutIfNeeded()
        let size = contentView.systemLayoutSizeFitting(layoutAttributes.size)
        var newFrame = layoutAttributes.frame
        newFrame.size.width = CGFloat(ceilf(Float(size.width)))
        layoutAttributes.frame = newFrame
        isHeightCalculated = true
    }
    return layoutAttributes
}

দ্রষ্টব্য আইওএস 9-তে আচরণটি কিছুটা বদলেছে যা আপনি যদি সাবধান না হন তবে আপনার বাস্তবায়নের উপর ক্র্যাশ ঘটতে পারে (আরও দেখুন এখানে )। আপনি যখন প্রয়োগ করেন তখন আপনাকে preferredLayoutAttributesFittingAttributesঅবশ্যই নিশ্চিত করতে হবে যে আপনি একবার কেবল আপনার বিন্যাসের বৈশিষ্ট্যের ফ্রেম পরিবর্তন করেছেন। আপনি যদি এটি না করেন তবে লেআউটটি আপনার প্রয়োগটিকে অনির্দিষ্টকালের জন্য ডেকে আনে এবং শেষ পর্যন্ত ক্রাশ হবে। একটি সমাধান হ'ল আপনার কক্ষের গণনা করা আকারটি ক্যাশে করা এবং আপনি যখনই ঘরটি পুনরায় ব্যবহার করেন বা যে বিষয়বস্তুটি আমি দিয়ে করেছি তেমন পরিবর্তন করে এটিকে অবৈধ করুন toisHeightCalculated সম্পত্তি ।

আপনার বিন্যাস অভিজ্ঞতা

এই মুহুর্তে আপনার সংগ্রহেভিউতে আপনার 'কার্যকরী' গতিশীল কক্ষ থাকা উচিত। আমার পরীক্ষাগুলির সময় আমি আউট-অফ-বাক্সের সমাধানটি পর্যাপ্তরূপে খুঁজে পাই নি তাই আপনার কাছে থাকলে নির্দ্বিধায় মন্তব্য করুন। এখনও মনে হচ্ছেUITableView গতিশীল আকারের আইএমএইচও-র যুদ্ধে জয়লাভ করে।

আদেশ সহকারে

খুব সচেতন থাকুন যে আপনি যদি আনুমানিক আইটেম সাইজ গণনা করতে প্রোটোটাইপ সেল ব্যবহার করেন - আপনার XIB আকারের ক্লাস ব্যবহার করে তবে এটি ভেঙে যাবে । এর কারণ হ'ল আপনি যখন আপনার সেলটি XIB থেকে লোড করবেন তখন এর আকারের শ্রেণিটি কনফিগার করা হবে Undefined। এটি কেবল আইওএস 8 এ বিভক্ত হবে এবং আইওএস 7-র পরে সাইজের ক্লাসটি ডিভাইসের উপর ভিত্তি করে লোড করা হবে (আইপ্যাড = নিয়মিত-কোনও, আইফোন = কমপ্যাক্ট-যেকোন)। আপনি হয় এক্সআইবি লোড না করে আনুমানিক আইটেম সাইজ সেট করতে পারেন, বা আপনি এক্সআইবি থেকে সেলটি লোড করতে পারেন, এটি কালেকশনভিউতে যুক্ত করতে পারেন (এটি বৈশিষ্ট্য সংকলনটি সেট করবে), বিন্যাসটি সম্পাদন করতে পারে এবং তারপরে তদারকির দৃশ্য থেকে অপসারণ করতে পারে। বিকল্পভাবে আপনি নিজের ঘরটি traitCollectionগেটকে ওভাররাইড করতে এবং উপযুক্ত বৈশিষ্ট্যগুলিও ফিরিয়ে দিতে পারেন। এটা আপনার উপর নির্ভর করছে.

আমি যদি কিছু মিস করি তবে আমাকে জানান, আশা করি আমি সহায়তা করেছি এবং ভাগ্য ভালো কোডিং



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

@ ইন্না আপনি কি লেআউটটিতে অবৈধ লেআউটকে ফোন করছেন?
ড্যানিয়েল গালাস্কো

1
আহ, পার্থক্যটি খুঁজে পেয়েছি, আপনি আনুমানিক উচ্চতা নির্ধারণ করেছেন উচ্চতর (400) যেখানে আমি সর্বনিম্ন (44) করছি। যে সাহায্য করেছে। তবে কন্টেন্টসাইজটি এখনও পুরোপুরি স্ক্রোল না করা পর্যন্ত সঠিকভাবে সেট করা হবে না বলে মনে হচ্ছে, তবুও খুব ব্যবহারযোগ্য নয়। বিটিডব্লিউ, আমি ইউআইটিেক্সটভিউকে ইউআইএলবেলে পরিবর্তন করেছি, একই আচরণ।
আন্না

17
এটি আইওএস 9 জিএম এ মূলত ভেঙে গেছে বলে মনে হচ্ছে। সেট estimatedItemSizeক্র্যাশ করার বিশালাকার - সেখানে কিভাবে স্বয়ংক্রিয় বিন্যাস UICollectionViewCell প্রক্রিয়া করার চেষ্টা করছে কিছু বিশাল বাগ মনে করা হয়।
ওয়েস ক্যাম্পেইগেন

3
অনুরূপ ইস্যুতে চলছে, কেউ কি আশেপাশে কোনও কাজ খুঁজে পেয়েছে?
টনি

47

আইওএস 10 তে নতুন ধ্রুবক বলা হয় UICollectionViewFlowLayout.automaticSize(পূর্বে UICollectionViewFlowLayoutAutomaticSize), সুতরাং পরিবর্তে:

self.flowLayout.estimatedItemSize = CGSize(width: 100, height: 100)

আপনি এটি ব্যবহার করতে পারেন:

self.flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize

এটির জন্য আরও ভাল পারফরম্যান্স রয়েছে বিশেষত যখন আপনার সংগ্রহের ভিউগুলিতে ধ্রুব প্রশস্ত হয়

প্রবাহ বিন্যাস অ্যাক্সেস করা:

override func viewDidLoad() {
   super.viewDidLoad()

   if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
      flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
   }
}

সুইফট 5 আপডেট হয়েছে:

override func viewDidLoad() {
   super.viewDidLoad()

   if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
      flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
    }
}

8
আপনি কোথায় সেট করেন? ভিউডিডলোডে? কীভাবে আপনি ফ্লোলেআউটে একটি হ্যান্ডেল পাবেন?
ইউকেডাটাগীক

1
আমি এটি বাস্তবায়ন করতে সক্ষম হয়েছি - তবে এটির একটি অদ্ভুত আচরণ রয়েছে যা যদি একটি একক কোষ থাকে তবে এটি সেলগুলিকে কেন্দ্র করে তোলে। : - এখানে এটি সম্পর্কে স্ট্যাক ওভারফ্লো প্রশ্ন হল আমার তুলবেন হয়েছে stackoverflow.com/questions/43266924/...
UKDataGeek

1
আপনি সংগ্রহ collectionViewLayoutUICollectionViewFlowLayout
ভিউগুলির

4
এটি আমার কোষগুলিকে খুব ছোট, অকেজো করে তোলে
user924

44

ড্যানিয়েল গালাসকো উত্তরের কয়েকটি মূল পরিবর্তনগুলি আমার সমস্ত সমস্যার সমাধান করে। দুর্ভাগ্যক্রমে, আমার সরাসরি মন্তব্য করার মতো যথেষ্ট খ্যাতি নেই (এখনও)।

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

আপনার কক্ষের উপস্থিতিটি কনফিগার করতে, ডেটা আইটেমের সামগ্রীটি উপস্থাপনা হিসাবে কনটেন্টভিউয়ের সম্পত্তিতে উপস্থাপনের জন্য উপস্থাপন করার জন্য প্রয়োজনীয় ভিউগুলি যুক্ত করুন। সরাসরি ঘরে নিজেই সাবভিউ যুক্ত করবেন না।

তারপরে সম্পূর্ণভাবে পদক্ষেপ 3 এড়িয়ে যান। এটি প্রয়োজন হয় না।


1
মজাদার; এটি বিশেষত Xibs এর জন্য তবে তবুও ধন্যবাদ, চেষ্টা করবে এবং গিথুব প্রকল্পের সাথে ঝামেলা করবে এবং দেখুন আমি পুনরুত্পাদন করতে পারি কিনা। হতে পারে উত্তরটি Xib বনাম প্রোগ্রামেমেটে ভাগ করুন
ড্যানিয়েল গালাসকো

খুব উপকারী . ধন্যবাদ!
প্রব্লমস্লোভার

2
আইওএস 9, এক্সকোড Ce. কক্ষগুলি স্টোরিবোর্ডে প্রোটোপড হয়, কাস্টম সাবক্লাস সেট করে। নামক একটি সম্পত্তি তৈরি করার চেষ্টা করা হয়েছিল contentView, এক্সকোড অভিযোগ করে যে এটি বিদ্যমান সম্পত্তির সাথে সাংঘর্ষিক। এতে সাবউভিউ যুক্ত করার চেষ্টা করেছে self.contentViewএবং এতে সীমাবদ্ধতা সেট করে, তারপরে অ্যাপ ক্র্যাশ হয়।
নিকোলাস মিয়ারি

@ নিকোলাসমিয়ারি আমি এই প্রোগ্রামটিমেটিক্যালি কীভাবে করব সে সম্পর্কে আমি জানিনা, আমার সমাধানটি আসলে XIB- তে একটি একক ইউভিউউ যুক্ত করা যেখানে সমস্ত কিছু এর ভিতরে চলে। আপনার কোনও সম্পত্তি বা কিছু তৈরি করার দরকার নেই।
ম্যাট কোয়ালা

আমি @ নিকোলাসমিয়ারির মতো একই সমস্যার মুখোমুখি। আমি যখন iOS 9 এর / Xcode 7 স্বয়ংক্রিয়-বহির্বিন্যাস সীমাবদ্ধতার সঙ্গে স্টোরিবোর্ড মধ্যে prototyped কোষ জন্য estimatedContentSize সেট অ্যাপ্লিকেশন একটি খারাপ এক্সেস ব্যতিক্রম এবং কোন সহায়ক ক্ষেত্রে স্টেকট্র্যাস সঙ্গে বিপর্যস্ত
ওয়াসাবি

34

আইওএস 10+ এ এটি খুব সাধারণ 2 ধাপের প্রক্রিয়া।

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

  2. আপনার ইউআইকোলিকেশনভিউয়ের ফ্লোলেআউটটি স্বয়ংক্রিয়ভাবে আকারে নির্দেশ দিন

    yourFlowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize

আমি কৌতূহলী, কোনও ইউআইভিউতে আপনার ঘরগুলির সামগ্রী মোড়ানো কীভাবে অটো লেআউটকে আরও কার্যকর করতে সক্ষম করবে? আইডি ভেবেছে যে এটি আরও অগভীর শ্রেণিবিন্যাসের সাথে আরও ভাল সম্পাদন করবে?
জেমস হিল্ড

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

আপনি কী দয়া করে আমাকে বলতে পারবেন কীভাবে উচ্চতা ধ্রুবক সেট করতে হবে (যেমন উচ্চতার সেট 25) এবং প্রস্থটি স্বয়ংক্রিয়ভাবে পরিবর্তিত হবে) UICollectionViewFlowLayoutAutomaticSize এর জন্য।
ZhengGe চে

সুইফট ৪.১ ব্যবহার করে, এক্সকোড জানায় যে আমার UICollectionViewFlowLayout.automaticSizeনামকরণ হয়েছে UICollectionViewFlowLayoutAutomaticSize
লিনাসগেফার্থ

14
  1. ভিডলিডলয়েডে ফ্লোলয়আউট যুক্ত করুন ()

    override func viewDidLoad() {
        super.viewDidLoad() 
        if let flowLayout = infoCollection.collectionViewLayout as? UICollectionViewFlowLayout {
            flowLayout.estimatedItemSize = CGSize(width: 1, height:1)
        }
    }
  2. এছাড়াও, আপনার ঘরের জন্য একটি ইউআইভিউউকে মূল কনটেনার হিসাবে সেট করুন এবং এর ভিতরে সমস্ত প্রয়োজনীয় দর্শন যুক্ত করুন add

  3. আরও রেফারেন্সের জন্য এই দুর্দান্ত, মাইন্ড- ব্লাইং টিউটোরিয়ালটি দেখুন: আইওএস 9 এবং 10 এ অটোলেআউট ব্যবহার করে অটোসাইজিং সেল সহ ইউআইকোলিকেশনভিউ


11

সম্পাদনা 11/19/19: আইওএস 13 এর জন্য, আনুমানিক উচ্চতা সহ কেবল ইউআইকোলিকেশনভিউকম্পোজেনাল লেআউট ব্যবহার করুন। এই ভাঙা এপিআই নিয়ে কাজ করে আপনার সময় নষ্ট করবেন না।

কিছু সময়ের জন্য এটির সাথে লড়াই করার পরে, আমি লক্ষ্য করেছি যে আপনি স্ক্রলিংটি অক্ষম না করে রাখলে UITextViews এর জন্য আকার পরিবর্তন করা কার্যকর হয় না:

let textView = UITextView()
textView.scrollEnabled = false

আমি যখন স্ক্রোল করার চেষ্টা করি তখন সংগ্রহ ভিউ সেলটি মসৃণ হয় না। আপনার কি এর কোনও সমাধান আছে?
সতীশ কুমার গুরুনাথন

6

সামগ্রী দেখুন অ্যাঙ্কর রহস্য:

একটি উদ্ভট ক্ষেত্রে এটি

    contentView.translatesAutoresizingMaskIntoConstraints = false

কাজ করবে না। কনটেন্টভিউতে চারটি সুস্পষ্ট অ্যাঙ্কর যুক্ত হয়েছে এবং এটি কার্যকর হয়েছে।

class AnnoyingCell: UICollectionViewCell {
    
    @IBOutlet var word: UILabel!
    
    override init(frame: CGRect) {
        super.init(frame: frame); common() }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder); common() }
    
    private func common() {
        contentView.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            contentView.leftAnchor.constraint(equalTo: leftAnchor),
            contentView.rightAnchor.constraint(equalTo: rightAnchor),
            contentView.topAnchor.constraint(equalTo: topAnchor),
            contentView.bottomAnchor.constraint(equalTo: bottomAnchor)
        ])
    }
}

এবং যথারীতি

    estimatedItemSize = UICollectionViewFlowLayout.automaticSize

ভিতরে YourLayout: UICollectionViewFlowLayout

কে জানে? কাউকে সাহায্য করতে পারে।

ধার

https://www.vadimbulavin.com/collection-view-cells-self-sizing/

সেখানে টিপকে হোঁচট খেয়েছে - এটির সমস্ত নিবন্ধে এটি আর কোথাও দেখেনি।


3

আমি সংগ্রহের দৃশ্যের একটি গতিশীল কক্ষের উচ্চতা করেছি। এখানে গিট হাব রেপো

এবং, কেন পছন্দসই লেআউটঅ্যাট্রিবিউটস ফিটিংঅ্যাট্রিবিউটসকে একাধিকবার বলা হয় তা সন্ধান করুন। আসলে, এটি কমপক্ষে 3 বার বলা হবে।

কনসোল লগ ছবি: এখানে চিত্র বর্ণনা লিখুন

1 ম preferredLayoutAttributesFittingAttributes :

(lldb) po layoutAttributes
<UICollectionViewLayoutAttributes: 0x7fa405c290e0> index path: (<NSIndexPath:    0xc000000000000016> 
{length = 2, path = 0 - 0}); frame = (15 12; 384 57.5); 

(lldb) po self.collectionView
<UICollectionView: 0x7fa40606c800; frame = (0 57.6667; 384 0);

লেআউটএট্রিবিউটস.ফ্রেম.সাইজ.হাইটি বর্তমান অবস্থা 57.5

2 য় পছন্দসই লেআউটঅ্যাট্রিবিউটস ফিটিংঅ্যাট্রিবিউটস :

(lldb) po layoutAttributes
<UICollectionViewLayoutAttributes: 0x7fa405c16370> index path: (<NSIndexPath: 0xc000000000000016> 
{length = 2, path = 0 - 0}); frame = (15 12; 384 534.5); 

(lldb) po self.collectionView
<UICollectionView: 0x7fa40606c800; frame = (0 57.6667; 384 0);

আমাদের প্রত্যাশা অনুযায়ী কক্ষের ফ্রেমের উচ্চতা 534.5 এ পরিবর্তিত হয়েছে । তবে, সংগ্রহের দৃশ্যটি এখনও শূন্যের উচ্চতায়।

3 য় পছন্দসই লেআউটআট্রিবিউটস ফিটিংঅ্যাট্রিবিউটস :

(lldb) po layoutAttributes
<UICollectionViewLayoutAttributes: 0x7fa403d516a0> index path: (<NSIndexPath: 0xc000000000000016> 
{length = 2, path = 0 - 0}); frame = (15 12; 384 534.5); 

(lldb) po self.collectionView
<UICollectionView: 0x7fa40606c800; frame = (0 57.6667; 384 477);

আপনি দেখতে পারবেন সংগ্রহের ভিউয়ের উচ্চতা 0 থেকে 477 এ পরিবর্তিত হয়েছিল

আচরণটি হ্যান্ডল স্ক্রোলের অনুরূপ:

1. Before self-sizing cell

2. Validated self-sizing cell again after other cells recalculated.

3. Did changed self-sizing cell

শুরুতে, আমি এই পদ্ধতিটি কেবল একবার কল করেছিলাম। সুতরাং আমি নিম্নলিখিত হিসাবে কোডেড:

CGRect frame = layoutAttributes.frame;
frame.size.height = frame.size.height + self.collectionView.contentSize.height;
UICollectionViewLayoutAttributes* newAttributes = [layoutAttributes copy];
newAttributes.frame = frame;
return newAttributes;

এই লাইন:

frame.size.height = frame.size.height + self.collectionView.contentSize.height;

সিস্টেম কল অসীম লুপ এবং অ্যাপ ক্র্যাশ ঘটায়।

যে কোনও আকার পরিবর্তিত হয়েছে, এটি সমস্ত কক্ষের পছন্দসই লেআউটঅ্যাট্রিবিউটস ফিটিংঅ্যাট্রিবিউটগুলিকে বারবার বৈধ করে দেবে যতক্ষণ না প্রতিটি ঘরের অবস্থান (অর্থাৎ ফ্রেম) এর বেশি পরিবর্তন হয় না।


2

উপরের উত্তর ছাড়াও,

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

এটাই.


1

আপনি যদি ইউআইসি কলিকেশনভিউডেলিগেটফ্লোএলআউট পদ্ধতিটি প্রয়োগ করেন:

- (CGSize)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath*)indexPath

আপনি যখন কল করবেন তখন এর পরিবর্তে collectionview performBatchUpdates:completion:আকারের উচ্চতা ব্যবহার করবে ।sizeForItemAtIndexPathpreferredLayoutAttributesFittingAttributes

এর রেন্ডারিং প্রক্রিয়াটি performBatchUpdates:completionপদ্ধতিটি দিয়ে যাবে preferredLayoutAttributesFittingAttributesতবে এটি আপনার পরিবর্তনগুলি উপেক্ষা করে।


আমি এই দুর্ব্যবহারটি দেখেছি তবে অনুমিত আকারটি শূন্য হলেই। আপনি কি নিশ্চিত যে আপনি একটি আনুমানিক আকার নির্ধারণ করছেন?
ডিগাটউড

1

যার জন্য এটি সহায়তা করতে পারে,

যদি estimatedItemSizeসেট করা থাকে তবে আমার সেই বাজে ক্রাশ হয়েছিল। এমনকি আমি 0 এ ফিরে এসেছি এমনকি যদি numberOfItemsInSection। সুতরাং, সেলগুলি নিজেরাই এবং তাদের অটো-লেআউট ক্র্যাশ হওয়ার কারণ ছিল না ... কালেকশনভিউ খালি থাকা অবস্থায়ও ক্র্যাশ estimatedItemSizeহয়েছিল , কেবলমাত্র স্ব-আকার দেওয়ার জন্য সেট করা হয়েছিল।

আমার ক্ষেত্রে আমি আমার প্রকল্পটি, একটি সংগ্রাহক ভিউ কন্ট্রোলার সহ একটি কন্ট্রোলার থেকে কন্ট্রোল ভিউ কনট্রোলার পর্যন্ত পুনর্গঠিত করেছি এবং এটি কাজ করেছে।

চিত্রে যান.


1
collectionView.collectionViewLayout.invalidateLayout()পরে ফোন করার চেষ্টা করুন collectionView.reloadData()
চেঙ্গসাম

ios10 জন্য এবং নীচের এই কোডটি `ওভাররাইড func viewWillLayoutSubviews () যোগ করুন {super.viewWillLayoutSubviews যদি #available () (প্রয়োজন iOS 11.0, *) {} আর {mainCollectionView.collectionViewLayout.invalidateLayout ()}} '
Marosdee উমা

1

যে কেউ ভাগ্য ছাড়াই সবকিছু চেষ্টা করেছিলেন, তার পক্ষে এটিই আমার জন্য কাজ করে। ঘরের অভ্যন্তরে মাল্টলাইন লেবেলের জন্য, এই যাদু লাইনটি যুক্ত করার চেষ্টা করুন:

label.preferredMaxLayoutWidth = 200

আরও তথ্য: এখানে

চিয়ার্স!


0

উপরের উদাহরণ পদ্ধতিটি সংকলন করে না। এখানে একটি সংশোধিত সংস্করণ রয়েছে (তবে এটি কাজ করে কি না তা নির্বিঘ্নিত))

override func preferredLayoutAttributesFittingAttributes(layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes 
{
    let attr: UICollectionViewLayoutAttributes = layoutAttributes.copy() as! UICollectionViewLayoutAttributes

    var newFrame = attr.frame
    self.frame = newFrame

    self.setNeedsLayout()
    self.layoutIfNeeded()

    let desiredHeight: CGFloat = self.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
    newFrame.size.height = desiredHeight
    attr.frame = newFrame
    return attr
}

0

আরও তথ্য আপডেট করুন:

  • আপনি যদি ব্যবহার করেন তবে flowLayout.estimatedItemSizeiOS8.3 এর পরবর্তী সংস্করণটি ব্যবহার করার পরামর্শ দিন। IOS8.3 এর আগে এটি ক্রাশ হবে [super layoutAttributesForElementsInRect:rect];। ত্রুটি বার্তাটি হ'ল

    *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'

  • দ্বিতীয়ত, iOS8.x সংস্করণে, flowLayout.estimatedItemSizeবিভিন্ন বিভাগের ইনসেট সেটিংস কাজ করে না। অর্থাত ফাংশন: (UIEdgeInsets)collectionView:layout:insetForSectionAtIndex:


0

সমাধানটিতে 4 টি গুরুত্বপূর্ণ পদক্ষেপ রয়েছে:

  1. গতিশীল কক্ষের আকার নির্ধারণ সক্ষম করা

flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize

  1. contentViewঘরের প্রান্তগুলিতে স্পষ্টভাবে অটো লেআউট এবং পিনটি সক্ষম করুন কারণ এতে স্বয়ংক্রিয় বিন্যাস সক্ষম না থাকা সত্ত্বেও contentViewস্ব-আকার নির্ধারণ করে।
class MultiLineCell: UICollectionViewCell{

    private var textViewHeightContraint: NSLayoutConstraint!

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .cyan
        contentView.translatesAutoresizingMaskIntoConstraints = false
        contentViewWidthAnchor = contentView.widthAnchor.constraint(equalToConstant: 0)

        NSLayoutConstraint.activate([
            contentView.leadingAnchor.constraint(equalTo: leadingAnchor),
            contentView.topAnchor.constraint(equalTo: topAnchor),
            contentView.trailingAnchor.constraint(equalTo: trailingAnchor),
            contentView.bottomAnchor.constraint(equalTo: bottomAnchor),
        ])
    } 
    ...
}
  1. কনটেন্টভিউয়ের সংক্ষিপ্তসারের collectionView(:cellForItemAt:)প্রস্থের মধ্যে সীমাবদ্ধ করতে কন্টেন্টভিউ.উইথঅনচর কোডসর্ট সেট করুন V

এটি নিম্নলিখিত হিসাবে ঘটে; আমরা ক্যালকের ভেরিয়েবলটি কালেকশনভিউর maxWidthপ্রস্থে collectionView(:cellForItemAt:)এবং maxWidthএর didSetপদ্ধতিতে সেট করব এবং আমরা প্রস্থআন্টর কোডসিস্ট্যান্টকে ম্যাক্সউইথথায় সেট করব।

class ViewController: UIViewController, UICollectionViewDataSource {
    ...

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! MultiLineCell
        cell.textView.text = dummyTextMessages[indexPath.row]
        cell.maxWidth = collectionView.frame.width
        return cell
    }

    ...
}
class MultiLineCell: UICollectionViewCell{
    ....

    var maxWidth: CGFloat? {
        didSet {
            guard let maxWidth = maxWidth else {
                return
            }
            contentViewWidthAnchor.constant = maxWidth
            contentViewWidthAnchor.isActive = true
        }
    }

    ....
}

আপনি যেহেতু ইউআইটিেক্সটভিউয়ের স্ব-আকার নির্ধারণ করতে সক্ষম করতে চান তাই এটির একটি অতিরিক্ত পদক্ষেপ রয়েছে;

4. গণনা করুন এবং ইউআইটিেক্সটভিউয়ের উচ্চতাআঙ্কর.কন্ট্যান্ট সেট করুন।

সুতরাং, যখনই contentView প্রস্থ সেট করা হয় আমরা বরাবর UITextView উচ্চতা সামঞ্জস্য করব didSetএর maxWidth

ইউআইসি কলিকেশনভিউসেল এর অভ্যন্তরে:

var maxWidth: CGFloat? {
    didSet {
        guard let maxWidth = maxWidth else {
            return
        }
        contentViewWidthAnchor.constant = maxWidth
        contentViewWidthAnchor.isActive = true

        let sizeToFitIn = CGSize(width: maxWidth, height: CGFloat(MAXFLOAT))
        let newSize = self.textView.sizeThatFits(sizeToFitIn)
        self.textViewHeightContraint.constant = newSize.height
    }
}

এই পদক্ষেপগুলি আপনার পছন্দসই ফলাফল পাবে। এখানে একটি সম্পূর্ণ চলমান টোকা

ভাদিম বুলাভিনকে তার পরিষ্কার এবং আলোকিত ব্লগ পোস্টের জন্য ধন্যবাদ - সংগ্রহ ভিউ সেলগুলি সেলফ-সাইজিং: স্টেপ বাই স্টেপ টিউটোরিয়াল


-2

আমি ব্যবহারের চেষ্টা করেছি estimatedItemSizeতবে ঘরগুলি সন্নিবেশ করানোর সময় এবং মুছার সময় অনেকগুলি বাগ উপস্থিত estimatedItemSizeছিল যদি ঘরের উচ্চতার সমান না হয়। আমি estimatedItemSizeপ্রোটোটাইপ সেল ব্যবহার করে গতিশীল কক্ষগুলি সেট করা এবং প্রয়োগ করেছি। এখানে এটি কিভাবে সম্পন্ন:

এই প্রোটোকলটি তৈরি করুন:

protocol SizeableCollectionViewCell {
    func fittedSize(forConstrainedSize size: CGSize)->CGSize
}

আপনার প্রথাতে এই প্রোটোকলটি প্রয়োগ করুন UICollectionViewCell:

class YourCustomCollectionViewCell: UICollectionViewCell, SizeableCollectionViewCell {

    @IBOutlet private var mTitle: UILabel!
    @IBOutlet private var mDescription: UILabel!
    @IBOutlet private var mContentView: UIView!
    @IBOutlet private var mTitleTopConstraint: NSLayoutConstraint!
    @IBOutlet private var mDesciptionBottomConstraint: NSLayoutConstraint!

    func fittedSize(forConstrainedSize size: CGSize)->CGSize {

        let fittedSize: CGSize!

        //if height is greatest value, then it's dynamic, so it must be calculated
        if size.height == CGFLoat.greatestFiniteMagnitude {

            var height: CGFloat = 0

            /*now here's where you want to add all the heights up of your views.
              apple provides a method called sizeThatFits(size:), but it's not 
              implemented by default; except for some concrete subclasses such 
              as UILabel, UIButton, etc. search to see if the classes you use implement 
              it. here's how it would be used:
            */
            height += mTitle.sizeThatFits(size).height
            height += mDescription.sizeThatFits(size).height
            height += mCustomView.sizeThatFits(size).height    //you'll have to implement this in your custom view

            //anything that takes up height in the cell has to be included, including top/bottom margin constraints
            height += mTitleTopConstraint.constant
            height += mDescriptionBottomConstraint.constant

            fittedSize = CGSize(width: size.width, height: height)
        }
        //else width is greatest value, if not, you did something wrong
        else {
            //do the same thing that's done for height but with width, remember to include leading/trailing margins in calculations
        }

        return fittedSize
    }
}

এখন আপনার নিয়ামকটিকে UICollectionViewDelegateFlowLayoutএই ক্ষেত্রের সাথে সামঞ্জস্য করুন এবং এতে:

class YourViewController: UIViewController, UICollectionViewDelegateFlowLayout {
    private var mCustomCellPrototype = UINib(nibName: <name of the nib file for your custom collectionviewcell>, bundle: nil).instantiate(withOwner: nil, options: nil).first as! SizeableCollectionViewCell
}

এটি ডেটা বেঁধে রাখতে প্রোটোটাইপ সেল হিসাবে ব্যবহৃত হবে এবং তারপরে নির্ধারণ করা হবে যে কীভাবে ডেটা আপনার গতিশীল হতে চায় সেই মাত্রাটিকে কীভাবে প্রভাবিত করেছে

অবশেষে, UICollectionViewDelegateFlowLayout's collectionView(:layout:sizeForItemAt:)বাস্তবায়ন করতে হবে:

class YourViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {

    private var mDataSource: [CustomModel]

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath)->CGSize {

        //bind the prototype cell with the data that corresponds to this index path
        mCustomCellPrototype.bind(model: mDataSource[indexPath.row])    //this is the same method you would use to reconfigure the cells that you dequeue in collectionView(:cellForItemAt:). i'm calling it bind

        //define the dimension you want constrained
        let width = UIScreen.main.bounds.size.width - 20    //the width you want your cells to be
        let height = CGFloat.greatestFiniteMagnitude    //height has the greatest finite magnitude, so in this code, that means it will be dynamic
        let constrainedSize = CGSize(width: width, height: height)

        //determine the size the cell will be given this data and return it
        return mCustomCellPrototype.fittedSize(forConstrainedSize: constrainedSize)
    }
}

এবং এটাই. এইভাবে কক্ষের আকারটি collectionView(:layout:sizeForItemAt:)ফিরিয়ে দেওয়া আমাকে ব্যবহার করতে বাধা দেয় estimatedItemSizeএবং ঘরগুলি সন্নিবেশ করানো এবং মোছার কাজটি পুরোপুরি কার্যকরভাবে কাজ করে।

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