سؤال

أقوم بإنشاء تطبيق سيحتوي على سؤال في ملف UILabel ويتم عرض إجابات الاختيار من متعدد في UITableView, ، يعرض كل صف اختيارًا متعددًا.سوف تختلف الأسئلة والأجوبة، لذلك أنا بحاجة إلى هذا UITableView أن تكون ديناميكية في الارتفاع.

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

هل يمكن لأي شخص أن ينصحني كيف يمكنني تحقيق ذلك؟

هل كانت مفيدة؟

المحلول

في الواقع لقد وجدت الجواب بنفسي.

أنا فقط إنشاء جديد CGRect ل tableView.frame مع ال height من table.contentSize.height

الذي يضع ارتفاع UITableView إلى height من محتواها. نظرًا لأن الكود يعدل واجهة المستخدم ، فلا تنسى تشغيله في الموضوع الرئيسي:

dispatch_async(dispatch_get_main_queue(), ^{
        //This code will run in the main thread:
        CGRect frame = self.tableView.frame;
        frame.size.height = self.tableView.contentSize.height;
        self.tableView.frame = frame;
    });

نصائح أخرى

Swift 5 و 4.2 الحل بدون KVO ، Dispatchqueue ، أو وضع قيود بنفسك.

يعتمد هذا الحل على إجابة جولز.

1) إنشاء فئة فرعية من UITableView:

import UIKit

final class ContentSizedTableView: UITableView {
    override var contentSize:CGSize {
        didSet {
            invalidateIntrinsicContentSize()
        }
    }

    override var intrinsicContentSize: CGSize {
        layoutIfNeeded()
        return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
    }
}

2) إضافة أ UITableView إلى تخطيطك وضبط القيود على جميع الجوانب. اضبط فئة ذلك على ContentSizedTableView.

3) يجب أن ترى بعض الأخطاء ، لأن القصة المصورة لا تأخذ الفئة الفرعية لدينا " intrinsicContentSize داخل الحساب. إصلاح هذا عن طريق فتح مفتش الحجم والتغلب على interinsicontentsize إلى قيمة العنصر النائب. هذا هو تجاوز وقت التصميم. في وقت التشغيل ، سوف يستخدم التجاوز في لدينا ContentSizedTableView صف دراسي


تحديث: تم تغيير الكود لـ Swift 4.2. إذا كنت تستخدم إصدارًا مسبقًا ، فاستخدم UIViewNoIntrinsicMetric بدلاً من UIView.noIntrinsicMetric

حل سريع

اتبع هذه الخطوات:

1- اضبط قيود الارتفاع للجدول من لوحة العمل.

2- اسحب قيود الارتفاع من لوحة العمل وإنشاء @aboutlet لذلك في ملف وحدة التحكم في العرض.

    @IBOutlet weak var tableHeight: NSLayoutConstraint!

3- ثم يمكنك تغيير ارتفاع الجدول الديناميكي باستخدام هذا الرمز:

override func viewWillLayoutSubviews() {
    super.updateViewConstraints()
    self.tableHeight?.constant = self.table.contentSize.height
}

تحديث

إذا تم قطع الصف الأخير بالنسبة لك ، فحاول استدعاء ViewWillLayoutsubViews () في وظيفة خلية Willdisplay:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    self.viewWillLayoutSubviews()
}

لقد جربت هذا في iOS 7 وعملت بالنسبة لي

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.tableView sizeToFit];
}

أضف مراقبًا للخاصية المحتوية على عرض الجدول ، وضبط حجم الإطار وفقًا لذلك

[your_tableview addObserver:self forKeyPath:@"contentSize" options:0 context:NULL];

ثم في رد الاتصال:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    {
         CGRect frame = your_tableview.frame;
         frame.size = your_tableview.contentSize;
         your_tableview.frame = frame;
    }

ارجوا ان يساعدك هذا.

في حال كنت لا ترغب في تتبع تغيير حجم محتوى عرض الجدول بنفسك ، فقد تجد هذه الفئة الفرعية مفيدة.

protocol ContentFittingTableViewDelegate: UITableViewDelegate {
    func tableViewDidUpdateContentSize(_ tableView: UITableView)
}

class ContentFittingTableView: UITableView {

    override var contentSize: CGSize {
        didSet {
            if !constraints.isEmpty {
                invalidateIntrinsicContentSize()
            } else {
                sizeToFit()
            }

            if contentSize != oldValue {
                if let delegate = delegate as? ContentFittingTableViewDelegate {
                    delegate.tableViewDidUpdateContentSize(self)
                }
            }
        }
    }

    override var intrinsicContentSize: CGSize {
        return contentSize
    }

    override func sizeThatFits(_ size: CGSize) -> CGSize {
        return contentSize
    }
}

كان لدي عرض جدول داخل عرض التمرير واضطررت إلى حساب ارتفاع TableView وتغيير حجمه وفقًا لذلك. هذه خطوات اتخذتها:

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

1) إنشاء فئة فرعية من UitableView:

class IntrinsicTableView: UITableView {

    override var contentSize:CGSize {
        didSet {
            self.invalidateIntrinsicContentSize()
        }
    }

    override var intrinsicContentSize: CGSize {
        self.layoutIfNeeded()
        return CGSize(width: UIViewNoIntrinsicMetric, height: contentSize.height)
    }

}

2) تعيين فئة من عرض الجدول في القصة المصورة إلى intrinsactableview: لقطة الشاشة: http://joxi.ru/a2xeenpsybwq0a

3) قم بتعيين أوجه الارتفاع على عرض الجدول الخاص بك

4) اسحب iboutlet من طاولتك إلى ViewController

5) اسحب Iboutlet من قيود ارتفاع طاولتك إلى ViewController

6) أضف هذه الطريقة إلى ViewController:

override func viewWillLayoutSubviews() {
        super.updateViewConstraints()
        self.yourTableViewsHeightConstraint?.constant = self.yourTableView.intrinsicContentSize.height
    }

أتمنى أن يساعدك هذا

سويفت 3، آي أو إس 10.3

الحل 1:فقط ضع self.tableview.sizeToFit() في cellForRowAt indexPath وظيفة.تأكد من ضبط ارتفاع عرض الطاولة على مستوى أعلى مما تحتاجه.يعد هذا حلاً جيدًا إذا لم يكن لديك طرق عرض أسفل عرض الطاولة.ومع ذلك، إذا كان لديك، فلن يتم تحديث قيد عرض الجدول السفلي (لم أحاول إصلاحه لأنني توصلت إلى الحل 2)

مثال:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell", for: indexPath) as? TestCell {
        cell.configureCell(data: testArray[indexPath.row])
        self.postsTableView.sizeToFit()
        return cell
    }

    return UITableViewCell()
}

الحل 2:قم بتعيين قيد ارتفاع عرض الطاولة في لوحة العمل واسحبه إلى ViewController.إذا كنت تعرف متوسط ​​ارتفاع خليتك وتعرف عدد العناصر التي تحتوي عليها مصفوفتك، فيمكنك القيام بشيء مثل هذا:

tableViewHeightConstraint.constant = CGFloat(testArray.count) * 90.0     // Let's say 90 is the average cell height

*يحرر:

بعد كل الحلول التي جربتها وكان كل واحد منهم يصلح شيئًا ما، ولكن ليس بشكل كامل، هذا هو الجواب الذي يشرح هذه المشكلة ويصلحها بالكامل.

في حالة عدم وجود محتوياتك على صواب ، فهذا يعتمد على المقدر (التلقائي) ، استخدم هذا من قبل

TableView.ESTimatedRowHeight = 0 ؛

مصدر : https://forums.developer.apple.com/thread/81895

إجابة ميمو و إجابة Anooj VM كلاهما رائع ولكن هناك مشكلة صغيرة إذا كان لديك قائمة كبيرة ، فمن الممكن أن يقطع ارتفاع الإطار بعض خلاياك.

لذا. لقد قمت بتعديل الإجابة قليلاً:

dispatch_async(dispatch_get_main_queue()) {
    //This code will run in the main thread:
    CGFloat newHeight=self.tableView.contentSize.height;
    CGFloat screenHeightPermissible=(self.view.bounds.size.height-self.tableView.frame.origin.y);
    if (newHeight>screenHeightPermissible)
    {
        //so that table view remains scrollable when 'newHeight'  exceeds the screen bounds
        newHeight=screenHeightPermissible;
    }

    CGRect frame = self.tableView.frame;
    frame.size.height = newHeight;
    self.tableView.frame = frame;
}

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

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    for constraint in tableView.constraints {
        if constraint.firstItem as? UITableView == tableView {
            if constraint.firstAttribute == .height {
                constraint.constant = tableView.contentSize.height
            }
        }
    }
}

كامتداد لإجابة Anooj VM ، أقترح ما يلي تحديث حجم المحتوى فقط عندما يتغير.

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

- (void)viewDidLoad {
        [super viewDidLoad];
        [self.tableView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:NULL]; 
}


- (void)resizeTableAccordingToContentSize:(CGSize)newContentSize {
        CGRect superviewTableFrame  = self.tableView.superview.bounds;
        CGRect tableFrame = self.tableView.frame;
        BOOL shouldScroll = newContentSize.height > superviewTableFrame.size.height;
        tableFrame.size = shouldScroll ? superviewTableFrame.size : newContentSize;
        [UIView animateWithDuration:0.3
                                    delay:0
                                    options:UIViewAnimationOptionCurveLinear
                                    animations:^{
                            self.tableView.frame = tableFrame;
        } completion: nil];
        self.tableView.scrollEnabled = shouldScroll;
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
    if ([change[NSKeyValueChangeKindKey] unsignedIntValue] == NSKeyValueChangeSetting &&
        [keyPath isEqualToString:@"contentSize"] &&
        !CGSizeEqualToSize([change[NSKeyValueChangeOldKey] CGSizeValue], [change[NSKeyValueChangeNewKey] CGSizeValue])) {
        [self resizeTableAccordingToContentSize:[change[NSKeyValueChangeNewKey] CGSizeValue]];
    } 
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    [super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
    [self resizeTableAccordingToContentSize:self.tableView.contentSize]; }

- (void)dealloc {
    [self.tableView removeObserver:self forKeyPath:@"contentSize"];
}

نسخة OBJC من Musa Almatri

(void)viewWillLayoutSubviews
{
    [super updateViewConstraints];
    CGFloat desiredHeight = self.tableView.contentSize.height;
    // clamp desired height, if needed, and, in that case, leave scroll Enabled
    self.tableHeight.constant = desiredHeight;
    self.tableView.scrollEnabled = NO;
}

يمكنك تجربة هذه العادة AGTableView

لتعيين قيود ارتفاع TableView باستخدام القصة المصورة أو برمجيًا. (تجلب هذه الفئة تلقائيًا قيود الارتفاع وتعيين ارتفاع عرض المحتوى على ارتفاع YouRtableView).

class AGTableView: UITableView {

    fileprivate var heightConstraint: NSLayoutConstraint!

    override init(frame: CGRect, style: UITableViewStyle) {
        super.init(frame: frame, style: style)
        self.associateConstraints()
    }

    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.associateConstraints()
    }

    override open func layoutSubviews() {
        super.layoutSubviews()

        if self.heightConstraint != nil {
            self.heightConstraint.constant = self.contentSize.height
        }
        else{
            self.sizeToFit()
            print("Set a heightConstraint to Resizing UITableView to fit content")
        }
    }

    func associateConstraints() {
        // iterate through height constraints and identify

        for constraint: NSLayoutConstraint in constraints {
            if constraint.firstAttribute == .height {
                if constraint.relation == .equal {
                    heightConstraint = constraint
                }
            }
        }
    }
}

ملحوظة إذا كان هناك أي مشكلة لتعيين ارتفاع yourTableView.layoutSubviews().

بناء على إجابة FL034. لكن ل Xamarin.ios المستخدمون:

    [Register("ContentSizedTableView")]
    public class ContentSizedTableView : UITableView
    {
        public ContentSizedTableView(IntPtr handle) : base(handle)
        {
        }

        public override CGSize ContentSize { get => base.ContentSize; set { base.ContentSize = value; InvalidateIntrinsicContentSize(); } }
        public override CGSize IntrinsicContentSize
        {
            get
            {
                this.LayoutIfNeeded();
                return new CGSize(width: NoIntrinsicMetric, height: ContentSize.Height);
            }
        }
    }

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

هذا يتجنب الكثير من الحسابات والمكالمات للتخطيط.

حل MU لهذا في Swift 3: استدعاء هذه الطريقة في viewDidAppear

func UITableView_Auto_Height(_ t : UITableView)
{
        var frame: CGRect = t.frame;
        frame.size.height = t.contentSize.height;
        t.frame = frame;        
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top