I am trying to change the title and message font for an alert shown using UIAlertController
I am trying to do using an NSAttributedStirng, but it gives compiler error that a NSAttributed string cannot be taken instead of Stirng
I tried something similar to this
var title_attrs = [NSFontAttributeName : CustomFonts.HELVETICA_NEUE_MEDIUM_16]
var msg_attrs = [NSFontAttributeName : CustomFonts.HELVETICA_NEUE_REGULAR_14]
var title = NSMutableAttributedString(string:"Done", attributes:title_attrs)
var msg = NSMutableAttributedString(string:"The job is done ", attributes:msg_attrs)
let alertController = UIAlertController(title: title, message: title , preferredStyle: UIAlertControllerStyle.Alert)
Can someone guide me how can I achieve this?
Swift 3 Version:
extension UIAlertController {
func changeFont(view: UIView, font:UIFont) {
for item in view.subviews {
if item.isKind(of: UICollectionView.self) {
let col = item as! UICollectionView
for row in col.subviews{
changeFont(view: row, font: font)
}
}
if item.isKind(of: UILabel.self) {
let label = item as! UILabel
label.font = font
}else {
changeFont(view: item, font: font)
}
}
}
open override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
let font = YOUR_FONT
changeFont(view: self.view, font: font! )
}
}
I think Apple removed the attributedTitle and -message from the API. It was never part of the public API so it might be that Apple will not allow your app in the app store if you used it.
You should use the UIAlertController as is. If you want to customise it a bit see this NSHipster post. If you want more control, create a custom View to display.
let myString = "Alert Title"
var myMutableString = NSMutableAttributedString()
myMutableString = NSMutableAttributedString(string: myString as String, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 18.0)!])
myMutableString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: NSRange(location:0,length:myString.characters.count))
alertController.setValue(myMutableString, forKey: "attributedTitle")
alertController.setValue(myMutableString, forKey: "attributedMessage")
extension UIAlertController {
func changeFont(view:UIView,font:UIFont) {
for item in view.subviews {
if item.isKindOfClass(UICollectionView) {
let col = item as! UICollectionView
for row in col.subviews{
changeFont(row, font: font)
}
}
if item.isKindOfClass(UILabel) {
let label = item as! UILabel
label.font = font
}else {
changeFont(item, font: font)
}
}
}
public override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
let font = UIFont(name: YourFontName, size: YourFontSize)
changeFont(self.view, font: font! )
}
}
Related
I try to make BarChart using https://github.com/CoreCharts/CoreCharts I have a button, which call UIAlertController with textField.
After I click submit button, new data is added to the array. I need the diagram to reboot.
#IBAction func newWeightButton(_ sender: Any) {
//updateGraph()
let alert = UIAlertController(title: "Enter your new weight", message: nil, preferredStyle: .alert)
alert.addTextField()
let submitAction = UIAlertAction(title: "Add", style: .default) { [unowned alert] _ in
let textField = alert.textFields![0]
textField.keyboardType = UIKeyboardType.numberPad
textField.becomeFirstResponder()
let answer = Double(textField.text!)
self.weightArr.append(answer!)
print(self.weightArr)
self.loadCoreChartData()
}
alert.addAction(submitAction)
present(alert, animated: true)
}
func loadCoreChartData() -> [CoreChartEntry] {
return getWeightList()
}
func getWeightList()->[CoreChartEntry] {
var allResults = [CoreChartEntry]()
//let days = ["Mon","Tue","Wed","Thur","Fri"]
let plateNumber = [80,75,90,88,84]
var count = self.weightArr.count
for index in 0..<count {
let newEntry = CoreChartEntry(id: "\(self.weightArr[index])",
barTitle: "Day",
barHeight: Double(self.weightArr[index]),
barColor: UIColor(red: 0, green: 122/255, blue: 1, alpha: 1))
allResults.append(newEntry)
}
For CoreCharts, call reload() on the chart.
Generally, in iOS, setting properties of the UIView is sufficient to get it to update, but with views that use a datasource of some type (like tables, collection views, and core charts), there is usually some kind of reload...() function to tell the view that the datasource changed.
I know that it is possible to set font family, font size and color separately for «large» and «small» titles using prefersLargeTitles.
The question is: is there any options for navigation controller to show the «large title» in opened navigation panel with uppercase?
Now I use custom Navigation Controller:
class MyNavigationController: UINavigationController {
public var titleSaved: String?
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
guard let topItem = navigationBar.topItem else {
return
}
if navigationBar.frame.size.height > 60 {
topItem.title = topItem.title?.uppercased()
} else {
if let titleSaved = titleSaved {
topItem.title = titleSaved
} else {
topItem.title = topItem.title?.applyingTransform(StringTransform(rawValue: "Title"), reverse: false)
}
}
}
}
Set title from View Controlle:
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.prefersLargeTitles = true
let title = "Sign In"
navigationItem.title = title
if let nc = navigationController as? MyNavigationController {
nc.titleSaved = title
}
}
}
this solution works, but when you switch from "large" title to "small" title and backwards it twitches and it looks pretty buggy
You can have an uppercased title for «large title» and capitalized title for «small title» using Small caps fonts
Change titleTextAttributes with other font and change largeTitleTextAttributes with caps font
class ViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Sign In"
self.navigationController?.navigationBar.prefersLargeTitles = true
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.red]
self.navigationController?.navigationBar.largeTitleTextAttributes = [.foregroundColor: UIColor.red,
.font:UIFont(name: "Panton-LightCaps", size: 30)!]
}
}
Or You can customize your font. I've created a new style font using OpenSans in http://www.glyphrstudio.com/online/
You can download it here
self.title = "Sign In"
self.navigationController?.navigationBar.prefersLargeTitles = true
self.navigationController?.navigationBar.titleTextAttributes = [.font:UIFont(name: "OpenSans-Regular", size: 30)!]
self.navigationController?.navigationBar.largeTitleTextAttributes = [.font:UIFont(name: "MyFontRegular", size: 30)!]
you can try like this:
navigationController?.navigationBar.prefersLargeTitles = true
let NavigationTitle = "Sign in"
navigationController?.navigationBar.topItem?.title = NavigationTitle.uppercased()
You just try to set a navigationbar title as uppercased. and set pregfersLargeTitles as true
self.navigationController?.navigationBar.prefersLargeTitles = true
self.title = "title".uppercased()
Check this:
I'm trying to make a clickable UILabel by following with this code:
let tap_plato = UITapGestureRecognizer(target: self, action: #selector(ViewController.ale_plato1))
plato1.isUserInteractionEnabled = true
plato1.addGestureRecognizer(tap_plato)
...
#objc
func ale_plato1(sender: UITapGestureRecognizer){
let label = sender.view
print ("tapped!")
}
This works well. But I want to pass parameters to the function. Something like this:
let tap_plato = UITapGestureRecognizer(target: self, action: #selector(MenuController.ale_plato1("parameter")))
plato1.isUserInteractionEnabled = true
plato1.addGestureRecognizer(tap_plato)
#objc
func ale_plato1(sender: UITapGestureRecognizer, parameterRecived: String){
}
But I don't know how do that in swift 3...
Any help? Thanks you
Wherever you make your multiple UILabel set each label to a different tag.
for i in 0..<3 {
let label = UILabel()
label.tag = i
let tap = UITapGestureRecognizer(target: self, action: #selector(tap))
label.isUserInteractionEnabled = true
label.addGestureRecognizer(tap_plato)
}
#objc func tap(sender: UITapGestureRecognizer) {
let label = sender.view as! UILabel // if you are SURE that your tap will be a UILabel
if(label.tag == 0) {
label.text = "This is label 0"
if(label.tag == 1) {
label.text = "This is label 1"
}
}
Threw this up in a jiffy, hop over the syntax issues if there are any.
Here we can create labels with tags and apply the same tap to them. From there, we can check what tag it is inside the tap method and do something from there.
You could use the tag attribute for Int values, but if you want anything other than that:
Create a custom UILabel Class with a value variable.
class LabelWithValue : UILabel {
var value : String = ""
}
Then you can use it as a normal Label
let label = LabelWithValue()
label.text = "bla"
label.value = "Anything"
label.isUserInteractionEnabled = true
label.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleGetText)))
Then you can get it's text and it's value.
#objc func handleGetText(_ sender : UITapGestureRecognizer) {
if let label = sender.view as? LabelWithValue {
print(label.text)
print(label.value)
}
}
I need to change font of buttons in UIAlertController, I've used the code below, but I doesn't work properly, because when the user touches the buttons of UIAlertController, the font will be change to it's default.
extension UIAlertController {
private func changeFont(view:UIView,font:UIFont) {
for item in view.subviews {
if let col = item as? UICollectionView {
for row in col.subviews{
changeFont(view: row, font: font)
}
}
if let label = item as? UILabel {
label.font = font
} else {
changeFont(view: item, font: font)
}
}
}
//To set font for any UILabels in action sheet
open override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
let font = MyCustomFont
changeFont(view: self.view, font: font! )
}
}
and here is the usage of this extension:
let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let action = UIAlertAction(title: STRING_OF_ACTION, style: .default) { _ in
//some action code
}
optionMenu.addAction(action)
//in UIViewController
self.present(optionMenu, animated: true, completion: nil)
It's hard to change it because the iOS system doesn't provide the API for us to do it. So we'd better use third party libraries like: SCLAlertView-Swift or PopupDialog if we need some customization.
I do have a UIScrollView only containing a UILabel. The UILabel contains an NSAttributedString made out of HTML:
let str = try NSAttributedString(data: content.data(using: String.Encoding.unicode, allowLossyConversion: true)!, options: [NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType], documentAttributes: nil)
Now I would like to let the user zoom the label to have everything bigger. When only using
func viewForZooming(in scrollView: UIScrollView) -> UIView?
everything works as expected, but the font gets blurry. I tried changing the font size after zooming:
func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {
myLabel.setFontSize(pointSize: scrollView.zoomScale)
}
with the function being the following:
extension UILabel {
func setFontSize(pointSize: CGFloat) {
let fullRange = NSRange(location: 0, length: text!.count)
let mutableAttributeText = NSMutableAttributedString(attributedString: attributedText!)
mutableAttributeText.enumerateAttribute(NSFontAttributeName, in: fullRange, options: NSAttributedString.EnumerationOptions.longestEffectiveRangeNotRequired) {
(attribute: Any!, range: NSRange, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
if let attributeFont = attribute as? UIFont {
let newPointSize = 12 * pointSize
let scaledFont = UIFont(descriptor: attributeFont.fontDescriptor, size: newPointSize)
mutableAttributeText.addAttribute(NSFontAttributeName, value: scaledFont, range: range)
}
}
attributedText = mutableAttributeText
}
}
But then the text is not positioned exactly the same as before. Now what's the best way to let the user zoom in and out and have the text still sharp? I'm using auto layout to position the label inside UIScrollView.
#swalkner since you have to display a html, why not use a WKWebview instead of UIScrollView.
let htmlString = "some_html"
let webView:WKWebView = WKWebView.init(frame: frame)
webView.backgroundColor = UIColor.white
self.view.addSubview(webView)
// load html
webView.loadHTMLString(htmlString, baseURL: nil)
And if the load html takes a little bit of time, you can simply try to preload the webview, by creating it and load the html before push or present the controller.