Reputation: 19612
I have 2 UIButtons
and their titles
and colors
are initially set using NSMutableAttributedString
. The text is 2 lines of text
I have a custom UISegmentedControl
and when the segment is switched I need to change only the color of the buttons. The way I do it now the colors do change but there is ugly blink when that occurs because the actual text gets set again. I need a smooth transition for the colors only
var selectedSegmentIndex = 0 {
didSet {
layoutIfNeeded()
UIView.animate(withDuration: 0.1) {
self.setTextForFollowersButton()
self.setTextForFollowingButton()
self.layoutIfNeeded()
}
}
}
How can I change only the color of the button's NSMutableAttributedString
?
Button Code:
var numOfFollowers = 0 {
didSet {
setTextForFollowersButton()
}
}
var numOfFollowing = 0 {
didSet {
setTextForFollowingButton()
}
}
lazy var followersButton: UIButton = {
let button = UIButton.init(type: .system)
// ...
return button
}()
lazy var followingButton: UIButton = {
let button = UIButton.init(type: .system)
//...
return button
}()
func setTextForFollowersButton() {
let button = self.followersButton
let buttonText = "Following\n\(String(numOfFollowing))" as NSString
// other code for 2 lines of text
var color = UIColor.blue
if selectedSegmentIndex == 0 {
color = UIColor.blue
} else {
color = UIColor.gray
}
let attrString1 = NSMutableAttributedString(string: substring1,
attributes: [NSMutableAttributedString.Key.font:
UIFont.boldSystemFont(ofSize: 16),
NSMutableAttributedString.Key.foregroundColor: color])
let attrString2 = NSMutableAttributedString(string: substring2,
attributes: [NSMutableAttributedString.Key.font:
UIFont.boldSystemFont(ofSize: 14),
NSMutableAttributedString.Key.foregroundColor: color])
attrString1.append(attrString2)
button.setAttributedTitle(attrString1, for: [])
}
func setTextForFollowingButton() {
let button = self.followingButton
let buttonText = "Following\n\(String(numOfFollowing))" as NSString
// other code for 2 lines of text
var color = UIColor.blue
if selectedSegmentIndex == 0 {
color = UIColor.gray
} else {
color = UIColor.blue
}
let attrString1 = NSMutableAttributedString(string: substring1,
attributes: [NSMutableAttributedString.Key.font:
UIFont.boldSystemFont(ofSize: 16),
NSMutableAttributedString.Key.foregroundColor: color])
let attrString2 = NSMutableAttributedString(string: substring2,
attributes: [NSMutableAttributedString.Key.font:
UIFont.boldSystemFont(ofSize: 14),
NSMutableAttributedString.Key.foregroundColor: color])
attrString1.append(attrString2)
button.setAttributedTitle(attrString1, for: [])
}
Upvotes: 0
Views: 191
Reputation: 19612
Another way to do this for a smooth transition without any blink at all is to use UIView.performWithoutAnimation
:
DispatchQueue.main.async {
self.layoutIfNeeded()
UIView.performWithoutAnimation {
self.setTextForFollowersButton()
self.setTextForFollowingButton()
self.layoutIfNeeded()
}
}
Upvotes: 0
Reputation: 1239
You should insert UIView.animate
function inside of DispatchQueue.main.async {}
to make a smooth transition. Making any kind of animation of the UI asynchronously on the main thread is always recommended.
Upvotes: 1