iOS animating UILabel expand
You can animate number of lines. It changes the intrinsicSize of the UILabel
. You need to call layoutIfNeeded inside your animation block on the view containing the UILabel. Here I attach a tap gesture to the table to toggle it between having 0 (as many as you want) lines and 1 line.
func tapLabel(tapGesture: UITapGestureRecognizer)
{
if let label = tapGesture.view as? UILabel {
label.numberOfLines = label.numberOfLines == 0 ? 1 : 0
UIView.animateWithDuration(0.5) {
label.superview?.layoutIfNeeded()
}
}
}
Expanding Multiline UILabel
I had a similar problem trying to make a view grow/shrink. Here is my SO post.
Basically I had to animate the frame to grow and then bounds/center to shrink. A bit awkward I know but I got the effect I wanted.
UILabel change height, animation expands from center
Faced same problem!
Try to set label' contentMode to Top in code:
label.contentMode = UIViewContentModeTop;
Why are animations on bounds of an UILabel only working when increasing the size?
It's because UILabel
sets its layer's contentsGravity
to the direction text is being rendered, which happens to default to UIViewContentModeLeft
(or @"left"
). Thus, when the layer is told to animate, it first takes a glance at its contents gravity and bases subsequent animations on that. Because it sees @"left"
where there should be @"resize"
, it assumes that the scaling animation should begin from the left, but it also has to respect the constraints you've given it (the bounds changes), so your label appears to jump into its final size then settle where it should in the center of the screen.
If you want to leave contentMode
alone, use CATransform3D
's and scale the label's layer that way instead of a bounds change.
UILabel size change doesn't animate with auto layout
The problem is with the UILabel
content mode. You see a similar problem here. Because you are shortening the label where the text is drawn, the label does a drawing pass, but it uses the final frame of the animation block for the update. The easiest way create a smooth animation is to use a greaterThanOrEqualTo
leading constraint and set the textAlignment
to .natural
.
When I do that I get the result on top as apposed to setting textAlignment
.right
on bottom.
Source code for demo:
import UIKit
import PlaygroundSupport
final class ViewController: UIViewController {
var constraint: NSLayoutConstraint?
var otherConstraint: NSLayoutConstraint?
lazy private var sideView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(view)
view.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
self.constraint = view.leadingAnchor.constraint(equalTo: self.view.trailingAnchor)
self.constraint?.isActive = true
view.widthAnchor.constraint(equalToConstant: 100).isActive = true
view.heightAnchor.constraint(equalToConstant: 44).isActive = true
view.backgroundColor = .yellow
return view
}()
lazy private var secondSideView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(view)
view.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 44.0).isActive = true
self.otherConstraint = view.leadingAnchor.constraint(equalTo: self.view.trailingAnchor)
self.otherConstraint?.isActive = true
view.widthAnchor.constraint(equalToConstant: 100).isActive = true
view.heightAnchor.constraint(equalToConstant: 44).isActive = true
view.backgroundColor = .yellow
return view
}()
lazy private var label: UILabel = {
let label = UILabel()
label.text = "Label"
label.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(label)
label.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
label.leadingAnchor.constraint(greaterThanOrEqualTo: self.view.leadingAnchor, constant: 8.0).isActive = true
label.trailingAnchor.constraint(equalTo: self.sideView.leadingAnchor).isActive = true
return label
}()
lazy private var secondLabel: UILabel = {
let label = UILabel()
label.textAlignment = .right
label.text = "Label"
label.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(label)
label.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 44.0).isActive = true
label.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 8.0).isActive = true
label.trailingAnchor.constraint(equalTo: self.sideView.leadingAnchor).isActive = true
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
self.secondSideView.isHidden = false
self.secondLabel.isHidden = false
self.sideView.isHidden = false
self.label.isHidden = false
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.perform(#selector(self.showSideView), with: nil, afterDelay: 5.0)
}
@objc private func showSideView() {
self.view.layoutIfNeeded()
UIView.animate(withDuration: 1.5, delay: 0.0, options: [.autoreverse, .repeat], animations: {
self.otherConstraint?.constant = -100
self.constraint?.constant = -100
self.view.layoutIfNeeded()
})
}
}
PlaygroundPage.current.liveView = ViewController()
Related Topics
Can Swift Closures Be Set to a Default Value When Used as a Parameter in a Function
Xcode/Swift 'Filename Used Twice' Build Error
Flutter:Not Connecting to iOS Simulator in Android Studio
Uiscrollview Zooming with Auto Layout
Watchkit: Unable to Find Interface Controller Class
Detect Tap on Calloutbubble in Mkannotationview
Passing Data Between 2 Uiviewcontroller Using Delegate and Protocol
Swift - Pushviewcontroller from Appdelegate, Rootviewcontroller.Navigationcontroller Is Nil
Using Generic In-App Purchase Items for a Dynamic Range of Digital Products
How to Draw a Non-Rectangle Uitextview
Property Cannot Be Found in Forward Class Object
How to Represent Core Data Optional Scalars (Bool/Int/Double/Float) in Swift
Afnetworking - Do Not Cache Response
Xcode 6.3.2 Can't Run on Osx 10.11 El Capitan Developer Preview 3
How to Play Movie with a Url Using a Custom Nsurlprotocol
I am Getting Unsupported Parameter Combination Cgbitmap Error with Swift