ios - استخدام تخطيط السيارات في إيتاتفيو لتخطيطات الخلية الحيوية وارتفاعات الصف المتغير


كيف تستخدم التخطيط التلقائي داخل UITableViewCell s في طريقة عرض جدول للسماح لمحتوى كل خلية ومعاينات فرعية بتحديد ارتفاع الصف (نفسه / تلقائيا)، مع الحفاظ على أداء التمرير السلس؟



Answers


تل؛ در: لا أحب القراءة؟ القفز مباشرة إلى المشاريع عينة على جيثب:

الوصف المفاهيمي

يتم تطبيق أول خطوتين أدناه بغض النظر عن إصدارات يوس التي تقوم بتطويرها.

1. إعداد وإضافة القيود

في الفئة الفرعية UITableViewCell الخاص بك، إضافة القيود بحيث تكون لمحات فرعية للخلية حوافها مثبتة على حواف محتوى الخليةالصورة (الأهم إلى أعلى والحواف السفلية). ملاحظة: لا تعلق معاينات على الخلية نفسها. فقط إلى contentView الخلية! السماح لحجم المحتوى الجوهري لهذه المشاهدات الفرعية دفع ارتفاع عرض محتوى عرض جدول الخلية عن طريق التأكد من عدم تجاوز قيود ضغط المحتوى وقيود تعانق المحتوى في البعد الرأسي لكل مشاهدة فرعية قيود ذات أولوية أعلى قمت بإضافتها. ( هاه؟ انقر هنا. )

تذكر أن الفكرة هي أن تكون المشاهدات الفرعية للخلية متصلة عموديا بمشاهدة محتوى الخلية بحيث يمكنها "ممارسة الضغط" وجعل عرض المحتوى يتسع ليلائمها. باستخدام مثال خلية مع عدد قليل من المقابلات الفرعية، وهنا هو توضيح مرئي لما بعض (وليس كل شيء!) من القيود الخاصة بك سوف تحتاج إلى أن تبدو مثل:

يمكنك أن تتخيل أنه كلما تم إضافة المزيد من النص إلى تسمية الجسم متعدد الخطوط في الخلية المثال أعلاه، فإنه سوف تحتاج إلى النمو عموديا لتتناسب مع النص، الأمر الذي سيجبر الخلية على نحو فعال في النمو في الارتفاع. (بالطبع، تحتاج إلى الحصول على القيود الحق من أجل هذا للعمل بشكل صحيح!)

الحصول على القيود الخاصة بك الحق هو بالتأكيد أصعب وأهم جزء من الحصول على ارتفاعات خلية ديناميكية تعمل مع تخطيط السيارات. إذا قمت بخطأ هنا، فإنه يمكن منع كل شيء آخر من العمل - حتى تأخذ وقتك! أوصي بإعداد القيود في التعليمات البرمجية لأنك تعرف بالضبط القيود التي يتم إضافتها حيث، وأنه من الأسهل بكثير لتصحيح الأخطاء عندما تسوء الأمور. إضافة القيود في التعليمات البرمجية هو مجرد سهلة كما وأكثر قوة بكثير من واجهة منشئ عند الاستفادة من واحدة من واجهات برمجة التطبيقات مفتوحة المصدر رائعة المتاحة - وهنا هو واحد أنا تصميم وصيانة واستخدام حصرا: https://github.com/ smileyborg / PureLayout

  • إذا كنت تقوم بإضافة قيود في التعليمات البرمجية، يجب عليك القيام بذلك مرة واحدة من ضمن أسلوب updateConstraints الفئة الفرعية updateConstraints الخاص بك. لاحظ أنه قد يتم استدعاء updateConstraints أكثر من مرة واحدة، وذلك لتجنب إضافة القيود نفسها أكثر من مرة، تأكد من التفاف التعليمات البرمجية الخاصة بك القيد مضيفا ضمن updateConstraints في الاختيار لخاصية منطقية مثل didSetupConstraints (الذي قمت بتعيينه إلى يس بعد تشغيل التعليمات البرمجية الخاصة بك القيد مضيفا مرة واحدة). من ناحية أخرى، إذا كان لديك رمز تحديث القيود الموجودة (مثل ضبط الخاصية constant على بعض القيود)، ضع هذا في updateConstraints ولكن خارج الاختيار ل didSetupConstraints بحيث يمكن تشغيلها في كل مرة يتم استدعاء الأسلوب.

2. تحديد جدول فريد عرض معرفات إعادة استخدام الخلية

لكل مجموعة فريدة من القيود في الخلية، استخدم معرف فريد لإعادة استخدام الخلية. وبعبارة أخرى، إذا كان لخلاياك أكثر من تخطيط فريد، يجب أن يتلقى كل تخطيط فريد معرف تعريف إعادة الاستخدام الخاص به. (تلميح جيد بأنك تحتاج إلى استخدام معرف إعادة استخدام جديد عندما يكون لدى متغير الخلايا عدد مختلف من المقابلات الفرعية، أو يتم ترتيب العروض الفرعية بطريقة مختلفة.)

على سبيل المثال، إذا كنت تعرض رسالة بريد إلكتروني في كل خلية، فقد يكون لديك 4 تخطيطات فريدة: رسائل ذات موضوع واحد، ورسائل ذات موضوع وجسم، ورسائل ذات موضوع ومرفق صورة، ورسائل ذات موضوع، الجسم، ومرفق الصورة. كل تخطيط له قيود مختلفة تماما المطلوبة لتحقيق ذلك، لذلك مرة واحدة يتم تهيئة الخلية ويتم إضافة القيود لأحد أنواع الخلايا هذه، يجب أن الخلية الحصول على معرف إعادة استخدام فريدة محددة لهذا النوع من الخلايا. وهذا يعني عندما ديكويو خلية لإعادة استخدامها، وقد تم بالفعل إضافة القيود وجاهزة للذهاب لهذا النوع من الخلايا.

لاحظ أنه نظرا للاختلافات في حجم المحتوى الجوهري، الخلايا مع نفس القيود (نوع) قد لا تزال لديها ارتفاعات مختلفة! لا تخلط بين تخطيطات مختلفة جذريا (قيود مختلفة) مع إطارات عرض محسوبة مختلفة (تم حلها من قيود متطابقة) بسبب أحجام مختلفة من المحتوى.

  • لا تضف خلايا ذات مجموعات مختلفة تماما من القيود على نفس مجموعة إعادة الاستخدام (أي استخدام نفس معرف إعادة الاستخدام) ثم محاولة إزالة القيود القديمة وإعداد قيود جديدة من الصفر بعد كل ديكو. لم يتم تصميم محرك تخطيط السيارات الداخلية للتعامل مع تغييرات واسعة النطاق في القيود، وسترى مشاكل الأداء الضخمة.

لدائرة الرقابة الداخلية 8 - خلايا التحجيم الذاتي

3. تمكين تقدير ارتفاع الصف

لتمكين خلايا عرض جدول التحجيم الذاتي، يجب تعيين الصف عرض الجدول الخاصية هيت إلى إيتابلفيووتوماتيكديمينزيون. يجب أيضا تعيين قيمة إلى الخاصية ميثودرووهيت. حالما يتم تعيين كل من هذه الخصائص، يستخدم النظام تخطيط السيارات لحساب الارتفاع الفعلي للصف

أبل: العمل مع الجدول التحجيم الذاتي عرض الخلايا

مع دائرة الرقابة الداخلية 8، وقد استوعبت أبل الكثير من العمل الذي كان سابقا ليتم تنفيذها من قبل لك قبل دائرة الرقابة الداخلية 8. من أجل السماح آلية الخلية التحجيم الذاتي للعمل، يجب عليك أولا تعيين الخاصية rowHeight على عرض الجدول إلى ثابت UITableViewAutomaticDimension . ثم، تحتاج ببساطة إلى تمكين تقدير ارتفاع الصف عن طريق تعيين الخاصية عرض ماتيونرووايت عرض الجدول إلى قيمة غير صفرية، على سبيل المثال:

self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 44.0; // set to whatever your "average" cell height is

ما يفعله هو توفير عرض الجدول بتقدير مؤقت / عنصر نائب لارتفاعات الصفوف من الخلايا التي لم تظهر بعد على الشاشة. بعد ذلك، عندما تكون هذه الخلايا على وشك التمرير على الشاشة، سيتم حساب ارتفاع الصف الفعلي. لتحديد الارتفاع الفعلي لكل صف، يطلب عرض الجدول تلقائيا لكل خلية ما ارتفاع contentView الخاص contentView يحتاج إلى أن يستند إلى عرض ثابت معروف من عرض المحتوى (الذي يقوم على عرض عرض الجدول، ناقص أي أشياء إضافية مثل قسم فهرس أو ملحق) وقيود تخطيط السيارات التي قمت بإضافتها إلى عرض محتوى الخلية ومعاينات فرعية. وبمجرد تحديد هذا الارتفاع الفعلي للخلية، يتم تحديث الارتفاع المقدر القديم للصف مع الارتفاع الفعلي الجديد (ويتم إجراء أي تعديلات على طريقة عرض الجدول كونتنتسيزي / كونتنت أوفست حسب الحاجة لك).

وبصفة عامة، لا يجب أن يكون التقدير الذي تقدمه دقيقا للغاية - يتم استخدامه فقط لحجم مؤشر التمرير بشكل صحيح في طريقة عرض الجدول، كما أن طريقة عرض الجدول تقوم بعمل جيد لضبط مؤشر التمرير لتقديرات غير صحيحة انتقل الخلايا التي تظهر على الشاشة. يجب تعيين الخاصية viewDidLoad عرض الجدول (في viewDidLoad أو ما شابه ذلك) إلى قيمة ثابتة هو "متوسط" ارتفاع الصف. فقط إذا كان ارتفاع الصفوف لديك تقلب الشديد (على سبيل المثال تختلف حسب ترتيب من حجم) ولاحظت مؤشر التمرير "القفز" كما كنت انتقل يجب عليك عناء تنفيذ tableView:estimatedHeightForRowAtIndexPath: كل صف.

لدعم دائرة الرقابة الداخلية 7 (تنفيذ خلية السيارات التحجيم نفسك)

3. القيام بتخطيط تخطيط والحصول على ارتفاع الخلية

أولا، إنشاء مثيل أوفسكرين من خلية عرض الجدول، مثيل واحد لكل معرف إعادة استخدام ، يتم استخدامه بشكل صارم لحسابات الارتفاع. (أوفسكرين يعني أن مرجع الخلية يتم تخزينه في خاصية / إيفار على وحدة تحكم العرض ولم يتم إرجاعه من tableView:cellForRowAtIndexPath: لعرض الجدول لعرضه فعليا على الشاشة.) بعد ذلك، يجب تكوين الخلية بالمحتوى الدقيق (مثل النص، الصور، الخ) التي سوف تعقد إذا كان ليتم عرضها في طريقة عرض الجدول.

ثم، فرض الخلية لتخطيط فورا سوبفيوس لها، ومن ثم استخدام systemLayoutSizeFittingSize: الأسلوب على contentView لمعرفة ما هو المطلوب من ارتفاع الخلية. استخدام UILayoutFittingCompressedSize للحصول على أصغر حجم مطلوب لتناسب جميع محتويات الخلية. يمكن بعد ذلك إرجاع الارتفاع من tableView:heightForRowAtIndexPath: طريقة المندوب.

4. استخدام مرتفعات الصف المقدرة

إذا كان عرض الجدول الخاص بك يحتوي على أكثر من بضع عشرات الصفوف في ذلك، سوف تجد أن القيام حل تخطيط تخطيط السيارات يمكن أن تعثر بسرعة أسفل مؤشر الترابط الرئيسي عند أول تحميل عرض الجدول، كما tableView:heightForRowAtIndexPath: يسمى على كل صف عند التحميل الأول (من أجل حساب حجم مؤشر التمرير).

اعتبارا من دائرة الرقابة الداخلية 7، يمكنك (وعلى الاطلاق ينبغي) استخدام الخاصية ميثودروهيت على عرض الجدول. ما يفعله هو توفير عرض الجدول بتقدير مؤقت / عنصر نائب لارتفاعات الصفوف من الخلايا التي لم تظهر بعد على الشاشة. ثم، عندما تكون هذه الخلايا على وشك التمرير على الشاشة، سيتم حساب ارتفاع الصف الفعلي (عن طريق استدعاء tableView:heightForRowAtIndexPath: ، والارتفاع المقدر تحديث مع واحد الفعلي.

وبصفة عامة، لا يجب أن يكون التقدير الذي تقدمه دقيقا للغاية - يتم استخدامه فقط لحجم مؤشر التمرير بشكل صحيح في طريقة عرض الجدول، كما أن طريقة عرض الجدول تقوم بعمل جيد لضبط مؤشر التمرير لتقديرات غير صحيحة انتقل الخلايا التي تظهر على الشاشة. يجب تعيين الخاصية viewDidLoad عرض الجدول (في viewDidLoad أو ما شابه ذلك) إلى قيمة ثابتة هو "متوسط" ارتفاع الصف. فقط إذا كان ارتفاع الصفوف لديك تقلب الشديد (على سبيل المثال تختلف حسب ترتيب من حجم) ولاحظت مؤشر التمرير "القفز" كما كنت انتقل يجب عليك عناء تنفيذ tableView:estimatedHeightForRowAtIndexPath: كل صف.

5. (إذا لزم الأمر) إضافة التخزين المؤقت ارتفاع الصف

إذا كنت قد فعلت كل ما سبق و لا تزال تجد أن الأداء بطيء بشكل غير مقبول عند القيام حل القيد في tableView:heightForRowAtIndexPath: سوف تحتاج للأسف إلى تنفيذ بعض التخزين المؤقت لارتفاعات الخلية. (وهذا هو النهج المقترح من قبل مهندسي أبل). والفكرة العامة هي السماح للمحرك تخطيط السيارات حل القيود للمرة الأولى، ثم ذاكرة التخزين المؤقت الارتفاع المحسوب لتلك الخلية واستخدام القيمة المخزنة مؤقتا لجميع الطلبات المستقبلية لارتفاع تلك الخلية. خدعة بالطبع هي التأكد من مسح ارتفاع مخبأ للخلية عندما يحدث أي شيء يمكن أن يسبب ارتفاع الخلية لتغيير - في المقام الأول، وهذا سيكون عندما يتغير محتوى هذه الخلية أو عندما تحدث أحداث هامة أخرى (مثل ضبط المستخدم شريط تمرير حجم النص الديناميكي).

دائرة الرقابة الداخلية 7 رمز عينة عام (مع الكثير من التعليقات العصير)

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Determine which reuse identifier should be used for the cell at this 
    // index path, depending on the particular layout required (you may have
    // just one, or may have many).
    NSString *reuseIdentifier = ...;

    // Dequeue a cell for the reuse identifier.
    // Note that this method will init and return a new cell if there isn't
    // one available in the reuse pool, so either way after this line of 
    // code you will have a cell with the correct constraints ready to go.
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];

    // Configure the cell with content for the given indexPath, for example:
    // cell.textLabel.text = someTextForThisCell;
    // ...

    // Make sure the constraints have been set up for this cell, since it 
    // may have just been created from scratch. Use the following lines, 
    // assuming you are setting up constraints from within the cell's 
    // updateConstraints method: [cell setNeedsUpdateConstraints];
    [cell updateConstraintsIfNeeded];

    // If you are using multi-line UILabels, don't forget that the 
    // preferredMaxLayoutWidth needs to be set correctly. Do it at this 
    // point if you are NOT doing it within the UITableViewCell subclass 
    // -[layoutSubviews] method. For example: 
    // cell.multiLineLabel.preferredMaxLayoutWidth = CGRectGetWidth(tableView.bounds);

    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Determine which reuse identifier should be used for the cell at this 
    // index path.
    NSString *reuseIdentifier = ...;

    // Use a dictionary of offscreen cells to get a cell for the reuse 
    // identifier, creating a cell and storing it in the dictionary if one 
    // hasn't already been added for the reuse identifier. WARNING: Don't 
    // call the table view's dequeueReusableCellWithIdentifier: method here 
    // because this will result in a memory leak as the cell is created but 
    // never returned from the tableView:cellForRowAtIndexPath: method!
    UITableViewCell *cell = [self.offscreenCells objectForKey:reuseIdentifier];
    if (!cell) {
        cell = [[YourTableViewCellClass alloc] init];
        [self.offscreenCells setObject:cell forKey:reuseIdentifier];
    }

    // Configure the cell with content for the given indexPath, for example:
    // cell.textLabel.text = someTextForThisCell;
    // ...

    // Make sure the constraints have been set up for this cell, since it 
    // may have just been created from scratch. Use the following lines, 
    // assuming you are setting up constraints from within the cell's 
    // updateConstraints method:
    [cell setNeedsUpdateConstraints];
    [cell updateConstraintsIfNeeded];

    // Set the width of the cell to match the width of the table view. This
    // is important so that we'll get the correct cell height for different
    // table view widths if the cell's height depends on its width (due to 
    // multi-line UILabels word wrapping, etc). We don't need to do this 
    // above in -[tableView:cellForRowAtIndexPath] because it happens 
    // automatically when the cell is used in the table view. Also note, 
    // the final width of the cell may not be the width of the table view in
    // some cases, for example when a section index is displayed along 
    // the right side of the table view. You must account for the reduced 
    // cell width.
    cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(cell.bounds));

    // Do the layout pass on the cell, which will calculate the frames for 
    // all the views based on the constraints. (Note that you must set the 
    // preferredMaxLayoutWidth on multi-line UILabels inside the 
    // -[layoutSubviews] method of the UITableViewCell subclass, or do it 
    // manually at this point before the below 2 lines!)
    [cell setNeedsLayout];
    [cell layoutIfNeeded];

    // Get the actual height required for the cell's contentView
    CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    // Add an extra point to the height to account for the cell separator, 
    // which is added between the bottom of the cell's contentView and the 
    // bottom of the table view cell.
    height += 1.0f;

    return height;
}

// NOTE: Set the table view's estimatedRowHeight property instead of 
// implementing the below method, UNLESS you have extreme variability in 
// your row heights and you notice the scroll indicator "jumping" 
// as you scroll.
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Do the minimal calculations required to be able to return an 
    // estimated row height that's within an order of magnitude of the 
    // actual height. For example:
    if ([self isTallCellAtIndexPath:indexPath]) {
        return 350.0f;
    } else {
        return 40.0f;
    }
}

مشاريع العينة

هذه المشاريع تعمل بشكل كامل أمثلة على وجهات النظر الجدول مع ارتفاع الصفوف متغير بسبب خلايا عرض الجدول التي تحتوي على محتوى ديناميكي في ويلابيلز.

لا تتردد في رفع أي أسئلة أو القضايا التي واجهت (يمكنك فتح القضايا على جيثب أو نشر التعليقات هنا). سأحاول قصارى جهدي للمساعدة!

زامارين (C # /. نيت)

إذا كنت تستخدم زامارين، تحقق من هذا المشروع عينة وضعت معا من قبل KentBoogaart .




ل IOS8 انها بسيطة حقا:

override func viewDidLoad() {  
    super.viewDidLoad()

    self.tableView.estimatedRowHeight = 80
    self.tableView.rowHeight = UITableViewAutomaticDimension
}

أو

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

ولكن ل IOS7، والمفتاح هو حساب الارتفاع بعد أوتولايوت،

func calculateHeightForConfiguredSizingCell(cell: GSTableViewCell) -> CGFloat {
    cell.setNeedsLayout()
    cell.layoutIfNeeded()
    let height = cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingExpandedSize).height + 1.0
    return height
}

مهم

  • إذا تسميات خطوط متعددة، لا ننسى تعيين numberOfLines إلى 0 .

  • لا تنسى label.preferredMaxLayoutWidth = CGRectGetWidth(tableView.bounds)

رمز المثال الكامل هنا .




مثال سريع على ارتفاع متغير إيتابلفيوسيل

تحديث ل سويفت 3

وليام هو سويفت الجواب هو جيد، لكنه يساعدني أن يكون بعض الخطوات بسيطة ولكنها مفصلة عند تعلم أن تفعل شيئا للمرة الأولى. المثال أدناه هو مشروع اختبار بلدي في حين تعلم لجعل UITableView مع ارتفاعات الخلايا المتغيرة. أنا على أساس هذا الأساسية إيتابيفيو سبيل المثال سويفت .

يجب أن يكون المشروع النهائي كما يلي:

إنشاء مشروع جديد

يمكن أن يكون مجرد تطبيق عرض واحد.

أضف الرمز

إضافة ملف سويفت جديد إلى المشروع الخاص بك. اسم ذلك ميكوستومسيل. ستحتفظ هذه الفئة بمنافذ العرض التي تضيفها إلى زنزانتك في لوحة العمل. في هذا المثال الأساسي سيكون لدينا فقط تسمية واحدة في كل خلية.

import UIKit
class MyCustomCell: UITableViewCell {
    @IBOutlet weak var myCellLabel: UILabel!
}

سنقوم بتوصيل هذا المنفذ في وقت لاحق.

افتح ViewController.swift وتأكد من امتلاكك للمحتوى التالي:

import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    // These strings will be the data for the table view cells
    let animals: [String] = [
        "Ten horses:  horse horse horse horse horse horse horse horse horse horse ",
        "Three cows:  cow, cow, cow",
        "One camel:  camel",
        "Ninety-nine sheep:  sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep baaaa sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep sheep",
        "Thirty goats:  goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat goat "]

    // Don't forget to enter this in IB also
    let cellReuseIdentifier = "cell"

    @IBOutlet var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // delegate and data source
        tableView.delegate = self
        tableView.dataSource = self

        // Along with auto layout, these are the keys for enabling variable cell height
        tableView.estimatedRowHeight = 44.0
        tableView.rowHeight = UITableViewAutomaticDimension
    }

    // number of rows in table view
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.animals.count
    }

    // create a cell for each table view row
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell:MyCustomCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! MyCustomCell
        cell.myCellLabel.text = self.animals[indexPath.row]
        return cell
    }

    // method to run when table view cell is tapped
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("You tapped cell number \(indexPath.row).")
    }
}

ملاحظة مهمة:

  • هو السطرين التاليين من التعليمات البرمجية (جنبا إلى جنب مع تخطيط السيارات) التي تجعل من ارتفاع الخلية متغير ممكن:

    tableView.estimatedRowHeight = 44.0
    tableView.rowHeight = UITableViewAutomaticDimension

إعداد لوحة العمل

إضافة عرض الجدول إلى وحدة تحكم العرض الخاص بك واستخدام تخطيط السيارات لتثبيته على الجوانب الأربعة. ثم اسحب خلية عرض الجدول على عرض الجدول. وعلى الخلية النموذجية، اسحب تسمية. استخدم التخطيط التلقائي لتثبيت التسمية على الحواف الأربعة لعرض المحتوى في خلية عرض الجدول.

ملاحظة مهمة:

  • تخطيط السيارات يعمل جنبا إلى جنب مع خطين مهم من التعليمات البرمجية المذكورة أعلاه. إذا كنت لا تستخدم تخطيط السيارات أنها لن تعمل.

إعدادات يب الأخرى

اسم فئة مخصص ومعرف

حدد الخلية عرض الجدول وتعيين فئة مخصصة ليكون MyCustomCell (اسم الفئة في ملف سويفت أضفنا). أيضا تعيين معرف ليكون cell (نفس السلسلة التي استخدمناها ل cellReuseIdentifier في التعليمات البرمجية أعلاه.

خطوط صفر للتسمية

اضبط عدد الأسطر على 0 في تصنيفك. وهذا يعني متعدد الخطوط ويسمح التسمية لتغيير حجم نفسه استنادا إلى محتواه.

ربط المنافذ

  • التحكم في السحب من الجدول عرض في القصة المصورة إلى الجدول عرض متغير في التعليمات البرمجية ViewController .
  • تفعل الشيء نفسه myCellLabel في الخلية النموذج الخاص بك إلى متغير myCellLabel في فئة myCellLabel .

تم الانتهاء من

يجب أن تكون قادرا على تشغيل المشروع الخاص بك الآن والحصول على خلايا ذات ارتفاعات متغيرة.

ملاحظات

  • هذا المثال يعمل فقط لنظام التشغيل يوس 8 وما بعده. إذا كنت لا تزال بحاجة إلى دعم دائرة الرقابة الداخلية 7 ثم وهذا لن يعمل بالنسبة لك.
  • الخلايا المخصصة الخاصة بك في مشاريعك المستقبلية ربما يكون أكثر من تسمية واحدة. تأكد من أن تحصل على كل شيء مثبت الحق بحيث تخطيط السيارات يمكن تحديد الارتفاع الصحيح للاستخدام. قد تضطر أيضا إلى استخدام مقاومة الضغط العمودي والتعانق. انظر هذه المقالة لمعرفة المزيد عن ذلك.
  • إذا لم تكن تعلق على الحواف الرائدة والرائدة (اليسار واليمين)، فقد تحتاج أيضا إلى تعيين تفضيلات التسمية preferredMaxLayoutWidth ل preferredMaxLayoutWidth بحيث يعرف متى يتم التفاف السطر. على سبيل المثال، إذا قمت بإضافة مركز أفقيا قيد إلى التسمية في المشروع أعلاه بدلا من دبوس الحواف الرائدة والزائدة، ثم تحتاج إلى إضافة هذا السطر إلى tableView:cellForRowAtIndexPath : طريقة tableView:cellForRowAtIndexPath :

     cell.myCellLabel.preferredMaxLayoutWidth = tableView.bounds.width

أنظر أيضا




أنا ملفوفة @ حل iOS7 سميليبورغ في فئة

قررت أن التفاف هذا الحل ذكي من قبلsmileyborg إلى فئة UICollectionViewCell+AutoLayoutDynamicHeightCalculation .

الفئة أيضا تصحيح القضايا المبينة في الجواب @ ويلدمونكي (تحميل خلية من بنك الاستثمار القومي و systemLayoutSizeFittingSize: العودة CGRectZero )

فإنه لا يأخذ بعين الاعتبار أي التخزين المؤقت ولكن يناسب احتياجاتي الآن. لا تتردد في نسخ ولصق والاختراق في ذلك.

UICollectionViewCell + AutoLayoutDynamicHeightCalculation.h

#import <UIKit/UIKit.h>

typedef void (^UICollectionViewCellAutoLayoutRenderBlock)(void);

/**
 *  A category on UICollectionViewCell to aid calculating dynamic heights based on AutoLayout contraints.
 *
 *  Many thanks to @smileyborg and @wildmonkey
 *
 *  @see .com/questions/18746929/using-auto-layout-in-uitableview-for-dynamic-cell-layouts-variable-row-heights
 */
@interface UICollectionViewCell (AutoLayoutDynamicHeightCalculation)

/**
 *  Grab an instance of the receiving type to use in order to calculate AutoLayout contraint driven dynamic height. The method pulls the cell from a nib file and moves any Interface Builder defined contrainsts to the content view.
 *
 *  @param name Name of the nib file.
 *
 *  @return collection view cell for using to calculate content based height
 */
+ (instancetype)heightCalculationCellFromNibWithName:(NSString *)name;

/**
 *  Returns the height of the receiver after rendering with your model data and applying an AutoLayout pass
 *
 *  @param block Render the model data to your UI elements in this block
 *
 *  @return Calculated constraint derived height
 */
- (CGFloat)heightAfterAutoLayoutPassAndRenderingWithBlock:(UICollectionViewCellAutoLayoutRenderBlock)block collectionViewWidth:(CGFloat)width;

/**
 *  Directly calls `heightAfterAutoLayoutPassAndRenderingWithBlock:collectionViewWidth` assuming a collection view width spanning the [UIScreen mainScreen] bounds
 */
- (CGFloat)heightAfterAutoLayoutPassAndRenderingWithBlock:(UICollectionViewCellAutoLayoutRenderBlock)block;

@end

UICollectionViewCell + AutoLayoutDynamicHeightCalculation.m

#import "UICollectionViewCell+AutoLayout.h"

@implementation UICollectionViewCell (AutoLayout)

#pragma mark Dummy Cell Generator

+ (instancetype)heightCalculationCellFromNibWithName:(NSString *)name
{
    UICollectionViewCell *heightCalculationCell = [[[NSBundle mainBundle] loadNibNamed:name owner:self options:nil] lastObject];
    [heightCalculationCell moveInterfaceBuilderLayoutConstraintsToContentView];
    return heightCalculationCell;
}

#pragma mark Moving Constraints

- (void)moveInterfaceBuilderLayoutConstraintsToContentView
{
    [self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) {
        [self removeConstraint:constraint];
        id firstItem = constraint.firstItem == self ? self.contentView : constraint.firstItem;
        id secondItem = constraint.secondItem == self ? self.contentView : constraint.secondItem;
        [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:firstItem
                                                                     attribute:constraint.firstAttribute
                                                                     relatedBy:constraint.relation
                                                                        toItem:secondItem
                                                                     attribute:constraint.secondAttribute
                                                                    multiplier:constraint.multiplier
                                                                      constant:constraint.constant]];
    }];
}

#pragma mark Height

- (CGFloat)heightAfterAutoLayoutPassAndRenderingWithBlock:(UICollectionViewCellAutoLayoutRenderBlock)block
{
    return [self heightAfterAutoLayoutPassAndRenderingWithBlock:block
                                            collectionViewWidth:CGRectGetWidth([[UIScreen mainScreen] bounds])];
}

- (CGFloat)heightAfterAutoLayoutPassAndRenderingWithBlock:(UICollectionViewCellAutoLayoutRenderBlock)block collectionViewWidth:(CGFloat)width
{
    NSParameterAssert(block);

    block();

    [self setNeedsUpdateConstraints];
    [self updateConstraintsIfNeeded];

    self.bounds = CGRectMake(0.0f, 0.0f, width, CGRectGetHeight(self.bounds));

    [self setNeedsLayout];
    [self layoutIfNeeded];

    CGSize calculatedSize = [self.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];

    return calculatedSize.height;

}

@end

مثال الاستخدام:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    MYSweetCell *cell = [MYSweetCell heightCalculationCellFromNibWithName:NSStringFromClass([MYSweetCell class])];
    CGFloat height = [cell heightAfterAutoLayoutPassAndRenderingWithBlock:^{
        [(id<MYSweetCellRenderProtocol>)cell renderWithModel:someModel];
    }];
    return CGSizeMake(CGRectGetWidth(self.collectionView.bounds), height);
}

والحمد لله أننا لن تضطر إلى القيام بذلك الجاز في iOS8، ولكن هناك هو الآن!




هنا هو الحل. تحتاج إلى معرفة تابلفيو المقدر قبل أن يحمل الرأي. وإلا فإنه لن يكون قادرا على التصرف مثل المتوقع.

- (void)viewWillAppear:(BOOL)animated {
    _messageField.delegate = self;
    _tableView.estimatedRowHeight = 65.0;
    _tableView.rowHeight = UITableViewAutomaticDimension;
}



الحل المقترح من قبل سميليبورغ هو الكمال تقريبا. إذا كان لديك خلية مخصصة وتريد واحد أو أكثر UILabel مع ارتفاعات دينامية ثم طريقة سيستيملايوتزيزيفتينزيزي جنبا إلى جنب مع تمكين CGSizeZero إرجاع CGSizeZero إلا إذا قمت بنقل كل قيود الخلية الخاصة بك من الخلية إلى كونتنتفيو (كما اقترح من قبلTomSwift هنا كيفية تغيير حجم سوبيرفيو لتناسب جميع سوبفيوس مع أوتولايوت؟ ).

للقيام بذلك تحتاج إلى إدراج التعليمات البرمجية التالية في تنفيذ إيتابيفوسيل مخصص الخاص بك (بفضلAdrian).

- (void)awakeFromNib{
    [super awakeFromNib];
    for (NSLayoutConstraint *cellConstraint in self.constraints) {
        [self removeConstraint:cellConstraint];
        id firstItem = cellConstraint.firstItem == self ? self.contentView : cellConstraint.firstItem;
        id seccondItem = cellConstraint.secondItem == self ? self.contentView : cellConstraint.secondItem;
        NSLayoutConstraint *contentViewConstraint =
        [NSLayoutConstraint constraintWithItem:firstItem
                                 attribute:cellConstraint.firstAttribute
                                 relatedBy:cellConstraint.relation
                                    toItem:seccondItem
                                 attribute:cellConstraint.secondAttribute
                                multiplier:cellConstraint.multiplier
                                  constant:cellConstraint.constant];
        [self.contentView addConstraint:contentViewConstraint];
    }
}

خلط الجوابsmileyborg مع هذا ينبغي ان يعمل.




ومسكتك المهم ما يكفي من جريت فقط في لنشر كإجابة.

@ الجواب smileyborg هي في معظمها صحيحة. ومع ذلك، إذا كان لديك أي رمز في layoutSubviewsطريقة صفك خلية مخصصة، على سبيل المثال وضع preferredMaxLayoutWidth، فلن يتم تشغيله مع هذا الرمز:

[cell.contentView setNeedsLayout];
[cell.contentView layoutIfNeeded];

ومن مرتبك لي لحظة. ثم أدركت انها لأن تلك هي اثار فقط layoutSubviews على contentView، وليس الخلية نفسها.

كود العمل الخاص بي يبدو مثل هذا:

TCAnswerDetailAppSummaryCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"TCAnswerDetailAppSummaryCell"];
[cell configureWithThirdPartyObject:self.app];
[cell layoutIfNeeded];
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return height;

لاحظ أنه إذا كنت تقوم بإنشاء خلية جديدة، وأنا متأكد من أنك لا تحتاج إلى استدعاء setNeedsLayoutكما يجب أن يكون بالفعل تعيينها. في الحالات التي قمت بحفظ إشارة إلى خلية، ربما يجب عليك تسميتها. وفي كلتا الحالتين فإنه لا ينبغي أن يضر أي شيء.

آخر نصيحة إذا كنت تستخدم فرعية الخلية حيث كنت في وضع أشياء مثل preferredMaxLayoutWidth. كماsmileyborg يذكر، "خلية عرض الجدول الخاص بك لم يتم حتى الآن قد عرضه ثابتة لعرض وجهة نظر الجدول". وهذا صحيح، والمتاعب إذا كنت تفعل عملك في فئة فرعية وليس في وحدة تحكم الرأي. ولكن يمكنك ببساطة وضع إطار خلية في هذه المرحلة باستخدام عرض الجدول:

على سبيل المثال في حساب للارتفاع:

self.summaryCell = [self.tableView dequeueReusableCellWithIdentifier:@"TCAnswerDetailDefaultSummaryCell"];
CGRect oldFrame = self.summaryCell.frame;
self.summaryCell.frame = CGRectMake(oldFrame.origin.x, oldFrame.origin.y, self.tableView.frame.size.width, oldFrame.size.height);

(I يحدث لتخزين هذه الخلية معينة لإعادة استخدامها، ولكن هذا غير ذي صلة).







(لكسكودي 8.x من / كسكودي 9.x من قراءة في الأسفل)

حذار من المشكلة التالية في كسكودي في 7.X، والتي قد تكون مصدرا للالتباس:

واجهة باني لا يعالج انشاء خلية التحجيم التلقائي بشكل صحيح. حتى لو القيود الخاصة بك صحيحة على الاطلاق، وسوف IB لا يزال يشكو وتعطيك اقتراحات مربكة والأخطاء. والسبب هو أن IB غير مستعدة لتغيير ارتفاع الصف كما تملي القيود الخاصة بك (بحيث الخلية يناسب حول المحتوى الخاص بك). بدلا من ذلك، فإنه يحتفظ ارتفاع الصف وثابتة ويبدأ أقترح عليك تغيير القيود الخاصة بك، والتي يجب تجاهل .

على سبيل المثال، تخيل أنك قمت بإعداد كل شيء على ما يرام، لا التحذيرات، عدم وجود أخطاء، جميع الأعمال.

الآن إذا قمت بتغيير حجم الخط (في هذا المثال أنا تغيير وصف حجم التسمية الخط 17،0-18،0).

لأن حجم الخط زيادة، التسمية يريد الآن لاحتلال 3 صفوف (قبل ذلك كان يشغل الصفوف 2).

إذا عملت واجهة البناء كما هو متوقع، فإنه تغيير حجم ارتفاع الخلية لاستيعاب ارتفاع التسمية الجديدة. ولكن ما يحدث في الواقع هو أن IB يعرض رمز الخطأ لصناعة السيارات في تخطيط الأحمر وأقترح عليك أن تعديل أولويات المعانقة / ضغط.

يجب تجاهل هذه التحذيرات. ما يمكنك القيام به * بدلا من ذلك هو تغيير ارتفاع الصف يدويا في (حدد الخلية> الحجم المفتش> ارتفاع الصف).

لقد تغير هذا الارتفاع ضغطة واحدة في كل مرة (باستخدام أعلى / أسفل السائر) حتى تختفي الأخطاء السهم الأحمر! (سوف تحصل في الواقع تحذيرات الصفراء، وعند هذه النقطة اذهبوا الى الامام والقيام "إطارات التحديث"، فإنه يجب أن نعمل جميعا).

* لاحظ أن لم يكن لديك فعلا لحل هذه الأخطاء حمراء أو صفراء تحذيرات في واجهة البناء - في وقت التشغيل، كل شيء يعمل بشكل صحيح (حتى لو تبين IB أخطاء / التحذيرات). فقط تأكد من أن في وقت التشغيل في وحدة تسجيل أنك لا تحصل على أية أخطاء التخطيط التلقائي.

في الواقع محاولة تحديث دائما ارتفاع الصف في IB هو السوبر مزعج وأحيانا بالقرب من المستحيل (بسبب القيم كسور).

لمنع تحذيرات IB مزعج / أخطاء، يمكنك تحديد وجهات المعنية و Size Inspectorللخاصية AmbiguityاختيارVerify Position Only

يبدو كسكودي 8.x من / كسكودي 9.x من ل(أحيانا) أن تفعل الأشياء بشكل مختلف عن كسكودي 7.X، ولكن لا يزال غير صحيح. على سبيل المثال حتى عندما compression resistance priority/ hugging priorityمن المقرر أن المطلوبة (1000)، واجهة البناء قد تمدد أو مقطع تسمية لتناسب الخلية (بدلا من تغيير حجم ارتفاع الخلية لتتلاءم حول التسمية). وفي مثل هذه الحالة قد لا تظهر حتى أي تحذيرات التخطيط التلقائي أو أخطاء. أو في بعض الأحيان فإنه بالضبط ما فعله كسكودي 7.X، هو موضح أعلاه.




طالما التصميم الخاص بك في الخلية الخاص بك هو جيد.

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];

    return [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
}

تحديث: يجب عليك استخدام تغيير حجم الحيوية التي أدخلت في دائرة الرقابة الداخلية 8.




مثل @ بوب-Spryn ركضت إلى مسكتك المهم ما يكفي أنني نشر هذا كإجابة.

أنا ناضلت مع @ smileyborg في الإجابة لفترة من الوقت. ومسكتك أنني واجهت هو إذا قمت بتعريف خلية النموذج الخاص بك في IB مع عناصر إضافية ( UILabels، UIButtonsوغيرها) في IB عند مثيل الخلية مع [ [YourTableViewCellClass alloc] init]فإنه لن مثيل جميع العناصر الأخرى داخل تلك الخلية إلا إذا كنت قد قانون مكتوب للقيام بذلك. (كان لي تجربة مماثلة مع initWithStyle).

لديك لوحة العمل مثيل جميع عناصر إضافية الحصول على الخلوي مع [tableView dequeueReusableCellWithIdentifier:@"DoseNeeded"](وليس [tableView dequeueReusableCellWithIdentifier:forIndexPath:]لأن هذا سوف يسبب مشاكل مثيرة للاهتمام.) عند القيام بذلك جميع العناصر التي تم تعريفها في IB سيتم إنشاء مثيل.




الجدول الديناميكي ارتفاع عرض خلية والتخطيط السيارات

وهناك طريقة جيدة لحل المشكلة مع تخطيط السيارات القصة المصورة:

- (CGFloat)heightForImageCellAtIndexPath:(NSIndexPath *)indexPath {
  static RWImageCell *sizingCell = nil;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    sizingCell = [self.tableView dequeueReusableCellWithIdentifier:RWImageCellIdentifier];
  });

  [sizingCell setNeedsLayout];
  [sizingCell layoutIfNeeded];

  CGSize size = [sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
  return size.height;
}



آخر "الحل": تخطي كل هذا الإحباط واستخدام UIScrollView بدلا من ذلك إلى الحصول على النتيجة التي يبدو ويشعر مماثلة لUITableView.

وكان هذا هو "الحل" مؤلمة بالنسبة لي، بعد أن وضعت في حرفيا 20+ ساعات محبطة جدا الإجمايل يحاول بناء شيء مثل ما smileyborg المقترحة وفشل عبر العديد من أشهر وثلاث نسخ من المتجر تطلق.

بلدي يأخذ هو أنه إذا كنت حقا بحاجة إلى دعم دائرة الرقابة الداخلية 7 (بالنسبة لنا، فإنه من الضروري) ثم التكنولوجيا ليست سوى هشة للغاية وعليك سحب شعرك تحاول. وأن UITableView اكتمال مبالغة عموما إلا إذا كنت تستخدم بعض ميزات التحرير الصف المتقدمة و / أو حقا بحاجة الى دعم 1000+ "الصفوف" (في التطبيق لدينا، انها واقعية أبدا أكثر من 20 صفوف).

واضاف منحة هو أن رمز يحصل بسيط بجنون مقابل كل حماقة مندوب وذهابا وإيابا الذي يأتي مع UITableView. انها واحدة فقط حلقة واحدة من التعليمات البرمجية في viewOnLoad أن تبدو أنيقة وسهلة لإدارة.

وإليك بعض النصائح حول كيفية القيام بذلك:

1) عن طريق إما القصة المصورة أو ملف بنك الاستثمار القومي، إنشاء طريقة عرض جذر ViewController وما يرتبط بها.

2) سحب أكثر من UIScrollView على عرض الجذر.

3) إضافة قيود أعلى، أسفل، يسار والقيود الصحيحة للرأي على مستوى عال بحيث يملأ UIScrollView وجهة الجذر بأكمله.

4) أضف UIView داخل UIScrollView والذي يطلق عليه "حاوية". إضافة العلوية والسفلية واليسار والقيود الصحيحة للUIScrollView (الأم). خدعة الرئيسية: أيضا إضافة "بعرض المساواة" قيود لربط UIScrollView وUIView.

سوف تحصل على خطأ "وجهة نظر التمرير له غامضة ارتفاع محتوى تمرير" وأنه يجب أن يكون UIView الحاويات على ارتفاع 0 بكسل. يبدو لا يهم الخطأ عند تشغيل التطبيق.

5) إنشاء ملفات وأجهزة التحكم بنك الاستثمار القومي لكل من بك "خلايا". استخدام UIView لا UITableViewCell.

5) في ViewController الجذر الخاص بك، فإنك أساسا إضافة كافة "الصفوف" إلى UIView الحاويات وبرمجيا إضافة القيود التي تربط حوافها اليسار واليمين إلى العرض الحاويات، والحواف العلوية إلى أي من وجهة نظر حاوية أعلى (للمادة أول) أو الخلية السابقة. ثم ربط الخلية النهائية إلى أسفل الحاوية.

بالنسبة لنا، كل "الصف" في ملف بنك الاستثمار القومي. ذلك الرمز يبدو شيئا من هذا القبيل:

class YourRootViewController {

    @IBOutlet var container: UIView! //container mentioned in step 4

    override func viewDidLoad() {

        super.viewDidLoad()

        var lastView: UIView?
        for data in yourDataSource {

            var cell = YourCellController(nibName: "YourCellNibName", bundle: nil)
            UITools.addViewToTop(container, child: cell.view, sibling: lastView)
            lastView = cell.view
            //Insert code here to populate your cell
        }

        if(lastView != nil) {
            container.addConstraint(NSLayoutConstraint(
                item: lastView!,
                attribute: NSLayoutAttribute.Bottom,
                relatedBy: NSLayoutRelation.Equal,
                toItem: container,
                attribute: NSLayoutAttribute.Bottom,
                multiplier: 1,
                constant: 0))
        }

        ///Add a refresh control, if you want - it seems to work fine in our app:
        var refreshControl = UIRefreshControl()
        container.addSubview(refreshControl!)
    }
}

وهنا رمز للUITools.addViewToTop:

class UITools {
    ///Add child to container, full width of the container and directly under sibling (or container if sibling nil):
    class func addViewToTop(container: UIView, child: UIView, sibling: UIView? = nil)
    {
        child.setTranslatesAutoresizingMaskIntoConstraints(false)
        container.addSubview(child)

        //Set left and right constraints so fills full horz width:

        container.addConstraint(NSLayoutConstraint(
            item: child,
            attribute: NSLayoutAttribute.Leading,
            relatedBy: NSLayoutRelation.Equal,
            toItem: container,
            attribute: NSLayoutAttribute.Left,
            multiplier: 1,
            constant: 0))

        container.addConstraint(NSLayoutConstraint(
            item: child,
            attribute: NSLayoutAttribute.Trailing,
            relatedBy: NSLayoutRelation.Equal,
            toItem: container,
            attribute: NSLayoutAttribute.Right,
            multiplier: 1,
            constant: 0))

        //Set vertical position from last item (or for first, from the superview):
        container.addConstraint(NSLayoutConstraint(
            item: child,
            attribute: NSLayoutAttribute.Top,
            relatedBy: NSLayoutRelation.Equal,
            toItem: sibling == nil ? container : sibling,
            attribute: sibling == nil ? NSLayoutAttribute.Top : NSLayoutAttribute.Bottom,
            multiplier: 1,
            constant: 0))
    }
}

وفقط "مسكتك" لقد وجدت في هذا النهج حتى الآن هو أن UITableView لديه ميزة لطيفة من "عائم" رؤوس المقاطع في الجزء العلوي من وجهة النظر أثناء التمرير. فإن الحل أعلاه لا تفعل ذلك إلا إذا قمت بإضافة المزيد من البرامج ولكن لحالتنا معينة وهذه الميزة ليست 100٪ أساسي ولا أحد لاحظ عندما ذهبت بعيدا.

إذا كنت تريد فواصل بين الخلايا، ما عليك سوى إضافة 1 بكسل UIView عالية في الجزء السفلي من عهدك "خلية" الذي يبدو وكأنه مقسم.

تأكد من تشغيل "مستبعد" و "ترتد عموديا" لمراقبة التحديث إلى العمل وهكذا يبدو أشبه tableview.

يظهر TableView بعض الصفوف الفارغة وفواصل تحت المحتوى الخاص بك، إذا كان لا تملأ كامل الشاشة حيث أن هذا الحل لا. ولكن شخصيا، أنا أفضل لو كانت تلك الصفوف الفارغة لم يكن هناك أي حال - مع ارتفاع الخلية متغير بدا دائما "عربات التي تجرها الدواب" للي على أية حال أن يكون الصفوف الفارغة في هناك.

هنا تأمل بعض مبرمج الآخر يقرأ منصبي قبل إضاعة 20+ ساعات في محاولة لمعرفة ذلك مع عرض الجدول في التطبيق الخاص بهم. :)




tableView.estimatedRowHeight = 343.0
tableView.rowHeight = UITableViewAutomaticDimension




اضطررت الى استخدام طرق العرض الديناميكية (وجهات النظر الإعداد والمعوقات التي الشفرة) وعندما أردت أن تحدد عرض preferredMaxLayoutWidth التسمية و0. لذا أنا عندي ارتفاع الخلية الخطأ.

ثم أضفت

[cell layoutSubviews];

قبل تنفيذ

[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];

بعد أن كان العرض الذي التسمية كما هو متوقع وارتفاع ديناميكية واحتساب الصحيح.




دعونا نقول لديك خلية مع subview، وتريد ارتفاع الخلية لتكون مرتفعة بما يكفي لتشمل subview + الحشو.

1) تعيين القيد القاع subview على قدم المساواة إلى cell.contentView ناقص الحشو التي تريدها. لا تضع القيود على الخلية أو cell.contentView نفسها.

2) تعيين إما tableView في rowHeightالممتلكات أو tableView:heightForRowAtIndexPath:ل UITableViewAutomaticDimension.

3) تعيين إما tableView في estimatedRowHeightالممتلكات أو tableView:estimatedHeightForRowAtIndexPath:إلى أفضل تخمين من الارتفاع.

هذا هو.







إذا قمت بذلك تخطيط برمجيا، وهنا هو ما يجب مراعاتها لدائرة الرقابة الداخلية 10 باستخدام المراسي في سويفت.

هناك ثلاث قواعد / الخطوات

رقم 1: تعيين هذه خاصيتين من tableview على viewDidLoad، أول واحد هو قول لtableview التي يجب أن نتوقع أحجام الحيوية على زنازينهم، والثاني هو لمجرد السماح التطبيق حساب حجم مؤشر شريط التمرير، لذلك يساعد ل أداء.

    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.estimatedRowHeight = 100

رقم 2: وهذا أمر مهم تحتاج إلى إضافة subviews إلى contentView الخلية ليس للنظر، وأيضا استخدام layoutsmarginguide لترسيخ subviews إلى أعلى وأسفل، وهذا هو المثال العملي لكيفية القيام بذلك.

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    setUpViews()
}

private func setUpViews() {

    contentView.addSubview(movieImageView)
    contentView.addSubview(descriptionLabel)
    let marginGuide = contentView.layoutMarginsGuide

    NSLayoutConstraint.activate([
        movieImageView.heightAnchor.constraint(equalToConstant: 80),
        movieImageView.widthAnchor.constraint(equalToConstant: 80),
        movieImageView.leftAnchor.constraint(equalTo: marginGuide.leftAnchor),
        movieImageView.topAnchor.constraint(equalTo: marginGuide.topAnchor, constant: 20),

        descriptionLabel.leftAnchor.constraint(equalTo: movieImageView.rightAnchor, constant: 15),
        descriptionLabel.rightAnchor.constraint(equalTo: marginGuide.rightAnchor),
        descriptionLabel.bottomAnchor.constraint(equalTo: marginGuide.bottomAnchor, constant: -15),
        descriptionLabel.topAnchor.constraint(equalTo: movieImageView.topAnchor)

        ])
}

إنشاء طريقة من شأنها أن تضيف إلى subviews وتنفيذ أعمال التصميم، الذي يطلق عليه في طريقة الحرف الأول.

رقم 3: لا استدعاء الأسلوب:

  override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    }

إذا كنت تفعل ذلك سوف تجاوز التطبيق الخاص بك.

اتبع هذه 3 قواعد للخلايا حيوية في tableviews.

هنا هو تطبيق العمل https://github.com/jamesrochabrun/MinimalViewController




في حالتي لدي لإنشاء خلية مخصصة مع الصورة التي تأتي من الخادم ويمكن أن يكون في أي العرض والارتفاع. واثنين من UILabels مع حجم الحيوي (كل من العرض والارتفاع)

لقد حققت نفسه هنا في جوابي مع التخطيط التلقائي وبرمجيا:

في الأساس فوقsmileyBorg الجواب ساعدت لكن systemLayoutSizeFittingSize لم يسبق لهم العمل بالنسبة لي، في وجهة نظري:

1. عدم استخدام التلقائي ارتفاع الصف الملكية الحساب. استخدام 2.No من يقدر الحاجة ارتفاع 3.No من updateConstraints لا لزوم لها. استخدام 4.No من المفضل التلقائي ماكس تخطيط العرض. 5. عدم استخدام systemLayoutSizeFittingSize (يجب أن يكون استخدام ولكن لا يعمل بالنسبة لي، أنا لا أعرف ماذا تفعل داخليا)، ولكن بدلا من ذلك لي طريقة - (تعويم) getViewHeight العمل وأنا أعرف ما تقوم به داخليا.

هل من الممكن أن يكون اختلاف ارتفاعات في خلية UITableView عند استخدام عدة طرق مختلفة لعرض الخلية؟




في حالتي، كان الحشو بسبب ارتفاعات sectionHeader وsectionFooter، حيث القصة المصورة سمحت لي لتغييره إلى الحد الأدنى 1. حتى في طريقة viewDidLoad:

tableView.sectionHeaderHeight = 0
tableView.sectionFooterHeight = 0



لضبط البعد التلقائي لارتفاع الصف وارتفاع الصف المقدرة، ضمان اتباع الخطوات لجعل، البعد السيارات فعالة للتخطيط ارتفاع الخلية / التوالي.

  • تعيين وتنفيذ DATASOURCE وتفويض
  • تعيين UITableViewAutomaticDimensionلrowHeight وestimatedRowHeight
  • تنفيذ مندوب / أساليب مصدر البيانات (أي heightForRowAtوإرجاع قيمة UITableViewAutomaticDimensionلها)

-

@IBOutlet weak var table: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Don't forget to set dataSource and delegate for table
    table.dataSource = self
    table.delegate = self

    // Set automatic dimensions for row height
    table.rowHeight = UITableViewAutomaticDimension
    table.estimatedRowHeight = UITableViewAutomaticDimension
}



// UITableViewAutomaticDimension calculates height of label contents/text
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

على سبيل المثال التسمية في UITableviewCell

  • عدد مجموعة من خطوط = 0 (ووضع خط فاصل = اقتطاع الذيل)
  • تعيين كافة القيود (أعلى، أسفل، حق اليسار) فيما يتعلق حاوية superview / خلية لها.
  • اختياري : تعيين ارتفاع الحد الأدنى للتسمية، إذا كنت تريد الحد الأدنى منطقة العمودية التسمية مغطاة، حتى إذا كان هناك أية بيانات.




لقد حاولت:

func textViewDidChange(_ textView: UITextView) {
    var frame = textView.frame
    frame.size.height = textView.contentSize.height
    textView.frame = frame
    print(frame)
    self.tableView.rowHeight = frame.size.height

ولكن على الرغم من أنني الحصول على حق وارتفاع الإطار الصف لا يتم تعديل




أنا فعلت بعض محاولة غبية والخطأ مع القيم 2 من rowHeightو estimatedRowHeightومجرد التفكير أنه قد تعطي فكرة التصحيح:

إذا قمت بتعيين لهم على حد سواء OR فقط تعيين estimatedRowHeightستحصل على السلوك المرغوب فيه:

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 1.00001 // MUST be greater than 1

انه اقترح أن تفعل أفضل ما لديكم للحصول على التقدير الصحيح، ولكن النتيجة النهائية لا يختلف. وسوف تؤثر فقط أدائك.

إذا قمت بتعيين فقط rowHeight أي فعل فقط:

tableView.rowHeight = UITableViewAutomaticDimension

نتيجة نهاية الخاص بك لن يكون كما هو مطلوب:

إذا قمت بتعيين estimatedRowHeightإلى 1 أو أصغر فإنك سوف تحطم بغض النظر عن rowHeight.

tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 1 

أنا تحطمت مع رسالة الخطأ التالية:

Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'table view row height
must not be negative - provided height for index path (<NSIndexPath:
0xc000000000000016> {length = 2, path = 0 - 0}) is -1.000000'
    ...some other lines...

libc++abi.dylib: terminating with uncaught exception of type
NSException



بعد حل آخر iOs7 + iOs8 في سويفت

var cell2height:CGFloat=44

override func viewDidLoad() {
    super.viewDidLoad()
    theTable.rowHeight = UITableViewAutomaticDimension
    theTable.estimatedRowHeight = 44.0;
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell =  tableView.dequeueReusableCellWithIdentifier("myTableViewCell", forIndexPath: indexPath) as! myTableViewCell
    cell2height=cell.contentView.height
    return cell
}

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    if #available(iOS 8.0, *) {
        return UITableViewAutomaticDimension
    } else {
        return cell2height
    }
}