When I try to animate UiTextField width constraints, it makes content looking like on the final animation frame (just shrinks it). How to avoid that and make animation forwards same as you see it works backwards? (animation slowed down in emulator here)
textFieldWidthConstraint.constant = 0.0
UIView.animate(withDuration: 0.3) {
self.layoutIfNeeded()
}
Related
I am trying to hide/show my subview of a UIStackView within an animation block like so:
UIView.animate(withDuration: 0.3) {
self.unpairSensorButton.isHidden = isHidden
}
Showing animation works perfectly, but when I try to hide it, it just waits for the animation duration and then just immediately disappears. Any idea why?
I have tried to use the layoutIfNeeded() and putting it into DispatchQueue.main.async block bot neither helped.
isHidden property is not animatable by itself.
UIStackView basically changes its internal constraints to adapt its size when you hide some subview. Since constraints are animatable, you would do this:
unpairSensorButton.isHidden = isHidden
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
Calling layoutIfNeeded() in an animation block will animate the layout process.
In my application I want to animate a view from bottom to up in override func viewDidLayoutSubviews(). So far I have done this way to transit the view from bottom but in different device it is showing different UI. UIView transition is working but view is not fully transitioning from bottom expect iPhone XS. So far I have done these two ways :
First Step:
let currentFrame = self.animationVIew.frame
self.animationVIew.frame = CGRect(x: 0, y: self.view.frame.height, width: currentFrame.size.width, height: currentFrame.size.height)
UIView.animate(withDuration: 1.0) {
self.animationVIew.frame = currentFrame
self.loadViewIfNeeded()
}
Second Step:
UIView.transition(with: animationVIew,
duration: 0.5,
options: [.transitionFlipFromBottom],
animations: {
},
completion: nil)
But for both way I am facing same problem. No luck!!
It was my mistake I did not think in proper way to solve it.Anyway if anyone face similar kind of problem then may be this answer will help them. I have just changed the current autolayout to fix this issue.This problem was happening because of constraint between animationView and topView. The distance constraint between these two view was fixed, That is why when animation was happening it was resizing the animationView to adjust the constraints.So my solution was making the animation view height constraint fixed and have changed the priority required to low of distance constraint between animationView and topView in storyboard
Swift View Animation from Line
Swift 4.2, Xcode 10.0
I want to perform an animation with a view wherein it builds out or into a line.
Build out of line:
Build into line:
My only solution at this point is to put another view on the opposite side of the line to cover the view before it starts to animate. But this is a bad solution and it can sometimes block other views. Also, I would like to avoid stretching my content because I want to be able to perform this animation with images. What would be the best way to integrate this. Thank you in advance for the help!
So you want this:
A subview can extend outside the bounds of its superview. When this happens, the part of the subview that is outside the superview is visible if the superview's clipsToBounds property is false, and hidden if the superview's clipsToBounds is true.
I used this clipping to hide the part of the green view that is below the line. Perhaps these side views at the halfway point of the animation will help explain how I set it up:
The superview (labelled “hider”) has been shrunk here to half the height of the green view. With clipping enabled, half of the green view is hidden. With clipping disabled, the bottom of the green view is visible below the line.
Here is how I set up the demo:
I put the green view in a new superview. I call this new superview the “hider”.
I turned on the “Clips to Bounds” check box in the hider's Attributes inspector.
I set width and height constraints on the green view. You could use other constraints (like leading/trailing) to control its size.
I constrained the leading, trailing, and top edges of the green view to equal the corresponding edges of the hider.
I constrained the height of the hider to equal the height of the green view plus 12. The 12 will make the white margin between the green view and the line. I set this constraint's priority to 999. This means auto layout will try very hard to satisfy the constraint, but will break this constraint if necessary in order to satisfy all required constraints.
I created a constraint setting the hider's height to zero. I connected this constraint to an outlet named hiderHeightConstraint in my view controller. Note that this means there are two constraints on the hider's height. This one forces the hider's height to zero and is required. The other (created in the prior step) sets the hider's height to the green view's height plus padding, but is not required. When you are editing the layout in the storyboard, you probably want to turn off this constraint by turning off its “Installed” check box in the constraint's Attributes inspector.
I connected the “Toggle Secret Message” button to this action:
#IBAction private func toggleButtonWasTapped() {
UIView.animate(withDuration: 0.7) {
self.hiderHeightConstraint.isActive.toggle()
self.view.layoutIfNeeded()
}
}
Here's how it works. When the hiderHeightConstraint is active, the hider is forced to zero height. Since it clips its subviews, the green view is not visible. Since the constraint between the hider's height and the green view's height is not required, the green view can still be its natural size. The other constraints (leading/trailing/top) force the green view to stick out beyond the bottom edge of the hider.
When the hiderHeightConstraint is not active, the hider grows to the height of the green view plus the padding, allowing the green view to be fully visible.
Here is what my storyboard looks like:
This is one approach you can follow to achieve this:
Take 2 Container UIView and 2 line view (you may take UIView again) and 2 UIImageView (or any for green view). So your StoryBoard should look like this :
Make sure your container views are clips to bound (you can set it from storyboard only).
Now you can achieve the animation easily by CGAffineTransform.
I will call outlet names for animated view as imageViewOne and imageViewTwo.
In viewDidLoad() write this (if initially views are hidden):
imageViewOne.transform = CGAffineTransform(translationX: 0.0, y: containerViewOne.bounds.height)
imageViewTwo.transform = CGAffineTransform(translationX: 0.0, y: -containerViewOne.bounds.height)
Then to show it with animation:
//To build out of line
UIView.animate(withDuration: 1.0, delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
self.imageViewOne.transform = .identity
self.imageViewTwo.transform = .identity
}, completion: nil)
//To build into line
UIView.animate(withDuration: 1.0, delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
self.imageViewOne.transform = CGAffineTransform(translationX: 0.0, y: containerViewOne.bounds.height)
self.imageViewTwo.transform = CGAffineTransform(translationX: 0.0, y: -containerViewOne.bounds.height)
}, completion: nil)
Use a view but then put in that view the line to make it look authentic.
Then when you are done make the whole animation disappear or if you want to make other animations go over it , you can call functions to move views above others
https://stackoverflow.com/a/38780829/4674760
I have a collectionView which I need to animate height changes for, so it expands up from the foot of the screen, & back down again. It's hard to explain what's going wrong so I've attached a recording of the simulator. The animation is fine for expanding, but very odd for the collapse - the content partially disappears as it animates, then reappears when it's done. The animation code is triggered during the scrollView 'scrollViewDidScroll(_ scrollView: UIScrollView)' delegate method, with logic to determine whether to collapse or expand. The expand animation, whose code is pretty much identical, works fine.
Animation code -
private func collapseTable() {
guard self.isTableChangingSize == false else { return } // as the delegate method is triggered during the animation, we use a flag to prevent multiple collapse calls
guard self.tableHeightConstraint.constant != self.tableCollapsedHeight else { return } // don't collapse if we're already collapsed
self.isTableChangingSize = true
self.tableHeightConstraint.constant = self.tableCollapsedHeight
UIView.animate(withDuration: 0.5, animations: {
self.view.layoutIfNeeded()
}) { _ in
self.isTableChangingSize = false
}
}
Here are a couple of videos of what's happening -
Normal speed
Slow motion
After far too long messing about trying different approaches, & tweaking everything, it seems that the problem was allowing scrolling during the animation block. If you set -
self.collectionView.isScrollEnabled = false
before the animation block, and -
self.collectionView.isScrollEnabled = true
in the completion, all is good.
Is there any way to obtain a flash screen effect like the one produced when a screenshot is taken, on demand, for a certain NSView? My question is not a duplicate of flashing screen programatically with Swift (on 'screenshot taken') , since I need a solution for osx, not ios and the methods are different.
Something like this might work
func showScreenshotEffect() {
let snapshotView = UIView()
snapshotView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(snapshotView)
// Activate full screen constraints
let constraints:[NSLayoutConstraint] = [
snapshotView.topAnchor.constraint(equalTo: view.topAnchor),
snapshotView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
snapshotView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
snapshotView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
]
NSLayoutConstraint.activate(constraints)
// White because it's the brightest color
snapshotView.backgroundColor = UIColor.white
// Animate the alpha to 0 to simulate flash
UIView.animate(withDuration: 0.2, animations: {
snapshotView.alpha = 0
}) { _ in
// Once animation completed, remove it from view.
snapshotView.removeFromSuperview()
}
}
The way to achieve this is to create a new UIView that is the same size of the screen, and black in color, add it a subview of your view then animate the alpha to zero( play around with the duration to achieve the desired effect) after completion remove the view from superview.
I have used this technique in many of my projects and it works like a charm. You can play around with the background color of the view to customize the look of the flash.