1. 程式人生 > >iOS仿支付寶首頁效果

iOS仿支付寶首頁效果

tor www self get mage rsh .data 一定的 完全

代碼地址如下:
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大師代發,拒絕轉載,轉載需要作者授權

iOS仿支付寶首頁效果