ios - كيف يمكنك إضافة نص متعدد الأسطر إلى UIButton؟




cocoa-touch uikit (15)

لدي الكود التالي ...

UILabel *buttonLabel = [[UILabel alloc] initWithFrame:targetButton.bounds];
buttonLabel.text = @"Long text string";
[targetButton addSubview:buttonLabel];
[targetButton bringSubviewToFront:buttonLabel];

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


سويفت 3

button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.textAlignment = .center  
button.setTitle("Button\nTitle",for: .normal)

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


إذا كنت تستخدم التخطيط التلقائي.

button.titleLabel?.adjustsFontSizeToFitWidth = true
button.titleLabel?.numberOfLines = 2

إذا كنت تستخدم التنسيق التلقائي على نظام التشغيل iOS 6 ، فقد تحتاج أيضًا إلى تعيين الخاصية preferredMaxLayoutWidth :

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;
button.titleLabel.preferredMaxLayoutWidth = button.frame.size.width;

انها تعمل على أكمل وجه.

إضافة إلى استخدام هذا مع ملف التكوين مثل Plist ، تحتاج إلى استخدام CDATA لكتابة العنوان متعدد الأسطر ، مثل هذا:

<string><![CDATA[Line1
Line2]]></string>

بادئ ذي بدء ، يجب أن تكون على علم بأن UIButton لديها بالفعل UILabel داخله. يمكنك ضبطه باستخدام –setTitle:forState:

المشكلة مع المثال الخاص بك أن تحتاج إلى تعيين خاصية UILabel's numberOfLines إلى شيء آخر غير قيمته الافتراضية 1. يجب عليك أيضاً مراجعة الخاصية lineBreakMode .


بالنسبة لأولئك الذين يستخدمون لوحة العمل الخاصة بـ Xcode 4 ، يمكنك النقر فوق الزر ، وفي الجزء الأيسر من الجزء المرافق ، ضمن Attributes Inspector ، سترى خيارًا لـ Line Break. اختر Word Wrap ، ويجب أن تكون على ما يرام.


بالنسبة لفكرة برينت عن وضع عنوان UILabel كأنه وجهة نظر الأخوة ، لا يبدو لي وكأنه فكرة جيدة للغاية. أظل أفكر في مشاكل التفاعل مع UILabel بسبب أحداث اللمس التي لا تمر عبر رؤية UIButton.

من ناحية أخرى ، مع UILabel باعتباره عرضًا فرعيًا لـ UIButton ، فأنا مرتاح جدًا مع العلم أن أحداث اللمس سيتم نشرها دائمًا في مشاهدة UILabel الفائقة.

لقد اتخذت هذا النهج ولم ألاحظ أي من المشاكل التي ذكرت مع backgroundImage. لقد أضفت هذا الرمز في -titleRectForContentRect: من فئة UIButton الفرعية ولكن يمكن أيضًا وضع الشفرة في روتين الرسم الخاص بـ superio UIButton ، والذي في هذه الحالة يجب عليك استبدال كل الإشارات إلى الذات بمتغير UIButton.

#define TITLE_LABEL_TAG 1234

- (CGRect)titleRectForContentRect:(CGRect)rect
{   
    // define the desired title inset margins based on the whole rect and its padding
    UIEdgeInsets padding = [self titleEdgeInsets];
    CGRect titleRect = CGRectMake(rect.origin.x    + padding.left, 
                                  rect.origin.x    + padding.top, 
                                  rect.size.width  - (padding.right + padding.left), 
                                  rect.size.height - (padding.bottom + padding].top));

    // save the current title view appearance
    NSString *title = [self currentTitle];
    UIColor  *titleColor = [self currentTitleColor];
    UIColor  *titleShadowColor = [self currentTitleShadowColor];

    // we only want to add our custom label once; only 1st pass shall return nil
    UILabel  *titleLabel = (UILabel*)[self viewWithTag:TITLE_LABEL_TAG];


    if (!titleLabel) 
    {
        // no custom label found (1st pass), we will be creating & adding it as subview
        titleLabel = [[UILabel alloc] initWithFrame:titleRect];
        [titleLabel setTag:TITLE_LABEL_TAG];

        // make it multi-line
        [titleLabel setNumberOfLines:0];
        [titleLabel setLineBreakMode:UILineBreakModeWordWrap];

        // title appearance setup; be at will to modify
        [titleLabel setBackgroundColor:[UIColor clearColor]];
        [titleLabel setFont:[self font]];
        [titleLabel setShadowOffset:CGSizeMake(0, 1)];
        [titleLabel setTextAlignment:UITextAlignmentCenter];

        [self addSubview:titleLabel];
        [titleLabel release];
    }

    // finally, put our label in original title view's state
    [titleLabel setText:title];
    [titleLabel setTextColor:titleColor];
    [titleLabel setShadowColor:titleShadowColor];

    // and return empty rect so that the original title view is hidden
    return CGRectZero;
}

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


سويفت 4.0

btn.titleLabel?.lineBreakMode = .byWordWrapping
btn.titleLabel?.textAlignment = .center
btn.setTitle( "Line1\nLine2", for: .normal)

ضبط lineBreakMode إلى NSLineBreakByWord يؤدي التفاف (إما في IB أو الرمز) إلى تسمية متعددة للزر ، لكنه لا يؤثر على إطار الزر.

إذا كان الزر يحمل عنوانًا ديناميكيًا ، فهناك خدعة واحدة: ضع UILabel المخفية بنفس الخط وربطه بارتفاع الزر مع التخطيط ؛ عند تعيين النص على زر والتسمية و autolayout سيجعل كل عمل.

ملحوظة

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


لإعادة صياغة اقتراح روجر نولان ، ولكن مع رمز صريح ، هذا هو الحل العام:

button.titleLabel?.numberOfLines = 0

لفة الطبقة زر الخاصة بك. إنه أفضل حل على المدى البعيد. UIButton ودروس UIKit الأخرى مقيدة للغاية في كيفية تخصيصها.


هناك طريقة أسهل بكثير:

someButton.lineBreakMode = UILineBreakModeWordWrap;

(تعديل لـ iOS 3 والإصدارات الأحدث :)

someButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;

يجب عليك إضافة هذا الرمز:

buttonLabel.titleLabel.numberOfLines = 0;

self.btnError.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping

self.btnError.titleLabel?.textAlignment = .center

self.btnError.setTitle("Title", for: .normal)




uikit