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.
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.
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"
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")
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")
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")
UIAlertAction
items in UIAlertController
as well, but it resulted in some key-value compliance and undefined key exceptions and the controller not displaying. –
Melchor 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];
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)
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;
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 –
Diarmit 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")
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"];
}
I noticed that some answers used a private API, which is not secure. I have a safer and simpler approach to achieve the same goal. Here is the code:
public extension UIAlertController {
func demo() {
title = "My Title"
message = "My subtitle\nsecond line\nthird line"
let messageLabel = findMessageLabel()
messageLabel?.textAlignment = .left
}
func findMessageLabel() -> UILabel? {
let originMessage = self.message
let secret = UUID().uuidString
self.message = secret
let resultLabel = findMessageLabel(in: view, secret: secret)
self.message = originMessage
return resultLabel
}
private func findMessageLabel(in targetView: UIView, secret: String) -> UILabel? {
if let label = targetView as? UILabel, label.text == secret {
return label
}
for subview in targetView.subviews {
if let label = findMessageLabel(in: subview, secret: secret) {
return label
}
}
return nil
}
}
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.
yourAlertController.messageLabel.textAlignment = NSTextAlignmentLeft;
© 2022 - 2024 — McMap. All rights reserved.