How to fade out a titleView label on iOS 12 - ios

I'm trying to fade out a UILabel which has been added as a UIViewController's navigation item's titleView. On iOS 11 and below, the following code correctly fades out the label. When run on iOS 12, the fade in animation works, but the fade out does not animate - the view disappears immediately.
let fadeTextAnimation = CATransition()
fadeTextAnimation.type = .fade
fadeTextAnimation.duration = 0.5
navigationItem.titleView!.layer.add(fadeTextAnimation, forKey: nil)
(navigationItem.titleView as! UILabel).isHidden = didShowNavigationItemTitle
I've also tried changing the code to use UIView.transition, but the same behaviour is observed.
UIView.transition(with: navigationItem.titleView!,
duration: 0.5,
options: .transitionCrossDissolve,
animations: {
(self.navigationItem.titleView as! UILabel).isHidden = self.didShowNavigationItemTitle
}, completion: nil)
How can one achieve this fade out in iOS 12?

Just use a UIView.animate block and animate the alpha of the title view.
UIView.animate(withDuration: 0.5, delay: 0, options: .transitionCrossDissolve, animations: {
self.navigationItem.titleView?.alpha = 0
})

Related

Hiding UIView animation in swift

I am trying to hide/present UITextField with an animation. The animation works when presenting the text field but not when hiding, is there any particular reason for this?
UIView.transition(with: self.confirmPasswordTextField, duration: 0.5, options: [.transitionCrossDissolve], animations: {
self.confirmPasswordTextField.isHidden = self.login
self.layoutIfNeeded()
})
You better use alpha
self.confirmPasswordTextField.alpha = show ? 0.0 : 1.0
UIView.transition(with: self.confirmPasswordTextField, duration: 0.5, options: [.transitionCrossDissolve], animations: {
self.confirmPasswordTextField.alpha = show ? 1.0 : 0.0
})

UIView.transition shows parent view with dark background (Swift)

While flipping, the parent view fades into black (from white) to the middle of the animation, then fades into white again... Why?
My code:
if !cardFrontView.isHidden {
let transitionOptions: UIViewAnimationOptions = [.transitionFlipFromRight, .showHideTransitionViews]
UIView.transition(from: cardFrontView, to: cardBackView, duration: 1.0, options: transitionOptions, completion: nil)
}
else {
let transitionOptions: UIViewAnimationOptions = [.transitionFlipFromLeft, .showHideTransitionViews]
UIView.transition(from: cardBackView, to: cardFrontView, duration: 1.0, options: transitionOptions, completion: nil)
}
I also tried UIView.transition(with: but I have another problem there: round corners are disappearing.
Struggling all day with this... I mean that's all the code.
Try setting BaseView Color to UIColor.clear instaed of UIColor.white

How to move UITableViewCell back and forth to show it can be swiped?

I see in some apps when you come to a screen with a tableview there's a short animation of the cell starting to be swiped, showing the red "swipe to delete" button (UIContextualAction button) and then it returns to normal. It is giving the user the hint: "These rows can be swiped."
Is there a way to achieve this effect? Maybe a way to programmatically start a row swipe then cancel it?
Swift Solution
Well, about 1.5 years later I finally came up with a solution.
Step 1 - Cell UI Setup
I set up my custom table view cell like this:
A and B represent the swipe action colors.
C is the UIView that I will animate side-to-side.
Step 2 - Add Animation to Cell
func animateSwipeHint() {
slideInFromRight()
}
private func slideInFromRight() {
UIView.animate(withDuration: 0.5, delay: 0.3, options: [.curveEaseOut], animations: {
self.cellBackgroundView.transform = CGAffineTransform(translationX: -self.swipeHintDistance, y: 0)
self.cellBackgroundView.layer.cornerRadius = 10
}) { (success) in
UIView.animate(withDuration: 0.2, delay: 0, options: [.curveLinear], animations: {
self.cellBackgroundView.transform = .identity
}, completion: { (success) in
// Slide from left if you have leading swipe actions
self.slideInFromLeft()
})
}
}
private func slideInFromLeft() {
UIView.animate(withDuration: 0.5, delay: 0, options: [.curveEaseOut], animations: {
self.cellBackgroundView.transform = CGAffineTransform(translationX: self.swipeHintDistance, y: 0)
}) { (success) in
UIView.animate(withDuration: 0.2, delay: 0, options: [.curveLinear], animations: {
self.cellBackgroundView.transform = .identity
})
}
}
Step 3 - Trigger the Animation
In the viewDidLoad of the view controller that has the table view, I have this code:
if self.tableView.visibleCells.count > 0 {
let cell = self.tableView.visibleCells[0] as! TableViewCell
cell.animateSwipeHint()
}
Example:
Video Solution
I created a video if you'd like a more in-depth walkthrough of this solution:
https://youtu.be/oAGoFd_GrxE
I have a piece of code that I saw long time ago to animate a view. Since our UITableViewCell is also a view, we can use it :) You just need to get your visible cell to animate, like so:
if let visibleCell = self.tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as? CustomCell {
print("Started animation...")
let animation = CAKeyframeAnimation(keyPath: "transform.translation.x")
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
animation.duration = 0.6
animation.values = [-20.0, 20.0, -20.0, 20.0, -10.0, 10.0, -5.0, 5.0, 0.0 ]
visibleCell.layer.add(animation, forKey: "shake")
}
Let me know if this helps. Tested it.
EDIT:
Animating your UITableView to let the user see that they can swipe on a cell is pretty easy, try it like so:
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
self.tableView.setEditing(true, animated: true)
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
self.tableView.setEditing(false, animated: true)
}
}
HOWEVER, if you want to swipe programmatically your cell to show your custom row actions, (I've been researching this for an hour), you can only achieve this, as far as I know, by using method swizzling. See this SO answer: http://codejaxy.com/q/186524/ios-swift-uitableview-how-to-present-uitableviewrowactions-from-pressing-a-button

iOS/Swift: Use UIView.animate to animate text getting added/removed from UITextView

I am adding and removing attributed text from a UITextView. I wish to use UIView.animate to add an animation to when text is appended to the text view and when that appended text is removed from the text view. So far, I have this, but it does not cause any noticeable animation on the text view:
UIView.animate(withDuration: 1, delay: 0, options: .CurveLinear, animations: {
self.view.layoutIfNeeded()
self.textView.attributedText = newAttributedText
}, completion: { finished in
print("Animation completed")
}
// prints "Animation completed", but no animation occurs
You cannot animate changing of text in that manner. There is a list of animatable properties of CALayer class and UIView class.
Set text cannot be animated by UIView.animate. Only changes like transparency, colors, shape, location, etc can be animated by the UIView.animate.
Here is an example of animating origin and transparency change with code looks like
self.textView.text = "test Animation"
self.textView.alpha = 0
UIView.animate(withDuration: 3, delay: 0, options: .curveLinear, animations: {
var frame = self.textView.frame
frame.origin.x = frame.origin.x + 50
frame.origin.y = frame.origin.y + 50
self.textView.frame = frame
self.textView.alpha = 1
}, completion: { finished in
print("Animation completed")
})
And animation looks like
Here is my solution (swift 3 ) :
let animator = UIViewPropertyAnimator(duration: 0.2, curve: .easeOut, animations: {
self.textView2.frame = self.textView2.frame.offsetBy(dx: 20 , dy: 25)
} )
animator.startAnimation()

Custom Segue Class UIView Animation Issue

I am having trouble creating a custom segue using swift 3 and iOS 8. I am trying to transition between view controllers by fading from one VC to a black screen and then fading from black to my second VC. I tried to implement the segue by creating a custom segue using the code below, but it is not working as I would like it to. My goal is to perform an animation when the black square goes from 0.5 alpha to 1.0 alpha, then present my second view controller, then set the black square from 1.0 alpha back to 0.5 alpha and delete it. Right now, it does the first part correctly but after the animation finishes you can see the first VC for a brief instant before the second VC pops up. How should I change my code to make the transition smoother and get the desired result?
override func perform() {
let sourceVC = self.source
let destinationVC = self.destination
let square = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
square.alpha = 0.5
square.backgroundColor = UIColor.black
sourceVC.view.addSubview(square)
UIView.animate(withDuration: 0.2, animations: {
square.alpha = 1.0
})
UIView.animate(withDuration: 0.2, delay: 0.2, animations: {
square.alpha = 0.5
}) { (finished) in
sourceVC.present(destinationVC, animated: false, completion: nil)
}
}
Update your code like below and try:
UIView.animate(withDuration: 0.2, animations: {
square.alpha = 1.0
UIView.animate(withDuration: 0.2, delay: 0.2, animations: {
square.alpha = 0.5
}) { (finished) in
DispatchQueue.main.async {
sourceVC.present(destinationVC, animated: false, completion: nil)
}
})
}

Resources