Reputation: 25
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.
Upvotes: 1
Views: 2038
Reputation: 884
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)
}
}
Upvotes: 0
Reputation: 1
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.
Upvotes: 0
Reputation: 7226
First, here's the sequence of events when you tap on a UIButton
.
isHighlighted
property to true
.Touch Down
actions, possibly multiple times if you drag your finger around.Primary Action Triggered
actions (like your buttonTapped
).Touch Up
actions.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.
Upvotes: 4
Reputation: 1973
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))
}
}
}
Upvotes: 0