skip to Main Content

I am trying to change font size of button itself after it was pressed.

class ViewController: UIViewController {
   @IBOutlet weak var buttonToResize: UIButton!

   @IBAction func buttonTapped(_ sender: UIButton) {
        buttonToResize.titleLabel!.font = UIFont(name: "Helvetica", size: 40)
// Also tried buttonToResize.titleLabel?.font = UIFont .systemFont(ofSize: 4)
}

However the changes are not applied.

What is interesting, to me, that if I try to resize some other button (second one) after pressing on initial (first one), it works as expected.

Like this:

class ViewController: UIViewController {
@IBOutlet weak var buttonToResize: UIButton!
@IBOutlet weak var secondButtonToResize: UIButton!

@IBAction func buttonTapped(_ sender: UIButton) {
    secondButtonToResize.titleLabel!.font = UIFont(name: "Helvetica", size: 40)
}

Other properties like backgroundColor seems to apply, however with font size I face problem.

4

Answers


  1. You probably want something like this

    struct MyView: View {
      @State var pressed: Bool = false
    
      var body: some View {
        Button(action: {
          withAnimation { 
            pressed = true 
          }
        }) {
          Text("Hello")
        }
        Button(action: {
        }) {
          Text("Hello")
             .font(pressed ? .system(size: 40) : .system(size: 20))
        }
      }
    }
    
    Login or Signup to reply.
  2. First, here’s the sequence of events when you tap on a UIButton.

    1. The button sets its own isHighlighted property to true.
    2. The button fires any Touch Down actions, possibly multiple times if you drag your finger around.
    3. The button fires any Primary Action Triggered actions (like your buttonTapped).
    4. The button fires any Touch Up actions.
    5. The button sets its own isHighlighted property to false.

    Every time isHighlighted changes, the button updates its styling to how it thinks it should look. So a moment after buttonTapped, the button you pressed overwrites your chosen font with its own font.

    It’s worth exploring this to make sure you understand it by creating a UIButton subclass. Don’t use this in production. Once you start overriding parts of UIButton, you need to override all of it.

    // This class is to demonstrate the sequence of events when you press a UIButton.
    // Do not use in production.
    // To make this work properly, you would also have to override all the other properties that effect UIButton.state, and also UIButton.state itself.
    class MyOverrideHighlightedButton : UIButton {
        // Define a local property to store our highlighted state.
        var myHighlighted : Bool = false
        
        override var isHighlighted: Bool {
            get {
                // Just return the existing property.
                return myHighlighted
            }
            
            set {
                print("Setting MyOverrideHighlightedButton.isHighlighted from (myHighlighted) to (newValue)")
                
                myHighlighted = newValue
                
                // Since the UIButton remains unaware of its highlighted state changing, we need to change its appearance here.
                // Use garish colors so we can be sure it works during testing.
                if (myHighlighted) {
                    titleLabel!.textColor = UIColor.red
                } else {
                    titleLabel!.textColor = titleColor(for: .normal)
                }
            }
        }
    }
    

    So where does it keep pulling its old font from? On loading a view it will apply UIAppearance settings, but those will get discarded when you press the button too. iOS 15+, it looks like it uses the new UIButton.Configuration struct. So you could put this in your buttonTapped:

    // The Configuration struct used here was only defined in iOS 15 and
    // will fail in earlier versions.
    // See https://developer.apple.com/documentation/uikit/uibutton/configuration
    sender.configuration!.titleTextAttributesTransformer = UIConfigurationTextAttributesTransformer { incoming in
        var outgoing = incoming
        // We only want to change the font, but we could change other properties here too.
        outgoing.font = UIFont(name: "Zapfino", size: 20)
        return outgoing
    }
    

    I’d like to think there’s a simpler way to do this. Whichever way you work, make sure it will also work in the event of other changes to your button, such as some other event setting isEnabled to false on it.

    Login or Signup to reply.
  3. class ViewController: UIViewController {
         @IBOutlet weak var buttonToResize: UIButton!
      
        @IBAction func buttonTapped(_ sender: UIButton) {
        sender.titleLabel?.font = .systemFont(ofSize: 30)
        }
      }
    

    This should solve the problem. Use the sender tag instead of the IBOutlet.

    Login or Signup to reply.
  4. Cowirrie analysis made me think of this solution (tested)

    @IBAction func testX(_ sender: UIButton) {
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1)  { 
            sender.titleLabel?.font = sender.titleLabel?.font.withSize(32) 
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search