ios - دائرة الرقابة الداخلية أوتولايوت متعدد الخطوط إيلابيل




uilabel autolayout (6)

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

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

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

التركيز مهم - وضع تخطيط ماكس يفضل يسبب تمريرة تخطيط أخرى ليتم تنفيذها، لذلك يمكنك في نهاية المطاف مع حلقة لانهائية.

بعد السؤال هو نوع من استمرار هذا واحد:

يوس: متعدد الخطوط إيلابيل في تخطيط السيارات

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

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

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

في إيفيو

-(CGSize) intrinsicContentSize

I سيتبريفيردماكسلايوتويدث لبلدي ويلابيلز وفقا ل self.frame.width.

وUIViewController

-(void) viewDidLayoutSubviews

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


كما اقترح من إجابة أخرى حاولت تجاوز viewDidLayoutSubviews :

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    _subtitleLabel.preferredMaxLayoutWidth = self.view.bounds.size.width - 40;
    [self.view layoutIfNeeded];
}

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

لم يكن هذا مقبولا بالنسبة لي.

وجدت ثم حل أفضل من خلال تجاوز updateViewConstraints :

-(void)updateViewConstraints {
    [super updateViewConstraints];

    // Multiline-Labels and Autolayout do not work well together:
    // In landscape mode the width is still "portrait" when the label determines the count of lines
    // Therefore the preferredMaxLayoutWidth must be set
    _subtitleLabel.preferredMaxLayoutWidth = self.view.bounds.size.width - 40;
}

كان هذا هو الحل الأفضل بالنسبة لي، لأنه لم يسبب "الخفقان البصري".


باستخدام بوندينغريكتويثزيز

حلت النضال مع اثنين من تسميات متعددة الخطوط في UITableViewCell القديمة التي كانت تستخدم "\ n" كسطر كسر عن طريق قياس العرض المطلوب مثل هذا:

- (CGFloat)preferredMaxLayoutWidthForLabel:(UILabel *)label
{
    CGFloat preferredMaxLayoutWidth = 0.0f;
    NSString *text = label.text;
    UIFont *font = label.font;
    if (font != nil) {
        NSMutableParagraphStyle *mutableParagraphStyle = [[NSMutableParagraphStyle alloc] init];
        mutableParagraphStyle.lineBreakMode = NSLineBreakByWordWrapping;

        NSDictionary *attributes = @{NSFontAttributeName: font,
                                     NSParagraphStyleAttributeName: [mutableParagraphStyle copy]};
        CGRect boundingRect = [text boundingRectWithSize:CGSizeZero options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil];
        preferredMaxLayoutWidth = ceilf(boundingRect.size.width);

        NSLog(@"Preferred max layout width for %@ is %0.0f", text, preferredMaxLayoutWidth);
    }


    return preferredMaxLayoutWidth;
}

ثم كان استدعاء الأسلوب ثم بسيطة مثل:

CGFloat labelPreferredWidth = [self preferredMaxLayoutWidthForLabel:textLabel];
if (labelPreferredWidth > 0.0f) {
    textLabel.preferredMaxLayoutWidth = labelPreferredWidth;
}
[textLabel layoutIfNeeded];

الحل النظيف هو تعيين rowcount = 0 واستخدام خاصية هيتكونستراينت التسمية. ثم بعد تعيين المحتوى استدعاء

CGSize sizeThatFitsLabel = [_subtitleLabel sizeThatFits:CGSizeMake(_subtitleLabel.frame.size.width, MAXFLOAT)];
_subtitleLabelHeightConstraint.constant = ceilf(sizeThatFitsLabel.height);

-(void) updateViewConstraints لديه مشكلة منذ دائرة الرقابة الداخلية 7.1.


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

ملخص، أنا:

  • ... سوبلكاسد ييلابيل
  • ... وتجاوز setBounds: إلى، إن لم يكن بالفعل تعيين ، تعيين CGRectGetWidth(bounds) إلى CGRectGetWidth(bounds)
  • ... استدعاء [super updateViewConstraints] قبل ما يلي
  • ... استدعاء layoutIfNeeded قبل الحصول على layoutIfNeeded لاستخدامها في حساب حجم التسمية

إديت: يبدو هذا الحل فقط للعمل، أو أن تكون هناك حاجة، في بعض الأحيان. كان لدي مشكلة (دائرة الرقابة الداخلية 7/8) حيث لم يتم حساب ارتفاع الملصق بشكل صحيح، كما تم إرجاع preferredMaxLayoutWidth 0 بعد أن تم تنفيذ عملية التخطيط مرة واحدة. حتى بعد بعض التجربة والخطأ (وبعد أن وجدت هذا دخول بلوق ) تحولت إلى استخدام UILabel مرة أخرى ومجرد تعيين أعلى وأسفل واليسار واليمين القيود تخطيط السيارات. ولأي سبب كان يتم تعيين ارتفاع الملصق بشكل صحيح بعد تحديث النص.


في نظام التشغيل يوس 8، يمكنك إصلاح مشكلات تخطيط العلامات متعددة الخطوط في خلية عن طريق استدعاء cell.layoutIfNeeded() بعد cell.layoutIfNeeded() وتكوين الخلية. المكالمة غير ضارة في يوس 9.

انظر إجابة نيك شنايدر. وقد اتخذ هذا الحل من التعليمات البرمجية له في https://github.com/nicksnyder/ios-cell-layout/blob/master/CellLayout/TableViewController.swift .





autolayout