[Ios] استخدام تخطيط السيارات في إيتاتفيو لتخطيطات الخلية الحيوية وارتفاعات الصف المتغير


Answers

ل 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)

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

Question

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




أنا ملفوفة @ حل 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، ولكن هناك هو الآن!




الحل المقترح من قبل سميليبورغ هو الكمال تقريبا. إذا كان لديك خلية مخصصة وتريد واحد أو أكثر 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 مع هذا ينبغي ان يعمل.







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

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

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

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




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

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

- (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;
}



tableView.estimatedRowHeight = 343.0
tableView.rowHeight = UITableViewAutomaticDimension




دعونا نقول لديك خلية مع 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




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

tableView.sectionHeaderHeight = 0
tableView.sectionFooterHeight = 0



لقد حاولت:

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

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




بعد حل آخر 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
    }
}