UIAlertController custom font doesn't work at iOS

回眸只為那壹抹淺笑 提交于 2019-12-10 12:47:56

问题


UIAlertController custom font doesn't work.

The following code is a function ShowActionSheetAsync, show ActionSheet. At this point, I want to change the font of ActionSheet. I have tried several ways, but it didn't work well. Is there good solution?

public Task<bool> ShowActionSheetAsync()
{
    var source = new TaskCompletionSource<bool>();
    var alert = new UIAlertController
    {
        Title = "title"
    };
    alert.AddAction(UIAlertAction.Create(
            "button1",
            UIAlertActionStyle.Default,
            _ => source.SetResult(true)));
    alert.AddAction(UIAlertAction.Create(
        "cancel",
        UIAlertActionStyle.Cancel,
        _ => source.SetResult(false)));

    // [Block 1]
    var viewController = UIApplication.SharedApplication.KeyWindow.RootViewController;
    ViewController.PresentViewController(alert, true, delegate
    {
        // [Block 2]
    });

    // [Block 3]
    return source.Task;
}

First attempt The following code does not work properly.

  • When I put the code on [Block 1] or [Block 2]

    • It does not work at all
  • When I put the code on [Block 3]

    • Applies only when the first show ActionSheet. From the second times, it does not work

UILabel.AppearanceWhenContainedIn(typeof(UIActionSheet)).Font = UIFont.FromName(StyleResources.MediumFontName, 20);

The second attempt The following code also does not work properly.

  • When I put the code on [Block 2]

    • After showing the default font for a short time, showing the custom font
  • When I put the code on [Block 3]

    • it work on only cancel button

FindDescendantViews<UILabel>() is a extension method for UIView and returns all child view of appropriate type.

var labels = alert.View.FindDescendantViews<UILabel>();
foreach (var label in labels)
{
    label.Font = UIFont.FromName(StyleResources.MediumFontName, 20);
}

回答1:


UIAlertController UILabels font and color can be set via KVC using the attributedTitle key. Use this in [Block 3]

func changeAlert(alert: UIAlertController, backgroundColor: UIColor, textColor: UIColor, buttonColor: UIColor?) {
    let view = alert.view.firstSubview().firstSubview()
    view.backgroundColor = backgroundColor
    view.layer.cornerRadius = 10.0

    // set color to UILabel font
    setSubviewLabelsToTextColor(textColor, view: view)

    // set font to alert via KVC, otherwise it'll get overwritten
    let titleAttributed = NSMutableAttributedString(
        string: alert.title!,
        attributes: [NSFontAttributeName:UIFont.boldSystemFontOfSize(17)])
    alert.setValue(titleAttributed, forKey: "attributedTitle")


    let messageAttributed = NSMutableAttributedString(
        string: alert.message!,
        attributes: [NSFontAttributeName:UIFont.systemFontOfSize(13)])
    alert.setValue(messageAttributed, forKey: "attributedMessage")


    // set the buttons to non-blue, if we have buttons
    if let buttonColor = buttonColor {
        alert.view.tintColor = buttonColor
    }
}

func setSubviewLabelsToTextColor(textColor: UIColor, view:UIView) {
    for subview in view.subviews {
        if let label = subview as? UILabel {
            label.textColor = textColor
        } else {
            setSubviewLabelsToTextColor(textColor, view: subview)
        }
    }
}



回答2:


It's not allowed to either subclass or change default things of an UIAlertController. You need to make a custom view for it.




回答3:


I have the solution here. I created a custom AlertThemeConfigurator that recursively runs through all the subviews looking for UILabels, then sets the themed attributedText on them for the title, message, and different types of actions. Feel free to style the attributed strings appropriately.

class AlertThemeConfigurator {

   class func configureAlertViewController(alertController : UIAlertController) {
        AlertLabelConfigurator.adjustLabels(inView: alertController.view, alertController: alertController)
   }

   class AlertLabelConfigurator {

       class func adjustLabels(inView view : UIView, alertController : UIAlertController) {
            for subview in view.subviews {

                if subview is UILabel {
                    adjustLabel((subview as! UILabel), inAlertViewController : alertController)
                }

                adjustLabels(inView :subview,  alertController : alertController)
            }
       }

       class func adjustLabel(label : UILabel, inAlertViewController alertController : UIAlertController) {
            if label.text == alertController.title {
                label.attributedText = attributedTitle(label.text!)
            } else if label.text == alertController.message {
                label.attributedText = attributedBody(label.text!)
            }

            for action in alertController.actions {
                if label.text == action.title {
                    switch action.style {
                    case .Default:
                        label.attributedText = attributedDefaultAction(action.title!)
                    case .Cancel:
                        label.attributedText = attributedCancelAction(action.title!)
                    case .Destructive:
                        label.attributedText = attributedDestructiveAction(action.title!)
                    }
                }
            }
        }

        class func attributedTitle(title : String) -> NSAttributedString {
             let attributes = [NSFontAttributeName:UIFont(name: "Avenir-Medium", size: 20)!, NSForegroundColorAttributeName :  UIColor.greenColor()]
             return NSAttributedString(string: title, attributes: attributes)
        }

        class func attributedBody(title : String) -> NSAttributedString {
             let attributes = [NSFontAttributeName:UIFont(name: "Avenir-Medium", size: 12)!, NSForegroundColorAttributeName :  UIColor.orangeColor()]
             return NSAttributedString(string: title, attributes: attributes)
        }

        class func attributedDefaultAction(title : String) -> NSAttributedString {
             let attributes = [NSFontAttributeName:UIFont(name: "Avenir-Medium", size: 14)!, NSForegroundColorAttributeName :  UIColor.yellowColor()]
             return NSAttributedString(string: title, attributes: attributes)
        }

        class func attributedCancelAction(title : String) -> NSAttributedString {
             let attributes = [NSFontAttributeName:UIFont(name: "Avenir-Medium", size: 14)!, NSForegroundColorAttributeName :  UIColor.purpleColor()]
             return NSAttributedString(string: title, attributes: attributes)
        }

        class func attributedDestructiveAction(title : String) -> NSAttributedString {
             let attributes = [NSFontAttributeName:UIFont(name: "Avenir-Medium", size: 14)!, NSForegroundColorAttributeName :  UIColor.redColor()]
             return NSAttributedString(string: title, attributes: attributes)
        }
    }
}

To present it call

 let alert = CustomAlertController(title: "Title", message:"Message" , preferredStyle: UIAlertControllerStyle.ActionSheet)
 alert.addAction(UIAlertAction(title: "Close", style: UIAlertActionStyle.Default, handler: nil))
 presentViewController(alert, animated: true, completion: nil)
 AlertThemeConfigurator.configureAlertViewController(alert)


来源:https://stackoverflow.com/questions/37406030/uialertcontroller-custom-font-doesnt-work-at-ios

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