UIAlertController text alignment

27,222

Solution 1

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

Swift 5 update

let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = alignment
let messageText = NSAttributedString(
    string: "message",
    attributes: [
        NSAttributedString.Key.paragraphStyle: paragraphStyle,
        NSAttributedString.Key.foregroundColor : UIColor.primaryText,
        NSAttributedString.Key.font : UIFont(name: "name", size: size)
    ]
)

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

Solution 2

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];

Solution 3

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)

Solution 4

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;

Solution 5

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")
Share:
27,222
dkaisers
Author by

dkaisers

Updated on July 09, 2022

Comments

  • dkaisers
    dkaisers almost 2 years

    Is there a way to change the alignment of the message displayed inside a UIAlertController on iOS 8?

    I believe accessing the subviews and changing it for the UILabel is not possible anymore.

  • dkaisers
    dkaisers almost 10 years
    Aren't those just the UITextFields that you can add to the UIAlertController? I only display a text through the message property that is styled as a bullet list and thus would benefit from being left aligned.
  • trojanfoe
    trojanfoe almost 10 years
    @DominikKaisers Yeah you are right; perhaps you can use the text fields and not use the message property?
  • dkaisers
    dkaisers almost 10 years
    Yeah, that probably would be a workaround. I'll give it a try, if nobody has an easier way.
  • Nurbol
    Nurbol almost 9 years
    Seems like this is private API use, did this make it into the App Store?
  • Eduardo
    Eduardo almost 9 years
    @powerj1984 yes, it did.
  • Chris Wagner
    Chris Wagner almost 9 years
    NSArray *viewArray = [[[[[[[[[[[[alertController view] subviews] firstObject] subviews] firstObject] subviews] firstObject] subviews] firstObject] subviews] firstObject] subviews]; That takes the cake for most nested ObjC I've never seen o.0
  • DerrickHo328
    DerrickHo328 almost 9 years
    Yes. Apple doesn't really want people to mess with it. It's is a far better investment to make a custom pop up alert than to tinker with something so deeply nested.
  • Chris Wagner
    Chris Wagner almost 9 years
    They never did come through with their promise, in one of the 2013 sessions they mentioned that they added a UIView property so that we could put whatever we want in there... It never made it in.
  • Bjarte
    Bjarte over 8 years
    These are the text input fields, not the message.
  • Randika Vishman
    Randika Vishman over 8 years
    Actually this is the correct modern answer for the current API I guess! It works like a charm! Sweet! Thanks man!
  • Lucas van Dongen
    Lucas van Dongen over 7 years
    What's private about it?
  • Sonic Master
    Sonic Master over 7 years
    Has someone make it to the app store?
  • Sonic Master
    Sonic Master about 7 years
    Is there any objective-c version?
  • Eduardo
    Eduardo about 7 years
    @SonicMaster sorry, but I don't have experience with Objective-C. I guess, since this is mainly assignments and calling functions, the translation should be straightforward.
  • somedev
    somedev over 6 years
    I tried to see if this method works for changing text alignment when using UIAlertAction items in UIAlertController as well, but it resulted in some key-value compliance and undefined key exceptions and the controller not displaying.
  • Naveen Kumawat
    Naveen Kumawat over 6 years
    Update for Swift 4 let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.alignment = NSTextAlignment.justified let messageText = NSMutableAttributedString( string: alertMsg, attributes: [ NSAttributedStringKey.paragraphStyle: paragraphStyle, NSAttributedStringKey.font : UIFont.preferredFont(forTextStyle: UIFontTextStyle.body), NSAttributedStringKey.foregroundColor : UIColor.black ] )
  • Akhil Shrivastav
    Akhil Shrivastav almost 6 years
    Is there any documentation for keys like "attributedMessage" and "attributedTitle"? How will I get a list of all available keys?
  • jjjjjjjj
    jjjjjjjj over 5 years
    @AkhilShrivastav google "UIAlertAction runtime headers", there are tons of undocumented keys that can be used to customize native components
  • Ariel Malka
    Ariel Malka about 5 years
    It crashes on iOS 11 (tested on real device): 'NSInvalidArgumentException', reason: '-[UIView setTextAlignment:]: unrecognized selector sent to instance...
  • Boris Gafurov
    Boris Gafurov about 5 years
    this is straight forward and does not seem too hacky, should be stable for a while
  • Sangam Belose
    Sangam Belose almost 5 years
    Please add explanation around your code. So that OP and future reader can easily understand your answer.