Swift CATransition Between Two Views - Slide over effect previous screen turns white - ios

I am trying to animate between two full screen views (same view controller) in swift using CATransition. Looking to replicate (or get close to) navigation view controller push transition. Running into issue where view2 (the new view to present) is sliding over correctly, but view1 (the view underneath) disappears. Basically the view that is being animated is sliding over a white screen, but I want it to slider over the previous screen.
var pushAnimationEffect = CATransition()
override func viewDidLoad() {
super.viewDidLoad()
pageToUIView[i] = UIView()
view1.frame = CGRect(x: 0, y: 0, width: screenSize.width, height: screenSize.height)
view1.center = CGPointMake(screenSize.width/2, screenSize.height/2)
view2.frame = CGRect(x: 0, y: 0, width: screenSize.width, height: screenSize.height)
view2.center = CGPointMake(screenSize.width/2, screenSize.height/2)
view1.layer.addAnimation(pushAnimationEffect, forKey: nil)
view2.layer.addAnimation(pushAnimationEffect, forKey: nil)
self.view.addSubview(view1)
pushAnimationEffect.delegate = self
pushAnimationEffect.duration = 0.4
pushAnimationEffect.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
}
func nextPage() {
pushAnimationEffect.type = kCATransitionMoveIn
pushAnimationEffect.subtype = kCATransitionFromRight
self.view.addSubview(view2)
view1.removeFromSuperview()
}
func prevPage() {
pushAnimationEffect.type = kCATransitionMoveIn
pushAnimationEffect.subtype = kCATransitionFromLeft
self.view.addSubview(view1)
view2.removeFromSuperview()
}
Simplified the code a bit so its easier to read.
Is there a better way to do this? Is there something wrong with the code?

You need to do the view remove on after the animation completes. Use the animationDidStop:finished: delegate method.

Related

UI freezes for a second when returning to the previous ViewController in Navigation Stack

I'm having some trouble figuring out what's causing the UI to freeze for a second when I press the back button. It started happening after I added a background image to the viewController that I'm transitioning from. If I'm just using "white" as my backgroundColor, the transition doesn't freeze, it only freezes once I add the image.
Here is a gif of what it looks like...
https://gfycat.com/waryagileichidna
Here is the extension that I'm calling in my viewDidLoad to set the background image...
extension UIView {
func addBackground(image:String) {
self.backgroundColor = .white
// screen width and height:
let width = UIScreen.main.bounds.size.width
let height = UIScreen.main.bounds.size.height
let imageViewBackground = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: height))
imageViewBackground.image = UIImage(named: "\(image)")
imageViewBackground.alpha = 0.5
// you can change the content mode:
imageViewBackground.contentMode = UIView.ContentMode.scaleAspectFill
self.addSubview(imageViewBackground)
self.sendSubviewToBack(imageViewBackground)
}
}
Could you try adding the below line to your addBackground method which you call in viewDidLoad.
imageViewBackground.clipsToBounds = true
I have a feeling this should solve it. That doesn't look like a freeze.

Custom animation for loading data

Here I have been trying so long to create a custom animated progress bar.
I'm trying to move a view from screen's one end to second end with resizing.
view's frmae is (0, 100, 10, 4)
What I want is...
At start of animation view should be at its initial position, lets say at (0, 100)
in the middle of the animation view will be at the middle of the screen and its width will be increased to 100px.
at the end of the animation view will be at screen's second end. and frame of the view will be at, lets say (400, 100) and width off the view will be again back to 10px
The whole progress should be reversed also.
UIButton Action method
var mainView = UIView()
#IBAction func btnTapped(_ sender: UIButton) {
let rect = CGRect(x: 0, y: 300, width: 10, height: 4)
mainView = UIView(frame: rect)
mainView.backgroundColor = UIColor.black
self.view.addSubview(mainView)
animate()
}
Animation Method
func animate() {
let theAnimationTranslationX = CABasicAnimation(keyPath: "transform.translation.x")
theAnimationTranslationX.fromValue = mainView.bounds.minX
theAnimationTranslationX.toValue = 400
let scaleAnimate:CABasicAnimation = CABasicAnimation(keyPath: "transform.scale.x")
scaleAnimate.fromValue = NSValue(caTransform3D: CATransform3DMakeScale(1, 1, 1))
scaleAnimate.toValue = NSValue(caTransform3D: CATransform3DMakeScale(1.2, 0, 0))
let group = CAAnimationGroup()
group.autoreverses = true
group.repeatCount = .greatestFiniteMagnitude
group.animations = [theAnimationTranslationX]//, scaleAnimate]
group.duration = 2
group.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
mainView.layer.add(group, forKey: "animation")
}
I'm not getting the desired animation effect.
Is there any other way to do so or is it possible with any other way please suggest me.
Thanks for you time and any help will be appreciated.
EDIT:
The final animation should look like...

iOS - Display a progress indicator at the center of the screen rather than the view

I want to display a progress indicator at the center of the screen, NOT the view. It should be the center of the view because the view is scrollable. Most answers only tells how to center it in the view. I have this code:
let screenBound = UIScreen.main.bounds
let progressIndc = UIActivityIndicatorView()
progressIndc.frame = CGRect(x: screenBound.width / 2 - 10,
y: screenBound.height / 2 - 10,
width: 20, height: 20)
progressIndc.hidesWhenStopped = true
progressIndc.color = UIColor.gray
progressIndc.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
// self.view is scroll view
self.view.addSubview(progressIndc)
progressIndc.startAnimating()
But it shown near the top in iPhone 7. What should be the right way? I can also do a blocking pop-up dialog with a progress indicator.
if you want to keep the indicator view at the center of screen while scrolling, you can add a overlay view to the current topmost UIWindow, then add your indicator view to the overlay view:
guard let topWindow = UIApplication.shared.windows.last else {return}
let overlayView = UIView(frame: topWindow.bounds)
overlayView.backgroundColor = UIColor.clear
topWindow.addSubview(overlayView)
let hudView = UIActivityIndicatorView()
hudView.bounds = CGRect(x: 0, y: 0, width: 20, height: 20)
overlayView.addSubview(hudView)
hudView.center = overlayView.center
you should do this after the topmost UIViewController's view was attached on the top UIWindow, for example, in viewDidAppearmethod.
you can use center property of UIView
progressIndc.center = self.view.center
for e.g
let screenBound = UIScreen.main.bounds
let progressIndc = UIActivityIndicatorView()
progressIndc.frame = CGRect(x: screenBound.width / 2 - 10,
y: screenBound.height / 2 - 10,
width: 20, height: 20)
progressIndc.hidesWhenStopped = true
progressIndc.color = UIColor.gray
progressIndc.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
// self.view is scroll view
progressIndc.center = self.view.center
self.view.addSubview(progressIndc)
progressIndc.startAnimating()
output
you can try this one to add you indicator on top of the screen. but it's not pretty solution -
AppDelegate.sharedInstance.window?.addSubview(progressIndc);

iOS stop status bar from disappearing during animation

I am segueing from a ViewController with a status bar to one without.
During the animation I'm seeing the status bar quickly slide up on the old ViewController as the new ViewController is sliding on top.
Any suggestions why this is happening and how to fix this?
The new ViewController has no status bar due to:
override var prefersStatusBarHidden: Bool {
return true
}
Presentation style is
modalPresentationStyle="overCurrentContext"
NEW:
Created a test XCode project with the issue:
https://github.com/paul301/TestSlideUp
To make the new ViewController stay on top of the old status bar, you need to create a new UIWindow and do the animation manually.
Sample code:
var window = UIWindow()
//to show new view controller
func showWindow() {
let vc = NewViewController()
self.window.rootViewController = vc
self.window.backgroundColor = UIColor.clear
self.window.windowLevel = UIWindowLevelStatusBar
self.window.frame = CGRect(x: 0, y: UIScreen.main.bounds.height, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
self.window.isHidden = false
UIView.animate(withDuration: 0.5) {
self.window.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
}
}

Adding a small UIView to an SKScene

I have a Swift + SpriteKit game in development, in which I would like to insert a small UITableViewController into a small (100 x 200) UIView, and then add that view to my SKScene. I am using this code:
class BugsScene: SKScene {
override func didMoveToView(view: SKView) {
anchorPoint = CGPoint(x: 0.5, y: 0.5)
NSUserDefaults.standardUserDefaults().setObject("bugs", forKey: "lastSceneViewed")
let bugsTableView: BugsTVC = BugsTVC()
let nav = UINavigationController(rootViewController: bugsTableView)
let smallerRect = CGRectMake(0, 0, 100, 200)
let smallerView = UIView(frame: smallerRect)
smallerView.addSubview(nav.view)
self.view.addSubview(smallerView)
}
}
However, in landscape mode (my app only supports landscape left and landscape right, NO portrait), the tableview occupies the entire height of the landscape mode, and has the width of an iPad in portrait.
How do I add a small UIView to a bigger scene in swift/spritekit?
LearnCocos2D definitely deserves credit for this, so if he ever posts an answer I will accept it. Essentially, I was failing to set the frame for the navigation controller's view. Here is my method for adding the smaller view to the scene:
override func didMoveToView(view: SKView) {
anchorPoint = CGPoint(x: 0.5, y: 0.5)
self.name = "Bugs Scene"
backgroundColor = bugsColor
let smallerRect = CGRectMake(400, 24, 600, 720)
let navRect = CGRectMake(0, 0, 600, 720)
let bugsTableView: BugsTVC = BugsTVC()
nav = UINavigationController(rootViewController: bugsTableView)
nav.view.frame = navRect
smallerView = UIView(frame: smallerRect)
smallerView.backgroundColor = UIColor.clearColor()
bugsTableView.view.frame = smallerRect
smallerView.frame = smallerRect
smallerView.addSubview(nav.view)
self.view.addSubview(smallerView)
}
It could probably be refined some but this is working for me. Now if I can only figure out how to remove the view when I transition to another scene!

Resources