ios導航欄的使用和滑動返回
//self.navigationItem.title = @"這麼任性好麼";
UILabel *title = [[UILabelalloc]initWithFrame:self.view.bounds];
title.textColor = [UIColorwhiteColor];
title.backgroundColor = [UIColorclearColor];
title.textAlignment =NSTextAlignmentCenter;
title.text =@"產品庫";
title.font = [
self.navigationItem.titleView = title;
[self.navigationController.navigationBarsetBarTintColor:[UIColorcolorWithRed:1green:0.1blue:0.1alpha:1.000]]; //設定導航欄背景顏色
3,滑動返回。
iOS 7中在傳統的左上角返回鍵之外,提供了右滑返回上一級介面的手勢。支援此手勢的是UINavigationController中新增的屬性
interactivePopGestureRecognizer,即右滑返回只支援以UINavigationController為容器的ViewController間切換,要想在自定義容 器中使用,需要一些額外的工作。
基本地,控制ViewController是否啟用右滑返回,只需要這樣:
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
預設情況下enabled為YES。
在實際使用中,遇到了一些問題,整理如下:
1、自定義返回按鈕後,右滑返回失效;
解決方案:比較直觀的辦法是在自定義返回按鈕時,使用backBarButtonItem:
1 UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
2//some initialize code here...
3UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
4self.navigationItem.leftBarButtonItem = barItem; //not working
5self.navigationItem.backBarButtonItem = barItem; //serve well
但這樣無法支援左上角多個按鈕的情況。考慮到 interactivePopGestureRecognizer也有delegate屬性,替換預設的self . navigationController .interactivePopGestureRecognizer.delegate來配置右滑返回的表現也是可行的。在rootViewController中:
self.navigationController.interactivePopGestureRecognizer.delegate =self;
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if (self.navigationController.viewControllers.count ==1)//關閉主介面的右滑返回
{
returnNO;
}
else {
return YES;
}
}
這種方式沒有辦法自定義轉場動畫,下面的是可以自定義轉場動畫的方式。
// UINavigationController.h
@property(nullable,nonatomic,weak)id<UINavigationControllerDelegate> delegate;
要使用這個代理。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
_revenueAnalyseVc = [[layerViewController alloc] init];
UINavigationController *rootNavigationController = [[UINavigationController alloc] initWithRootViewController:_revenueAnalyseVc];
[rootNavigationController setNavigationBarHidden:YES];
rootNavigationController.delegate = [NavigationPerformer getNavigationPerformerInstance];
[[NavigationPerformer getNavigationPerformerInstance] setupPanGesture:rootNavigationController];
self.window.rootViewController = rootNavigationController;
[self.window makeKeyAndVisible];
return YES;
}
下面這個類是對手勢的處理、動畫的選擇、動畫的進度控制。#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface NavigationPerformer : NSObject <UINavigationControllerDelegate>
@property (nonatomic, strong) id<UIViewControllerAnimatedTransitioning> pushAnimation;
@property (nonatomic, strong) id<UIViewControllerAnimatedTransitioning> popAnimation;
@property (nonatomic, weak) UINavigationController *referenceNaviController;
@property (nonatomic, strong) UIPercentDrivenInteractiveTransition *interactionController;
@property (nonatomic, assign) CGPoint locationS;
+(NavigationPerformer *)getNavigationPerformerInstance;
-(void)setupPanGesture: (UINavigationController *)referenceNaviController;
@property (nonatomic, assign) BOOL isInMoveState;
@end
#import "NavigationPerformer.h"
#import "transAnimate.h"
@implementation NavigationPerformer
- (id)init{
if (self = [super init]) {
_pushAnimation = [[transAnimate alloc] init];
((transAnimate*)_pushAnimation).theType = animateTypePush;
_popAnimation = [[transAnimate alloc] init];
((transAnimate*)_popAnimation).theType = animateTypePop;
}
return self;
}
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC
{
if (operation == UINavigationControllerOperationPush) {
return self.pushAnimation;
}
else if (operation == UINavigationControllerOperationPop) {
return self.popAnimation;
}
return nil;
}
- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController {
return self.interactionController;
}
+(NavigationPerformer *)getNavigationPerformerInstance {
static dispatch_once_t once;
static NavigationPerformer * NavigationPerformerInstance;
dispatch_once(&once, ^{
NavigationPerformerInstance = [[NavigationPerformer alloc] init];
});
return NavigationPerformerInstance;
}
- (void)pan:(UIPanGestureRecognizer *)pan {
UIView *view = self.referenceNaviController.view;
if (pan.state == UIGestureRecognizerStateBegan) {
_locationS = [pan translationInView:view];
}
else if (pan.state == UIGestureRecognizerStateChanged) {
CGPoint translation = [pan translationInView:view];
if (translation.x - _locationS.x > 0 && self.referenceNaviController.viewControllers.count > 1) {
if (!_isInMoveState) {
_isInMoveState = YES;
self.interactionController = [[UIPercentDrivenInteractiveTransition alloc] init];
[self.referenceNaviController popViewControllerAnimated:YES];
}
}
CGFloat progress = (translation.x - _locationS.x) / [UIScreen mainScreen].bounds.size.width;
[self.interactionController updateInteractiveTransition:progress];
}
else if (pan.state == UIGestureRecognizerStateEnded) {
CGPoint translation = [pan translationInView:view];
if(translation.x - _locationS.x > 20) {
[self.interactionController finishInteractiveTransition];
}
else {
[self.interactionController cancelInteractiveTransition];
}
_isInMoveState = NO;
_locationS = CGPointZero;
self.interactionController = nil;
}
}
-(void)setupPanGesture: (UINavigationController *)referenceNaviController {
self.referenceNaviController = referenceNaviController;
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
[self.referenceNaviController.view addGestureRecognizer:panGesture];
}
@end
下面的程式碼是push或是pop的動畫自定義。
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef enum {
animateTypePush,
animateTypePop
}animateType;
@interface transAnimate : NSObject <UIViewControllerAnimatedTransitioning>
@property (nonatomic, assign) animateType theType;
@end
#import "transAnimate.h"
@implementation transAnimate
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext {
return 2.5;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
UIViewController *desController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController *srcController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
CGRect shadowStartFrame, shadowEndFrame;
CGRect srcViewRectTo;
CGRect desViewRectTo;
CGRect srcViewRectFrom;
CGRect desViewRectFrom;
UIView *maskView = nil;
CGFloat maskAlphaend = 0.0;
UIImageView *shadowImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"trans_shadow"]];
if (_theType == animateTypePush) {
[[transitionContext containerView] addSubview:desController.view];
srcViewRectTo = CGRectMake(-[UIScreen mainScreen].bounds.size.width/2, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
desViewRectTo = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
srcViewRectFrom = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
desViewRectFrom = CGRectMake([UIScreen mainScreen].bounds.size.width, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
}
else if (_theType == animateTypePop) {
[[transitionContext containerView] insertSubview:desController.view belowSubview:srcController.view];
srcViewRectTo = CGRectMake([UIScreen mainScreen].bounds.size.width, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
desViewRectTo = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
srcViewRectFrom = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
desViewRectFrom = CGRectMake(-[UIScreen mainScreen].bounds.size.width/2, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
maskView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
maskView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5f];
maskView.frame = desViewRectFrom;
maskView.alpha = 0.3;
[[transitionContext containerView] insertSubview:maskView belowSubview:srcController.view];
shadowStartFrame = CGRectMake(srcViewRectFrom.origin.x - 8, srcViewRectFrom.origin.y, 8, srcViewRectFrom.size.height);
shadowEndFrame = CGRectMake(srcViewRectTo.origin.x - 8, srcViewRectTo.origin.y, 8, srcViewRectTo.size.height);
[[transitionContext containerView] insertSubview:shadowImageView aboveSubview:maskView];
}
desController.view.frame = desViewRectFrom;
srcController.view.frame = srcViewRectFrom;
shadowImageView.frame = shadowStartFrame;
[UIView animateWithDuration:[self transitionDuration:transitionContext]
delay:0
options:UIViewAnimationOptionCurveLinear
animations:^{
desController.view.frame = desViewRectTo;
srcController.view.frame = srcViewRectTo;
shadowImageView.frame = shadowEndFrame;
maskView.frame = desViewRectTo;
maskView.alpha = maskAlphaend;
}
completion:^(BOOL finished) {
[shadowImageView removeFromSuperview];
[maskView removeFromSuperview];
//srcController.view.transform = CGAffineTransformIdentity;
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
}
@end