Is there any possibilities to perform segue from Right To Left Without push or Persenting ViewController. The Following Code Working Fine with animation but if I use this class my TabBar is hidden. If I remove the code inside the Perform() TabBar is show but the animation is stop
Using MDCBottomNavigationBar
class SegueFromRight: UIStoryboardSegue {
override func perform() {
let src = self.source
let dst = self.destination
src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
dst.view.transform = CGAffineTransform(translationX: src.view.frame.size.width, y: 0)
UIView.animate(withDuration: 0.25,delay: 0.0,options: UIView.AnimationOptions.curveEaseInOut,animations: {
dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
},completion: { finished in
src.navigationController?.pushViewController(dst, animated: false)
}
)
}
}
is there any other way to perform segue with animation without hiding TabBar ?
Finally I found the answer. Just Removing the line Push ViewController
class SegueFromRight: UIStoryboardSegue {
override func perform() {
let src = self.source
let dst = self.destination
src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
dst.view.transform = CGAffineTransform(translationX: src.view.frame.size.width, y: 0)
UIView.animate(withDuration: 0.25,delay: 0.0,options: UIView.AnimationOptions.curveEaseInOut,animations: {
dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
},completion: { finished in
//Remove Following line if you want to segue modally
//src.navigationController?.pushViewController(dst, animated: false)
}
)
}
}
Try this
private func setupAlwaysVisibleView() {
guard let tabBarController = self.tabBarController else { return }
tabBarController.view.insertSubview(alwaysVisibleView, belowSubview: tabBarController.tabBar)
}
Related
i am working on application where i am trying to call controllers with animations
second view controller with animations
like when i call second controller with segue
second controller come from right and first controller start moving to left
like android push pop animations
i make some code
class SegueFromRight: UIStoryboardSegue {
override func perform() {
let src = self.source
let dst = self.destination
src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
dst.view.transform = CGAffineTransform(translationX: src.view.frame.size.width*2, y: 0)
//Double the X-Axis
UIView.animate(withDuration: 0.25, delay: 0.0, options: UIView.AnimationOptions.curveEaseInOut, animations: {
dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
}) { (finished) in
src.present(dst, animated: false, completion: nil)
}
}
}
but from this code new controller come from right i need to move current controller to move left too
if anyone can help
Try this code:
class CustomSegue: UIStoryboardSegue {
override func perform() {
let firstVCView: UIView = self.source.view
let secondVCView: UIView = self.destination.view
self.destination.modalPresentationStyle = .fullScreen
let screenWidth = UIScreen.main.bounds.size.width
let screenHeight = UIScreen.main.bounds.size.height
secondVCView.frame = CGRect(x: screenWidth, y: 0, width: screenWidth, height: screenHeight)
let window = UIApplication.shared.keyWindow
window?.insertSubview(secondVCView, aboveSubview: firstVCView)
UIView.animate(withDuration: 0.4, animations: { () -> Void in
firstVCView.frame = firstVCView.frame.offsetBy(dx: -screenWidth, dy: 0.0)
secondVCView.frame = secondVCView.frame.offsetBy(dx: -screenWidth, dy: 0.0)
}) { (Finished) -> Void in
self.source.present(self.destination as UIViewController,
animated: false,
completion: nil)
}
}
}
class CustomSegueUnwind: UIStoryboardSegue {
override func perform() {
let secondVCView: UIView = self.source.view
let firstVCView: UIView = self.destination.view
self.destination.modalPresentationStyle = .fullScreen
let screenWidth = UIScreen.main.bounds.size.width
let window = UIApplication.shared.keyWindow
window?.insertSubview(firstVCView, aboveSubview: secondVCView)
UIView.animate(withDuration: 0.4, animations: { () -> Void in
firstVCView.frame = firstVCView.frame.offsetBy(dx: screenWidth, dy: 0.0)
secondVCView.frame = secondVCView.frame.offsetBy(dx: screenWidth, dy: 0.0)
}) { (Finished) -> Void in
self.source.dismiss(animated: false, completion: nil)
}
}
}
Reference HERE for more details
I have a viewcontroller that is embedded in a navigation controller. I wanted a Swipe right to go right left and change viewcontroller from VC1 to VC2, which thanks to people on stackoverflow i managed to do. However now i want to go the traditional way left right (traditional way for push), when swiping left on VC2 that goes back to VC1.
This is my code in VC1 (to swipe right to go to VC2):
override func viewDidLoad() {
super.viewDidLoad()
//Swipe right gesture
let gesture = UISwipeGestureRecognizer(target: self, action: #selector(SelectedTopicViewController.performChange))
gesture.direction = .right
self.view.addGestureRecognizer(gesture)
}
#objc func performChange() {
self.performSegue(withIdentifier: "goTo", sender: nil)
}
This is my code in VC2 (for swiping left to go back to VC1):
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.setNavigationBarHidden(true, animated: false)
//swipe left gesture
let gesture = UISwipeGestureRecognizer(target: self, action: #selector(SendMessageTopicViewController.performChange))
gesture.direction = .left
self.view.addGestureRecognizer(gesture)
// Do any additional setup after loading the view.
}
#objc func performChange() {
//self.navigationController?.popViewController(animated: true)
//print("swipe detected")
self.performSegue(withIdentifier: "goBackToRight", sender: nil)
}
Also this is my custom segue code (for both left and right swipe):
import Foundation
import UIKit
import QuartzCore
class SegueFromLeft: UIStoryboardSegue {
override func perform() {
let src: UIViewController = self.source
let dst: UIViewController = self.destination
let transition: CATransition = CATransition()
let timeFunc : CAMediaTimingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.duration = 0.25
transition.timingFunction = timeFunc
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromLeft
src.navigationController!.view.layer.add(transition, forKey: kCATransition)
src.navigationController!.pushViewController(dst, animated: false)
}
}
class SegueFromRight: UIStoryboardSegue {
override func perform() {
let src = self.source
let dst = self.destination
src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
dst.view.transform = CGAffineTransform(translationX: src.view.frame.size.width*2, y: 0) //Double the X-Axis
UIView.animate(withDuration: 0.25, delay: 0.0, options: UIViewAnimationOptions.curveEaseInOut, animations: {
dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
}) { (finished) in
src.present(dst, animated: false, completion: nil)
}
}
}
And this is my storyboard, note that i have one segue going to VC2, and one going back to VC1 (both custom segue using the different classes).
Even if i have a print("swiped") when user swipes on VC2 it dosent get printed in console, hence why i think its something wrong with the swipes...
Conclusion: Swipe does work on VC1 and segue to VC2 works, however swipe on VC2 does not work at all...
After launch screen dismisses itself logo and title of my app (they are in container) should go closer to the top of the screen. Between dismissing launch screen and viewDidAppear method there is a strange 'blink' of my container in the background. As you can see I am using snapkit but it should have nothing to do with the problem. Here is my code:
class WelcomeScreenViewController: UIViewController {
var welcomeScreenView: WelcomeScreenView {
return view as! WelcomeScreenView
}
override func loadView() {
let contentView = WelcomeScreenView(frame: .zero)
view = contentView
}
override func viewDidLoad() {
super.viewDidLoad()
self.welcomeScreenView.checkWeatherButton.transform = CGAffineTransform(translationX: 0, y: 200)
self.welcomeScreenView.checkWeatherButton.addTarget(self, action: #selector(showCityChoiceVC), for: .touchUpInside)
navigationController?.isNavigationBarHidden = true
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.welcomeScreenView.appNameLogoContainerVerticalConstraint?.isActive = false
self.welcomeScreenView.appNameLogoContainer.snp.makeConstraints({ (make) in
make.top.equalTo(self.welcomeScreenView).offset(100)
})
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.5, options: [], animations: {
self.welcomeScreenView.layoutIfNeeded()
self.welcomeScreenView.checkWeatherButton.transform = CGAffineTransform(translationX: 0, y: 0)
}, completion: nil)
}
#objc private func showCityChoiceVC() {
self.navigationController?.pushViewController(RegisterViewController(), animated: true)
}
Blinking comes from setting constraints in viewDidAppear. Use viewWillAppear or viewDidLoad instead. viewDidAppear is invoked when your view actually appears on screen. So any changes that happen will be visible to the user.
I am using a custom segue to slide my views over. The custom subclass works fine whenever it moves from a view controller to a view controller, but it crashes when I try to move from a view controller to a navigation controller. (It carries over the previous navigation bar and when I try to click the screen it crashes.)
This is the custom segue
class FromRightSegue: UIStoryboardSegue {
override func perform() {
let src = self.source
let dst = self.destination
src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
dst.view.transform = CGAffineTransform(translationX: src.view.frame.size.width, y: 0)
UIView.animate(withDuration: 0.25,
delay: 0.0,
options: .curveEaseInOut,
animations: {
dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
},
completion: { finished in
src.present(dst, animated: false, completion: nil)
}
)
}
}
When I use the built in segues like show the segue works fine, but there is no built in segue that moves from the right. Any suggestions?
I'm using Custom Segue class to navigate between controllers.
class CustomSegue: UIStoryboardSegue {
override func perform() {
let firstVCView = self.source.view as UIView!
let secondVCView = self.destination.view as UIView!
let screenWidth = UIScreen.main.bounds.size.width
let screenHeight = UIScreen.main.bounds.size.height
secondVCView?.frame = CGRect(x: 0.0, y: screenHeight, width: screenWidth, height: screenHeight)
let window = UIApplication.shared.keyWindow
window?.insertSubview(secondVCView!, aboveSubview: firstVCView!)
UIView.animate(withDuration: 0.4, animations: { () -> Void in
firstVCView?.frame = (firstVCView?.frame.offsetBy(dx: 0.0, dy: -screenHeight))!
secondVCView?.frame = (secondVCView?.frame.offsetBy(dx: 0.0, dy: -screenHeight))!
}) { (Finished) -> Void in
self.source.present(self.destination as UIViewController,
animated: false,
completion: nil)
}
}
}
my question is how to dismiss with the opposite animation,
in dismiss method, I don't have the source/destination view to take the width and height.Thanks!
You probably found out already, but for other people landing on this topic, the solution is given in this post, namely doing the animation in the ViewController and then dismiss without animation.
Swift 4 code:
#IBAction func BackAction(_ sender: Any) {
let transition: CATransition = CATransition()
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
transition.type = CATransitionType.reveal
transition.subtype = CATransitionSubtype.fromLeft
self.view.window!.layer.add(transition, forKey: nil)
self.dismiss(animated: false, completion: nil)
}