zoukankan      html  css  js  c++  java
  • iOS仿支付宝首页效果

    代码地址如下:
    http://www.demodashi.com/demo/12776.html

    首先看一下效果

    效果
    状态栏红色是因为使用手机录屏的原因。

    1.问题分析

    效果图

    1.导航栏A有两组控件,随着tableView的向上滑动,这一组控件的透明度从1到0,然后另一组控件透明度从0到1,如此反复。
    2.导航栏下面的一组控件B,随着tableView向上滑动,也往上滑动,但是滑动值小于tableView的滑动值。透明度逐渐变成0,然后消失。
    3.tableView的头部有一个控件C,跟随tableView一起滑动,滑动值相同。(很流畅,无卡顿)
    4.tableView即控件D的右侧滚动条从中间开始。
    5.滑动控件B,C,D,tableView均能做出反应。
    6.如果tableView滑动较少时,导航栏下面的控件B会根据滑动的多少自动折叠或者完全展开。

    很多人看到第4条时,可能会认为tableView从中间开始,其实不一定是这样。scrollview有一个属性scrollIndicatorInsets可以设置滚动条的偏移。

    我的思路

    将控件B,C都加在tableView的视图上面,这样滑动的时候,可以直接跟随tableView滚动(滑动的时候绝度丝滑),另外由于B,C是tableView的子视图,当滑动的时候无法响应滑动手势,然后传递给tableView滑动手势响应,这应解决了问题3,5。这样需要给tableView设置偏移,否则会被B,C挡住一部分。
    然后给tableView的scrollIndicatorInsets设置偏移,这样有一种tableView从中间开始的假象。解决了问题4。

    创建各个组件的代码

    - (void)initView {
        CustrmNav * nav = [CustrmNav custrmNav];
        //navBShadowView 背后不响应事件,只是上划的时候显示
        NavBarBottomView * navBShadowView = [NavBarBottomView navBarBottomView];
        navBShadowView.frame = CGRectMake(0, CGRectGetMaxY(nav.frame), Screen_Width, 80);
        [self.view addSubview:navBShadowView];
        //navBottom 响应事件,在滑动 tableView下滑动到0以后出现
        NavBarBottomView * navBottom = [NavBarBottomView navBarBottomView];
        navBottom.frame = CGRectMake(0, -320, Screen_Width, 80);
        
        TabHeaderView * tabHeader = [TabHeaderView tabHeaderView];
        tabHeader.frame = CGRectMake(0, -240, Screen_Width, 240);
        CGFloat backH = nav.height + navBottom.height;
        CGFloat contentY = tabHeader.height + navBottom.height;
        
        //增加背景色View
        UIView * backView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, Screen_Width, backH)];
        backView.backgroundColor = MP_RGBColor(27, 107, 200);
        [self.view insertSubview:backView atIndex:0];
        
        _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(nav.frame), Screen_Width, Screen_Height-nav.height-MP_TabBarHeight) style:UITableViewStylePlain];
        _tableView.delegate = self;
        _tableView.dataSource = self;
        
        //设置偏移量
        [_tableView setContentInset:UIEdgeInsetsMake(contentY , 0, 0, 0)];
        //假装tableView 从TabHeaderView 的下部开始的
        _tableView.scrollIndicatorInsets = UIEdgeInsetsMake(contentY, 0, 0, 0);
        //背景透明
        _tableView.backgroundColor = [UIColor clearColor];
        [self.view addSubview:_tableView];
        [_tableView addSubview:navBottom];
        [_tableView addSubview:tabHeader];
        //放在顶层的 nav 应在在最外层的view
        [self.view addSubview:nav];
        
        MJRefreshNormalHeader *mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
            [self refershAction];
        }];
        _tableView.mj_header = mj_header;
        
        [[SlideManger shareSlideManger] slideMangerCustomNav:nav navBottm:navBottom tabHeader:tabHeader navBottomShadowView:navBShadowView];
    }
    

    1.解决第一个问题,自定义导航栏,可以通过检测tableView的滑动值,来改变A控件内的视图的透明度来实现。
    自定义导航栏代码Xib布局

    #import "CustrmNav.h"
    @interface CustrmNav ()
    @property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
    @property (weak, nonatomic) IBOutlet UIImageView *plusup;
    @property (weak, nonatomic) IBOutlet UIImageView *firend;
    @property (weak, nonatomic) IBOutlet UIImageView *sao;
    @property (weak, nonatomic) IBOutlet UIImageView *pay;
    @property (weak, nonatomic) IBOutlet UIImageView *search;
    @property (weak, nonatomic) IBOutlet UIImageView *get;
    @property (weak, nonatomic) IBOutlet UIImageView *plusdown;
    
    @end
    @implementation CustrmNav
    
    + (id)custrmNav {
        NSString * className = NSStringFromClass([self class]);
        UINib * nib = [UINib nibWithNibName:className bundle:nil];
        CustrmNav * nav = [nib instantiateWithOwner:nil options:nil].firstObject;
        [nav updateAlpha:0.0];
        nav.frame = CGRectMake(0, 0, Screen_Width, MP_NavBarHeight);
        return nav;
    }
    
    - (void)updateAlpha:(float)alpha {
        //上部分
        _sao.alpha = (alpha-0.5) * 2;
        _pay.alpha = (alpha-0.5) * 2;
        _plusup.alpha = (alpha-0.5) * 2;
        _get.alpha = (alpha-0.5) * 2;
        _search.alpha = (alpha-0.5) * 2;
        //下部分
        _searchBar.alpha = 1 - alpha * 2;
        _plusdown.alpha = 1 - alpha * 2;
        _firend.alpha = 1 - alpha * 2;
        //当滑到一定的位置,背景变成有色
        if (alpha >= 1.0) {
            self.backgroundColor = MP_RGBColor(27, 107, 200);
        } else {
            self.backgroundColor = [UIColor clearColor];
        }
    }
    
    

    2.解决问题二,我是为B控件又创建了一个分身B1放到tabelView的背后视图上。当向上滑动的时候,B隐藏B1显示,然后根据tableView的滑动距离,改变B1的Y值。另外改变里面的小组件的透明度

    处理各个组件的透明度以及动画效果管理类

    #import "SlideManger.h"
    #import <UIKit/UIKit.h>
    #import "CustrmNav.h"
    #import "NavBarBottomView.h"
    @interface SlideManger ()<NSCopying, NSMutableCopying>
    @property(nonatomic,weak)NavBarBottomView * navBottmView;
    @property(nonatomic,weak)NavBarBottomView * navBShadowView;
    @property(nonatomic,weak)UIView * tabHeader;
    @property(nonatomic,weak)CustrmNav * customNav;
    
    @end
    static SlideManger * _slideManger = nil;
    @implementation SlideManger
    + (id)shareSlideManger {
        return [[self alloc] init];
    }
    
    + (id)allocWithZone:(struct _NSZone *)zone {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            if (_slideManger == nil) {
                _slideManger = [super allocWithZone:zone];
            }
        });
        return _slideManger;
    }
    
    - (id)copyWithZone:(NSZone *)zone {
        return _slideManger;
    }
    
    - (id)mutableCopyWithZone:(NSZone *)zone {
        return _slideManger;
    }
    
    
    - (void)slideMangerCustomNav:(UIView *)customNav navBottm:(UIView *)navBottmView tabHeader:(UIView *)tabHeader navBottomShadowView:(UIView *)navBShadowView {
        if (navBottmView) {
            _navBottmView = (NavBarBottomView *)navBottmView;
        }
        if (tabHeader) {
            _tabHeader = tabHeader;
        }
        if (customNav) {
            _customNav = (CustrmNav *)customNav;
        }
        if (navBShadowView) {
            _navBShadowView = (NavBarBottomView *)navBShadowView;
        }
    }
    
    //滑动的时候
    - (void)tableViewSlide:(CGFloat)slide {
        if (_navBShadowView && _tabHeader) {
            //得到真实的偏移量,让slideY从0开始算起
            CGFloat slideY = slide + _navBShadowView.height + _tabHeader.height;
    //        NSLog(@"******%f",slideY);
            [self handleTabHeader:slideY];
            [self handleCustomNavNavBottom:slideY];
        }
    }
    //tableView 停止的时候 
    - (void)tabViewEndSlide:(CGFloat)slide scrollView:(UIScrollView *)scrollView {
        if (_navBShadowView && _tabHeader) {
            //得到真实的偏移量
            CGFloat slideY = slide + _navBShadowView.height + _tabHeader.height;
            if (slideY > 0) {
                if (slideY >= _navBShadowView.height/2 && slideY < _navBShadowView.height) {
                    //自动滑到上面
                    [scrollView setContentOffset:CGPointMake(0, -_tabHeader.height) animated:YES];
                } else if (slideY < _navBShadowView.height/2) {
                    //自动滑下去
                    [scrollView setContentOffset:CGPointMake(0, -(_navBShadowView.height + _tabHeader.height)) animated:YES];
                }
            }
        }
    }
    //处理 TabHeader 跟随 tableView 滑动
    - (void)handleTabHeader:(CGFloat)slide {
      static BOOL isDown = NO;
        if (slide <= 0) {
            _navBottmView.hidden = NO;
            _navBShadowView.hidden = YES;
            //tableView往下滑的时候,禁止 _tabHeader与_navBottmView一起下滑
            _tabHeader.y = -_tabHeader.height + slide;
            _navBottmView.y = -(_navBShadowView.height + _tabHeader.height) + slide;
            isDown = YES;
        } else {
            _navBottmView.hidden = YES;
            _navBShadowView.hidden = NO;
            if (isDown) {
                _tabHeader.y = -_tabHeader.height;
                isDown = NO;
            }
        }
    }
    //处理customnav  的渐变色问题 以及navbottom 影子 的位置 渐变色问题
    - (void)handleCustomNavNavBottom:(CGFloat)slide {
        if (slide >= 0) {
            CGFloat halfNavBottomH = _navBShadowView.height/2;
            CGFloat alpValue = (_navBShadowView.height - slide)?(_navBShadowView.height - slide):0;
            [_navBShadowView updateAlpha:alpValue/_navBShadowView.height];
            [_customNav updateAlpha:slide/_navBShadowView.height];
            if (slide<= _navBShadowView.height) {
                _navBShadowView.y = _customNav.height - slide/2;
            } else {
                _navBShadowView.y = _customNav.height - halfNavBottomH;
            }
        } else {
            [_navBShadowView updateAlpha:1.0];
            [_customNav updateAlpha:0.0];
            _navBShadowView.y = _customNav.height;
        }
    }
    
    @end
    

    6.解决问题六,主要是scrollView的 代理的滚动停止的方法和拖拽停止的方法确定不会再滚动的时候。依据滚动停止tableView滑动量来确定是展开还是折叠。

    //tableView 停止的时候
    - (void)tabViewEndSlide:(CGFloat)slide scrollView:(UIScrollView *)scrollView {
        if (_navBShadowView && _tabHeader) {
            //得到真实的偏移量
            CGFloat slideY = slide + _navBShadowView.height + _tabHeader.height;
            if (slideY > 0) {
                if (slideY >= _navBShadowView.height/2 && slideY < _navBShadowView.height) {
                    //自动滑到上面
                    [scrollView setContentOffset:CGPointMake(0, -_tabHeader.height) animated:YES];
                } else if (slideY < _navBShadowView.height/2) {
                    //自动滑下去
                    [scrollView setContentOffset:CGPointMake(0, -(_navBShadowView.height + _tabHeader.height)) animated:YES];
                }
            }
        }
    }
    

    项目结构图

    iOS仿支付宝首页效果

    代码地址如下:
    http://www.demodashi.com/demo/12776.html

    注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

  • 相关阅读:
    Jenkins 集成Sonar scanner的使用案例
    Sonarqube 安装 及与Jenkins sonar scanner插件集成部署
    shell if 判断匹配1位数字
    使用tcpdump抓包
    golang + snap7 对西门子plc进行读写
    python基础练习题(题目 求输入数字的平方,如果平方运算后小于 50 则退出)
    python基础练习题(题目 统计 1 到 100 之和)
    python基础练习题(题目 使用lambda来创建匿名函数。)
    微服务状态之python巡查脚本开发
    python基础练习题(题目 计算两个矩阵相加)
  • 原文地址:https://www.cnblogs.com/demodashi/p/9436618.html
Copyright © 2011-2022 走看看