.NET을 사용하여 탭 모음 기반 응용 프로그램에서 프로그래밍 방식으로 탭을 전환하고 UITabBarController.selectedIndex
있습니다. 제가 해결하려는 문제는 뷰 간의 전환을 애니메이션으로 만드는 방법입니다. 즉. 현재 탭의보기에서 선택한 탭의보기로.
첫 번째 생각은를 사용하는 것이 UITabBarControllerDelegate
었지만 프로그래밍 방식으로 탭을 전환 할 때 호출되지 않는 것으로 보입니다. 나는 이제 UITabBarDelegate.didSelectItem
전환 애니메이션을 설정하는 가능한 후크로 고려하고 있습니다.
누구든지 전환을 애니메이션으로 만들 수 있습니까? 그렇다면 어떻게?
답변
2016 년 4 월 업데이트 : Justed는 모든 투표에 대해 모든 사람에게 감사를 표하기 위해이 내용을 업데이트하고 싶었습니다. 또한 이것은 원래 ARC 이전, 제약 이전, 이전 … 많은 것들로 돌아가서 작성되었습니다! 따라서 이러한 기술을 사용할지 여부를 결정할 때이 점을 고려하십시오. 더 현대적인 접근 방식이있을 수 있습니다. 아, 그리고 찾으면. 모든 사람이 볼 수 있도록 응답을 추가하세요. 감사.
얼마 후 …
많은 연구 끝에 두 가지 작업 솔루션을 찾았습니다. 둘 다 작동하고 탭 사이의 애니메이션을 수행했습니다.
솔루션 1 :보기에서 전환 (단순)
이것은 가장 쉽고 미리 정의 된 UIView 전환 방법을 사용합니다. 이 솔루션을 사용하면 방법이 우리를 위해 일하기 때문에 뷰를 관리 할 필요가 없습니다.
// Get views. controllerIndex is passed in as the controller we want to go to.
UIView * fromView = tabBarController.selectedViewController.view;
UIView * toView = [[tabBarController.viewControllers objectAtIndex:controllerIndex] view];
// Transition using a page curl.
[UIView transitionFromView:fromView
toView:toView
duration:0.5
options:(controllerIndex > tabBarController.selectedIndex ? UIViewAnimationOptionTransitionCurlUp : UIViewAnimationOptionTransitionCurlDown)
completion:^(BOOL finished) {
if (finished) {
tabBarController.selectedIndex = controllerIndex;
}
}];
해결 방법 2 : 스크롤 (더 복잡함)
더 복잡한 솔루션이지만 애니메이션을 더 많이 제어 할 수 있습니다. 이 예에서는 슬라이드를 켜고 끌 수있는 뷰를 얻습니다. 이것으로 우리는 뷰를 직접 관리해야합니다.
// Get the views.
UIView * fromView = tabBarController.selectedViewController.view;
UIView * toView = [[tabBarController.viewControllers objectAtIndex:controllerIndex] view];
// Get the size of the view area.
CGRect viewSize = fromView.frame;
BOOL scrollRight = controllerIndex > tabBarController.selectedIndex;
// Add the to view to the tab bar view.
[fromView.superview addSubview:toView];
// Position it off screen.
toView.frame = CGRectMake((scrollRight ? 320 : -320), viewSize.origin.y, 320, viewSize.size.height);
[UIView animateWithDuration:0.3
animations: ^{
// Animate the views on and off the screen. This will appear to slide.
fromView.frame =CGRectMake((scrollRight ? -320 : 320), viewSize.origin.y, 320, viewSize.size.height);
toView.frame =CGRectMake(0, viewSize.origin.y, 320, viewSize.size.height);
}
completion:^(BOOL finished) {
if (finished) {
// Remove the old view from the tabbar view.
[fromView removeFromSuperview];
tabBarController.selectedIndex = controllerIndex;
}
}];
Swift의이 솔루션 :
extension TabViewController: UITabBarControllerDelegate {
public func tabBarController(tabBarController: UITabBarController, shouldSelectViewController viewController: UIViewController) -> Bool {
let fromView: UIView = tabBarController.selectedViewController!.view
let toView : UIView = viewController.view
if fromView == toView {
return false
}
UIView.transitionFromView(fromView, toView: toView, duration: 0.3, options: UIViewAnimationOptions.TransitionCrossDissolve) { (finished:Bool) in
}
return true
}
}
답변
다음은 drekka 코드를 delegate (UITabBarControllerDelegate) 메서드에 사용하려는 시도입니다.
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
NSArray *tabViewControllers = tabBarController.viewControllers;
UIView * fromView = tabBarController.selectedViewController.view;
UIView * toView = viewController.view;
if (fromView == toView)
return false;
NSUInteger fromIndex = [tabViewControllers indexOfObject:tabBarController.selectedViewController];
NSUInteger toIndex = [tabViewControllers indexOfObject:viewController];
[UIView transitionFromView:fromView
toView:toView
duration:0.3
options: toIndex > fromIndex ? UIViewAnimationOptionTransitionFlipFromLeft : UIViewAnimationOptionTransitionFlipFromRight
completion:^(BOOL finished) {
if (finished) {
tabBarController.selectedIndex = toIndex;
}
}];
return true;
}
답변
iOS7.0 이상에 대한 내 솔루션입니다.
탭 모음의 대리자에서 사용자 지정 애니메이션 컨트롤러를 지정할 수 있습니다.
다음과 같은 애니메이션 컨트롤러를 구현합니다.
@interface TabSwitchAnimationController : NSObject <UIViewControllerAnimatedTransitioning>
@end
@implementation TabSwitchAnimationController
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
return 0.2;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
UIViewController* fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController* toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView* toView = toVC.view;
UIView* fromView = fromVC.view;
UIView* containerView = [transitionContext containerView];
[containerView addSubview:toView];
toView.frame = [transitionContext finalFrameForViewController:toVC];
// Animate by fading
toView.alpha = 0.0;
[UIView animateWithDuration:[self transitionDuration:transitionContext]
delay:0.0
options:UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionAllowUserInteraction
animations:^{
toView.alpha = 1.0;
}
completion:^(BOOL finished) {
toView.alpha = 1.0;
[fromView removeFromSuperview];
[transitionContext completeTransition:YES];
}];
}
@end
그런 다음 UITabBarControllerDelegate에서 사용하십시오.
- (id <UIViewControllerAnimatedTransitioning>)tabBarController:(UITabBarController *)tabBarController
animationControllerForTransitionFromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC
{
return [[TabSwitchAnimationController alloc] init];
}
답변
사용하는 대신 tabBarController:shouldSelectViewController:
구현 하는 것이 좋습니다tabBarController:animationControllerForTransitionFromViewController:toViewController:
TransitioningObject.swift
import UIKit
class TransitioningObject: NSObject, UIViewControllerAnimatedTransitioning {
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
let fromView: UIView = transitionContext.viewForKey(UITransitionContextFromViewKey)!
let toView: UIView = transitionContext.viewForKey(UITransitionContextToViewKey)!
transitionContext.containerView().addSubview(fromView)
transitionContext.containerView().addSubview(toView)
UIView.transitionFromView(fromView, toView: toView, duration: transitionDuration(transitionContext), options: UIViewAnimationOptions.TransitionCrossDissolve) { finished in
transitionContext.completeTransition(true)
}
}
func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
return 0.25
}
}
TabBarViewController.swift
import UIKit
class TabBarViewController: UITabBarController, UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
// MARK: - Tabbar delegate
func tabBarController(tabBarController: UITabBarController, animationControllerForTransitionFromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return TransitioningObject()
}
}
답변
CATransition을 사용하여 UITabBarControlelr에 대한 전환을 쉽게 수행 할 수 있다고 생각합니다. 이것은 또한 transitionFromView : toView 사용의 모든 부작용을 해결합니다.
UITabBarController에서 확장 된 사용자 정의 TabBarController 클래스 내에서 이것을 사용하십시오.
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController (UIViewController*)viewController {
CATransition *animation = [CATransition animation];
[animation setType:kCATransitionFade];
[animation setDuration:0.25];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:
kCAMediaTimingFunctionEaseIn]];
[self.view.window.layer addAnimation:animation forKey:@"fadeTransition"];
}
도움이 되었기를 바랍니다 🙂
답변
내가 쓴 글을 여기에 다양한 답변을 시도한 후.
코드는 Swift에 있으며을 호출하여 애니메이션으로 탭을 프로그래밍 방식으로 변경할 수 있습니다 animateToTab
.
func animateToTab(toIndex: Int) {
let tabViewControllers = viewControllers!
let fromView = selectedViewController!.view
let toView = tabViewControllers[toIndex].view
let fromIndex = tabViewControllers.indexOf(selectedViewController!)
guard 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.mainScreen().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.userInteractionEnabled = false
UIView.animateWithDuration(0.5, delay: 0.0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIViewAnimationOptions.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.userInteractionEnabled = true
})
}
모든 탭 변경에 애니메이션이 포함되도록하려면 다음 UITabBarControllerDelegate
과 같이 연결합니다 .
func tabBarController(tabBarController: UITabBarController, shouldSelectViewController viewController: UIViewController) -> Bool {
let tabViewControllers = tabBarController.viewControllers!
guard let toIndex = tabViewControllers.indexOf(viewController) else {
return false
}
// Our method
animateToTab(toIndex)
return true
}
답변
Swift의 내 솔루션 :
사용자 지정 TabBar 클래스를 만들고 스토리 보드 TabBar에서 설정합니다.
class MainTabBarController: UITabBarController, UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
// Do any additional setup after loading the view.
}
func tabBarController(tabBarController: UITabBarController, shouldSelectViewController viewController: UIViewController) -> Bool {
let tabViewControllers = tabBarController.viewControllers!
let fromView = tabBarController.selectedViewController!.view
let toView = viewController.view
if (fromView == toView) {
return false
}
let fromIndex = tabViewControllers.indexOf(tabBarController.selectedViewController!)
let toIndex = tabViewControllers.indexOf(viewController)
let offScreenRight = CGAffineTransformMakeTranslation(toView.frame.width, 0)
let offScreenLeft = CGAffineTransformMakeTranslation(-toView.frame.width, 0)
// start the toView to the right of the screen
if (toIndex < fromIndex) {
toView.transform = offScreenLeft
fromView.transform = offScreenRight
} else {
toView.transform = offScreenRight
fromView.transform = offScreenLeft
}
fromView.tag = 124
toView.addSubview(fromView)
self.view.userInteractionEnabled = false
UIView.animateWithDuration(0.5, delay: 0.0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
toView.transform = CGAffineTransformIdentity
}, completion: { finished in
let subViews = toView.subviews
for subview in subViews{
if (subview.tag == 124) {
subview.removeFromSuperview()
}
}
tabBarController.selectedIndex = toIndex!
self.view.userInteractionEnabled = true
})
return true
}
}