iOS:记一次导航栏平滑过渡的实现

图片 6

 

UltraEdit 换行替换,ultraedit换行替换

需求:想在每行结尾添加   ‘),

图片 1

 

 

方案:在查找栏填写(^r^n)  替换栏(’),^r^n)

图片 2

 

效果:

图片 3

 

换行替换,ultraedit换行替换
需求:想在每行结尾添加 ‘), 方案:在查找栏填写( ^r^n ) 替换栏( ‘),^r^n
) 效果:…

3.1、手势滑动back

这种情况我们需要去监听导航控制器的手势滑动,导航控制器有个方法‘_updateInteractiveTransition:’,该方法可以监听手势滑动以及当前转场的进度,我们可以通过swizzing来交换方法实现,来接手‘_updateInteractiveTransition:’方法调用的监听

+ (void)load{
    //交换导航控制器的手势进度转场方法,来监听手势滑动的进度
    SEL originalSEL =  NSSelectorFromString(@"_updateInteractiveTransition:");
    SEL swizzledSEL =  NSSelectorFromString(@"xa_updateInteractiveTransition:");
    Method originalMethod = class_getInstanceMethod(self,  originalSEL);
    Method swizzledMethod = class_getInstanceMethod(self,  swizzledSEL);
    BOOL success = class_addMethod(self, originalSEL, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
    if(success){
        class_replaceMethod(self, swizzledSEL, method_getImplementation(originalMethod),  method_getTypeEncoding(originalMethod));
    }else{
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

然后通过转场的上下文信息,拿到源和目的的控制器navBarAlpha值,再根据percentComplete转场进度参数计算并设置导航栏透明度值,这样就完成了手势滑动的back

- (void)xa_updateInteractiveTransition:(CGFloat)percentComplete{
    [self xa_updateInteractiveTransition:percentComplete];
    UIViewController *topVC = self.topViewController;
    if(topVC){
        //通过transitionCoordinator拿到转场的两个控制器上下文信息
        id <UIViewControllerTransitionCoordinator> coordinator =  topVC.transitionCoordinator;
        if(coordinator != nil){
            //拿到源控制器和目的控制器的透明度(每个控制器都单独保存了一份)
            CGFloat fromVCAlpha  = [coordinator viewControllerForKey:UITransitionContextFromViewControllerKey].xa_navBarAlpha;
            CGFloat toVCAlpha    = [coordinator viewControllerForKey:UITransitionContextToViewControllerKey].xa_navBarAlpha;
            //再通过源,目的控制器的导航条透明度和转场的进度(percentComplete)计算转场时导航条的透明度
            CGFloat newAlpha     = fromVCAlpha + ((toVCAlpha - fromVCAlpha ) * percentComplete);
            //这里不要直接去修改控制器navBarAlpha属性,会影响目的控制器的navBarAlpha的数值
            [self xa_changeNavBarAlpha:newAlpha];
        }
    }
}

 

3、实现平滑过渡

现在存在的问题就是我在某个页面设置了导航栏的透明度,back回上一个界面,导航栏的透明度值仍然是上个界面的

图片 4

navbug

这里做过渡有两种情况,一种是手势滑动back回上一个界面,还有一种情况是直接点击了back按钮回到上一个界面的。根据这两种情况我们分别做一下处理。

需求:想在每行结尾添加   ‘),

构思:

  • 首先要获取到导航栏里的子控件来设置其透明度(实现透明度变化)
  • 为所有控制器添加一个导航栏透明度属性,用于记录当前控制器的导航栏透明度(记录透明度值)
  • 通过监听手势滑动来获取源和目的控制器,计算从源到目的控制器的透明度变化,来改变导航栏的透明度(实现平滑过渡)

图片 5

bardemo


效果:

1、实现透明度变化

要想实现透明度变化,得先获取到导航栏里的子控件,然后设置其alpha值。但是如何获取呢?
首先考虑使用KVC,通过导航栏的’valueForKey:‘方法来获取子控件对象,但是在不同的系统上,导航栏里的子控件布局排布也是有所不同,
意味着key值并非固定,通过key值拿子控件对象的方法在不同的系统上就很容易抛异常。

图片 6

左:iOS10 右:iOS9

考虑到这一点,我采用了最直接的方式:遍历导航栏的所有子控件,拿到首个子控件给其设置透明度。这样不但不需要再去考虑系统的问题了,同时也能满足带颜色的导航栏或者是带背景图的导航栏透明度的变化。

- (void)xa_changeNavBarAlpha:(CGFloat)navBarAlpha{
    NSMutableArray *barSubviews = [NSMutableArray array];
    //将导航栏的子控件添加到数组当中,取首个子控件设置透明度(防止导航栏上存在非导航栏自带的控件)
    for (UIView * view in self.navigationBar.subviews) {
        if(![view isMemberOfClass:[UIView class]]){
            [barSubviews addObject:view];
        }
    }
    UIView *barBackgroundView = [barSubviews firstObject];
    barBackgroundView.alpha   = navBarAlpha;
}
You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图