UIAlertController text alignment

ぃ、小莉子 提交于 2019-11-27 19:37:25
Eduardo

I have successfully used the following, for both aligning and styling the text of UIAlertControllers:

let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = NSTextAlignment.Left

let messageText = NSMutableAttributedString(
    string: "The message you want to display",
    attributes: [
        NSParagraphStyleAttributeName: paragraphStyle,
        NSFontAttributeName : UIFont.preferredFontForTextStyle(UIFontTextStyleBody),
        NSForegroundColorAttributeName : UIColor.blackColor()
    ]
)

myAlert.setValue(messageText, forKey: "attributedMessage")

You can do a similar thing with the title, if you use "attributedTitle", instead of "attributedMessage"

Swift 3 update

The above still works in Swift 3, but the code has to be slightly altered to this:

let messageText = NSMutableAttributedString(
    string: "The message you want to display",
    attributes: [
        NSParagraphStyleAttributeName: paragraphStyle,
        NSFontAttributeName : UIFont.preferredFont(forTextStyle: UIFontTextStyle.body),
        NSForegroundColorAttributeName : UIColor.black
    ]
)

myAlert.setValue(messageText, forKey: "attributedMessage")

Swift 4 update

let messageText = NSMutableAttributedString(
    string: "The message you want to display",
    attributes: [
        NSAttributedStringKey.paragraphStyle: paragraphStyle,
        NSAttributedStringKey.font: UIFont.preferredFont(forTextStyle: UIFontTextStyle.body),
        NSAttributedStringKey.foregroundColor: UIColor.black
    ]
)

myAlert.setValue(messageText, forKey: "attributedMessage")

Use the below code

UIAlertController * alert = [UIAlertController
                                 alertControllerWithTitle:[title lowercaseString]
                                 message:[message lowercaseString]
                                 preferredStyle:UIAlertControllerStyleAlert];

    if (alertStyle == kUIAlertStylePlainText)
    {
        [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {

        }];
    }

    if (okTitle) {
        UIAlertAction* ok = [UIAlertAction actionWithTitle:[okTitle lowercaseString] style:UIAlertActionStyleDefault
                                                   handler:^(UIAlertAction * action) {
                                                       callback(alert, action, nil);
                                                   }];
        [alert addAction:ok];
    }

    if (cancelTitle) {
        UIAlertAction* cancel = [UIAlertAction actionWithTitle:[cancelTitle lowercaseString] style:UIAlertActionStyleDefault
                                                       handler:^(UIAlertAction * action) {
                                                           callback(alert, nil, action);
                                                       }];
        [alert addAction:cancel];
    }


    NSMutableParagraphStyle *paraStyle = [[NSMutableParagraphStyle alloc] init];
    paraStyle.alignment = NSTextAlignmentLeft;

    NSMutableAttributedString *atrStr = [[NSMutableAttributedString alloc] initWithString:[message lowercaseString] attributes:@{NSParagraphStyleAttributeName:paraStyle,NSFontAttributeName:[UIFont systemFontOfSize:13.0]}];

    [alert setValue:atrStr forKey:@"attributedMessage"];
    [viewInstance presentViewController:alert animated:YES completion:nil];

Navigate to subview tree until you get to the UILabels for the title and the message

NSArray *viewArray = [[[[[[[[[[[[alertController view] subviews] firstObject] subviews] firstObject] subviews] firstObject] subviews] firstObject] subviews] firstObject] subviews];
UILabel *alertTitle = viewArray[0]
UILabel *alertMessage = viewArray[1];
alertMessage.textAlignment = NSTextAlignmentLeft;

However, you may want to make an category for it

@interface UIAlertController (ShowMeTheLabels)

@property (nonatomic, strong) UILabel *titleLabel, *messageLabel;

@end

@implementation UIAlertController (ShowMeTheLabels)
@dynamic titleLabel;
@dynamic messageLabel;

- (NSArray *)viewArray:(UIView *)root {
    NSLog(@"%@", root.subviews);
    static NSArray *_subviews = nil;
    _subviews = nil;
    for (UIView *v in root.subviews) {
        if (_subviews) {
            break;
        }
        if ([v isKindOfClass:[UILabel class]]) {
            _subviews = root.subviews;
            return _subviews;
        }
        [self viewArray:v];
    }
    return _subviews;
}

- (UILabel *)titleLabel {
    return [self viewArray:self.view][0];
}

- (UILabel *)messageLabel {
    return [self viewArray:self.view][1];
}

@end

Then you can align the text like this

yourAlertController.messageLabel.textAlignment = NSTextAlignmentLeft;

The following method will set the text alignment, while preserving the default font size.

static void makeAlertControllerLeftAligned( UIAlertController* avc )
{
    NSMutableParagraphStyle *paraStyle = [[[NSMutableParagraphStyle alloc] init] autorelease];
    paraStyle.alignment = NSTextAlignmentLeft;
    NSMutableAttributedString *atrStr =
        [[[NSMutableAttributedString alloc] initWithString:avc.message attributes:@{
             NSParagraphStyleAttributeName:paraStyle,
             NSFontAttributeName: [UIFont preferredFontForTextStyle: UIFontTextStyleFootnote],
         }]
         autorelease];
    [avc setValue:atrStr forKey:@"attributedMessage"];
}

Swift 4.2 + multiline string linebreak indentation

let paragraphStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle

paragraphStyle.headIndent = 14

let messageText = NSMutableAttributedString(
    string: "... multiline string need linebreak indentation ...",
    attributes: [
        NSAttributedString.Key.paragraphStyle: paragraphStyle,
        NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12),
        NSAttributedString.Key.foregroundColor: UIColor.gray
    ]
)

alert.setValue(messageText, forKey: "attributedMessage")

I took up @Amos's answer and made it into a convenient extension:

public extension UIAlertController {

    func setMessageAlignment(_ alignment : NSTextAlignment) {
        let paragraphStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
        paragraphStyle.alignment = alignment

        let messageText = NSMutableAttributedString(
            string: self.message ?? "",
            attributes: [
                NSAttributedString.Key.paragraphStyle: paragraphStyle,
                NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12),
                NSAttributedString.Key.foregroundColor: UIColor.gray
            ]
        )

        self.setValue(messageText, forKey: "attributedMessage")
    }
}

Then you can simply set the alignment value: myAlert.setMessageAlignment(.left)

This property exposes the text fields, so could probably be used to configure them:

textFields

The array of text fields displayed by the alert. (read-only)

Declaration

SWIFT

var textFields: [AnyObject]? { get }

OBJECTIVE-C

@property(nonatomic, readonly) NSArray *textFields

Discussion

Use this property to access the text fields displayed by the alert. The text fields are in the order in which you added them to the alert controller. This order also corresponds to the order in which they are displayed in the alert.

Note: even though it says the property is readonly, it returns an array of text field object references which can be used to modify the controls.

Nagabhushan Vaddi
yourAlertController.messageLabel.textAlignment = NSTextAlignmentLeft;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!