Viewcontroller Slide Animation

ViewController slide animation

You can use the following idea: https://samwize.com/2016/04/27/making-tab-bar-slide-when-selected/

Also, here's the code updated to Swift 4.1 and I also removed the force unwrappings:

import UIKit

class MyTabBarController: UITabBarController {

override func viewDidLoad() {
super.viewDidLoad()

delegate = self
}
}

extension MyTabBarController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
guard let tabViewControllers = tabBarController.viewControllers, let toIndex = tabViewControllers.index(of: viewController) else {
return false
}
animateToTab(toIndex: toIndex)
return true
}

func animateToTab(toIndex: Int) {
guard let tabViewControllers = viewControllers,
let selectedVC = selectedViewController else { return }

guard let fromView = selectedVC.view,
let toView = tabViewControllers[toIndex].view,
let fromIndex = tabViewControllers.index(of: selectedVC),
fromIndex != toIndex else { return }


// Add the toView to the tab bar view
fromView.superview?.addSubview(toView)

// Position toView off screen (to the left/right of fromView)
let screenWidth = UIScreen.main.bounds.size.width
let scrollRight = toIndex > fromIndex
let offset = (scrollRight ? screenWidth : -screenWidth)
toView.center = CGPoint(x: fromView.center.x + offset, y: toView.center.y)

// Disable interaction during animation
view.isUserInteractionEnabled = false

UIView.animate(withDuration: 0.3,
delay: 0.0,
usingSpringWithDamping: 1,
initialSpringVelocity: 0,
options: .curveEaseOut,
animations: {
// Slide the views by -offset
fromView.center = CGPoint(x: fromView.center.x - offset, y: fromView.center.y)
toView.center = CGPoint(x: toView.center.x - offset, y: toView.center.y)

}, completion: { finished in
// Remove the old view from the tabbar view.
fromView.removeFromSuperview()
self.selectedIndex = toIndex
self.view.isUserInteractionEnabled = true
})
}
}

So, you need to subclass UITabBarController and you also have to write the animation part, you can tweak the animation options (delay, duration, etc).

I hope it helps, cheers!

Sample Image

How to create a slide animation inside a view controller?

Why do this programmatically with a fixed constant? Set the right of your uiview (trailing) equal to the leading (left) of your superciew (uiviewcontroller). Create an outlet of that constraint and animate it by adding a constant which is equal to the uiview’s width and maybe some offset.

Alternative you can make your subview equal to your superviews width - someoffset, equal height -someoffset, centerX and centerY to the superview and animate the centerX constraint.

Custom Slide in animation when presenting navigation controller not working at all in swift

Update your methods to swift3-:

func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return Transition()
}

func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return Transition()
}

View controller slide down animation IOS

You are presenting a view controller modally (slide up). The same view controller that does the presentation can also call dismiss(animated: true, completion: nil) to dismiss it. It will handle all animations for you.

You just need to make sure to wire up your 'back button' correctly. It sounds like at the moment it's hooked up to keep presenting new controllers.

Edit - In Objective C:

[self dismissViewControllerAnimated:YES completion:nil];

How to make UIViewController slide from bottom to top without fading previous view?

Your fade effect is the layer where you've put your animation. You are over-complicating yourself. Just instantiate the view controller and present it on top of your existing view controller.

let loginScreenVC = storyboard?.instantiateViewController(withIdentifier: "LoginScreen") as! LoginScreen
loginScreenVC.modalPresentationStyle = .overCurrentContext
self.present(loginScreenVC, animated: true)
//might be as well:
//navigationController?.present(loginScreenVC, animated: true)

UPDATE:

If you want to close it, just call:

self.dismiss(animated: true, completion: nil)

How to reuse slide up menu class in any view controller?

Code

class ViewController: UIViewController {

var oldMenu: OldMenu!

override func viewDidLoad() {
super.viewDidLoad()

oldMenu = OldMenu(controller: self)
navigationItem.rightBarButtonItem = oldMenu.MenuButton
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

extension ViewController: MenuDelegate {


func tableRowDidSelect(_ indexPath: IndexPath) {

}
}

OldMenu

class OldMenu: NSObject {

var presenter: UIViewController?

var menuController = MenuViewController()

var MenuButton: UIBarButtonItem!

init(controller: UIViewController?) {
super.init()
presenter = controller
MenuButton = UIBarButtonItem(title: "Menu", style: .plain, target: self, action: #selector(onClickMenu))
}

@objc func onClickMenu() {
menuController.modalPresentationStyle = .custom
menuController.transitioningDelegate = self
menuController.delegate = presenter as! MenuDelegate
presenter?.present(menuController, animated: true, completion: nil)
}
}

extension OldMenu: UIViewControllerTransitioningDelegate {

func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
PresentationController(presentedViewController: presented, presenting: presenting)
}

}

MenuViewController

Configure your tableView in MenuViewController, and use delegates to communicate back to the main view

protocol MenuDelegate {
func tableRowDidSelect(_ indexPath: IndexPath)
}

// Configure your tableView in MenuViewController
// Use delegates to communicate back to main view
class MenuViewController: UIViewController {

var delegate: MenuDelegate?

override func viewDidLoad() {
view.backgroundColor = .gray
}
}

PresentationController

You can reuse PresentationController to present view controllers in half screen.

import Foundation
import UIKit

class PresentationController: UIPresentationController {

let blurEffectView: UIVisualEffectView!
var tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer()

override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) {
let blurEffect = UIBlurEffect(style: .dark)
blurEffectView = UIVisualEffectView(effect: blurEffect)
super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissController))
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.blurEffectView.isUserInteractionEnabled = true
self.blurEffectView.addGestureRecognizer(tapGestureRecognizer)
}

override var frameOfPresentedViewInContainerView: CGRect {

// Set your presentation height
let presentHeight: CGFloat = 300

return CGRect(origin: CGPoint(x: 0, y: self.containerView!.frame.height - presentHeight),
size: CGSize(width: self.containerView!.frame.width, height: presentHeight))
}

override func presentationTransitionWillBegin() {
self.blurEffectView.alpha = 0
self.containerView?.addSubview(blurEffectView)
self.presentedViewController.transitionCoordinator?.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) in
self.blurEffectView.alpha = 0.5
}, completion: { (UIViewControllerTransitionCoordinatorContext) in })
}

override func dismissalTransitionWillBegin() {
self.presentedViewController.transitionCoordinator?.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) in
self.blurEffectView.alpha = 0
}, completion: { (UIViewControllerTransitionCoordinatorContext) in
self.blurEffectView.removeFromSuperview()
})
}

override func containerViewWillLayoutSubviews() {
super.containerViewWillLayoutSubviews()

// set your corner radius
presentedView!.roundCorners([.topLeft, .topRight], radius: 18)
}

override func containerViewDidLayoutSubviews() {
super.containerViewDidLayoutSubviews()
presentedView?.frame = frameOfPresentedViewInContainerView
blurEffectView.frame = containerView!.bounds
}

@objc func dismissController(){
self.presentedViewController.dismiss(animated: true, completion: nil)
}
}

extension UIView {
func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners,
cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
layer.mask = mask
}
}

Result

Sample Image

How to make transition of a ViewController from Bottom to Top?

Try this,

class SlideInTransition: NSObject, UIViewControllerAnimatedTransitioning {

var isPresenting = false
let dimmingView = UIView()

func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.3
}

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

guard let toViewController = transitionContext.viewController(forKey: .to),
let fromViewController = transitionContext.viewController(forKey: .from) else { return }

let containerView = transitionContext.containerView

let finalWidth = toViewController.view.bounds.width
let finalHeight = toViewController.view.bounds.height * 0.8

if isPresenting {
// Add dimming view
dimmingView.backgroundColor = .black
dimmingView.alpha = 0.0
containerView.addSubview(dimmingView)
dimmingView.frame = containerView.bounds
// Add menu view controller to container
containerView.addSubview(toViewController.view)

// Init frame off the screen
toViewController.view.frame = CGRect(x: 0, y: finalHeight, width: finalWidth, height: finalHeight)
}

// Move on screen
let transform = {
self.dimmingView.alpha = 0.5
toViewController.view.transform = CGAffineTransform(translationX: 0, y: -finalHeight)
}

// Move back off screen
let identity = {
self.dimmingView.alpha = 0.0
fromViewController.view.transform = .identity
}

// Animation of the transition
let duration = transitionDuration(using: transitionContext)
let isCancelled = transitionContext.transitionWasCancelled
UIView.animate(withDuration: duration, animations: {
self.isPresenting ? transform() : identity()
}) { (_) in
transitionContext.completeTransition(!isCancelled)
}
}
}


Related Topics



Leave a reply



Submit