禁止转载,原因是源码不完整也并不耐看
前言
在某论坛看到一个置顶帖子,说是仿支付宝首页,手段大概是这样的
scrollview里放一个超长的tableview,长到整个tableview内容全部都一次展示出来,不让它滑动,然后在tableview上面塞一个view,里面做动画。。。。
问题大概看出来了:性能“爆表”
文章中用到的tableview中的cell都是空的,没有文字没有图片,顺畅是应该的,如果像支付宝一样放点内容进去呢?不说多了,20行就足够它内存爆炸了。
我的建议:菜鸟就不要在论坛发表“教程帖”了,论坛的大手们不要置顶这种帖子好不好?
那么应该怎么实现支付宝的首页效果,让内存占用廉价一点,代码优雅一点?
1.scrollview不嵌套
2.tableview/collectionview复用cell
正文-解决方案
整体解读
先上效果图

1.除去顶部的导航栏,其它应该只用一个scrollview(tableview/collectionview)来解决
2.动画是根据scrollview的contentoffset.y来控制的,通过notification或者scrollview.delegate来监听,我这里用的delegate
3.将动画分解为两部分:导航栏动画和header动画
4.下拉刷新控件要放在header下面(解决方案是设置scrollview.contentinset.top,让MJRefreshHeader放到header下面,这个方案collectionview和tableview通用,如果用tableview.tableheaderview,是实现不了这个效果的)
5.小细节:支付宝为了防止渐变过程中用户点击按钮出错,将滑动停止在动画的两个分界点,实现类似于scrollview.pagingenabled的效果,实现方式用的是scrollview.delegate中的-(void)scrollViewWillEndDragging:(UIScrollView*)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inoutCGPoint*)targetContentOffset方法
分解动画解读
1.导航栏动画根据contentoffset.y从小到大,分为4部分:无动画,带输入框的bar透明度从1到0,只有按钮的bar透明度从0到1,无动画

2.header动画根据contentoffset.y从小到大,分为3部分:无动画,大按钮透明度从1到0+大按钮父控件时间差移动,无动画

核心思想
1.原生导航栏隐藏,使用自定义view创建3个导航栏,父控件是controller.view,根据层级从下到上:背景色view(无交互),带文本输入框的bar(透明度动画),小按钮bar(透明度动画)
2.设置scrollview.contentinset.top,预留出header的位置,将header放置到scrollview上(主要作用是将刷新控件顶到下面去)
3.大按钮的时间差移动动画用autoresizingMask(UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin)+ 父控件高度变化来实现,至于原理请自行搜索引擎
小白分割线
源码
由于只是一时兴起,单纯的diss某论坛的置顶帖,所以代码可读性一般,不打算发github更不打算直接交给伸手党,代码发出来,看得懂就看,看不懂就查,查不出来就问,不要伸手!
如果这都看不懂又不自己研究的话,请留言,我看心情更新注释或者优化可读性,如果真的火了,我会优化到可以放到github上的程度
PS:导航栏ChenNavigationView是自定义view,不贴详细代码,请用UIView+UIButton来替换
#import "ChenTestViewController.h"
CGFloatHeaderHeight =100+140;
CGFloatHeaderContentViewHeight =140;
@interface ChenTestViewController ()
@property (nonatomic,weak)UITableView *tableView;
@property (nonatomic,weak)UIView *headerView;
@property(nonatomic,weak)UIView*headerButtonView;
@property(nonatomic,weak)ChenNavigationView*tempNavigationView;
@end
@implementationChenTestViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.navigationView removeAllItems];
NSArray *buttonNames = @[@"icon_me_infomation",@"icon_me_bankcard",@"icon_me_history",@"icon_me_message"];
for(NSString*buttonNameinbuttonNames) {
[self.navigationView addLeftButtonWithImageNameNormal:buttonName imageNameHightlight:buttonName target:self action:@selector(test)];
}
self.navigationView.alpha = 0;
UITableView *tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) style:UITableViewStylePlain];
[self.view insertSubview:tableView belowSubview:self.navigationView];
self.tableView= tableView;
if(@available(iOS11.0, *)) {
tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(test)];
tableView.contentInset=UIEdgeInsetsMake(self.navigationView.frame.size.height+HeaderHeight,0,0,0);
tableView.delegate=self;
tableView.dataSource=self;
tableView.scrollIndicatorInsets = UIEdgeInsetsMake(self.navigationView.frame.size.height + HeaderHeight, 0, 0, 0);
UIView*headerView = [[UIViewalloc]initWithFrame:CGRectMake(0, -tableView.contentInset.top,SCREEN_WIDTH,self.navigationView.frame.size.height+HeaderHeight)];
[tableViewaddSubview:headerView ];
self.headerView= headerView;
headerView.backgroundColor = [UIColor themeColor];
CGFloatheaderButtonWidth =SCREEN_WIDTH/ buttonNames.count;
CGFloat headerButtonHeight = HeaderHeight - HeaderContentViewHeight;
UIView*headerButtonView = [[UIViewalloc]initWithFrame:CGRectMake(0,self.navigationView.frame.size.height,SCREEN_WIDTH, headerButtonHeight)];
[headerViewaddSubview:headerButtonView];
self.headerButtonView= headerButtonView;
headerButtonView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
CGFloatbuttonX =0;
for(inti =0;i < buttonNames.count;i++){
NSString*imageName = buttonNames[i];
UIButton*headerButton = [[UIButtonalloc]initWithFrame:CGRectMake(buttonX,0, headerButtonWidth, headerButtonHeight)];
[headerButtonViewaddSubview:headerButton];
[headerButtonsetImage:[[UIImage imageNamed:imageName]scaleToSize:CGSizeMake(40, 40)] forState:UIControlStateNormal];
buttonX += headerButtonWidth;
}
UIView*headerContentView = [[UIViewalloc]initWithFrame:CGRectMake(0,CGRectGetMaxY(headerButtonView.frame),SCREEN_WIDTH,HeaderContentViewHeight)];
[headerViewaddSubview:headerContentView];
headerContentView.backgroundColor= [UIColorwhiteColor];
headerContentView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
ChenNavigationView *tempNavigationView = [[ChenNavigationView alloc]init];
[self.viewinsertSubview:tempNavigationViewbelowSubview:self.navigationView];
self.tempNavigationView= tempNavigationView;
UIButton*tempLeftButton = [tempNavigationViewaddRightButtonWithTitle:@"临时"target:selfaction:@selector(test)];
[tempNavigationViewaddRightButtonWithTitle:@"占位"target:selfaction:@selector(test)];
UIView*tempNavigationBackgroundView = [[UIViewalloc]initWithFrame:tempNavigationView.frame];
[self.viewinsertSubview:tempNavigationBackgroundViewbelowSubview:tempNavigationView];
tempNavigationBackgroundView.backgroundColor= [UIColorthemeColor];
CGRecttempLeftButtonRect = [tempLeftButton.superviewconvertRect:tempLeftButton.frametoView:tempNavigationView];
UIView*tempView = [[UIViewalloc]initWithFrame:CGRectMake(12, tempLeftButtonRect.origin.y+6, tempLeftButtonRect.origin.x-12*2, tempLeftButtonRect.size.height-6*2)];
[tempNavigationViewaddSubview:tempView];
tempView.backgroundColor= [UIColorcolorWithString:@"0B80EE"alpha:1.0];
}
-(void)test{
[self.tableView.mj_header performSelector:@selector(endRefreshing) withObject:nil afterDelay:1];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView*)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section{
return 100;
}
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"test"];
if(!cell){
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"test"];
}
cell.backgroundColor = [UIColor randomColor];
returncell;
}
-(void)scrollViewDidScroll:(UIScrollView*)scrollView{
CGFloatcontentOffsetY = scrollView.contentOffset.y;
CGFloatheaderHeight =MIN(MAX(self.navigationView.frame.size.height, -contentOffsetY),self.navigationView.frame.size.height+HeaderHeight);
CGFloatheaderY =MIN(0, contentOffsetY);
CGFloattempNavigationAlpha =MIN(1,MAX(0, (headerHeight -self.navigationView.frame.size.height-HeaderContentViewHeight) / ((HeaderHeight-HeaderContentViewHeight) /2) -0.5));
CGFloat headerButtonAlpha = MIN(1, MAX(0, (headerHeight - self.navigationView.frame.size.height - HeaderContentViewHeight) / ((HeaderHeight - HeaderContentViewHeight) / 2)));
CGFloat navigationAlpha = MIN(1, MAX(0, 1 - (headerHeight - self.navigationView.frame.size.height - HeaderContentViewHeight) / (HeaderHeight - HeaderContentViewHeight)));
NSLog(@"contentOffsetY:%.2f headerHeight:%.2f headerY:%.2f tempNavigationAlpha:%.2f headerButtonAlpha:%.2f navigationAlpha:%.2f",contentOffsetY,headerHeight,headerY,tempNavigationAlpha,headerButtonAlpha,navigationAlpha);
self.tempNavigationView.alpha= tempNavigationAlpha;
self.navigationView.alpha= navigationAlpha;
self.headerButtonView.alpha= headerButtonAlpha;
self.headerView.frame=CGRectMake(self.headerView.frame.origin.x, headerY,self.headerView.frame.size.width, headerHeight);
}
-(void)scrollViewWillEndDragging:(UIScrollView*)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inoutCGPoint*)targetContentOffset{
CGPointoriginalTargetContentOffset =CGPointMake(targetContentOffset->x, targetContentOffset->y);
if(originalTargetContentOffset.y< -HeaderContentViewHeight){
if(originalTargetContentOffset.y< -(scrollView.contentInset.top- (HeaderHeight-HeaderContentViewHeight) /2)){
*targetContentOffset =CGPointMake(0, -scrollView.contentInset.top);
}else{
*targetContentOffset =CGPointMake(0, -(scrollView.contentInset.top- (HeaderHeight-HeaderContentViewHeight)));
}
}
}
@end
网友评论