你的浏览器禁用了JavaScript, 请开启后刷新浏览器获得更好的体验!
首页
热门
推荐
精选
登录
|
注册
iOS仿支付宝首页的刷新布局效果
立即下载
用AI写一个
金额:
1
元
支付方式:
友情提醒:源码购买后不支持退换货
立即支付
我要免费下载
发布时间:2018-03-30
24人
|
浏览:3437次
|
收藏
|
分享
技术:object-c
运行环境:iOS 8.0+
概述
支付宝的新版,首页的UI和刷新控件的位置发生了变化,模仿首页的动画效果
详细
# XYAlipayRefreshDemo ## 运行效果 ![](/contentImages/image/20180329/GTwqGjniAPbls3H6iPR.gif) ## 动画效果分析 1.UI需要变动,向上滑动的时候,顶部部分收缩。 2.右侧的滚动条的位置是从中间开始的,说明一个现象,这个tableview是从这里开始的。 3.tableview上面的view,是给tableview一起滑动,做到了无缝衔接。 4.滑动 tableview 上面那块 view ,直接响应滑动。 **实现思路:** 怎么解决以上四个效果问题,是本次的重点。经过多次的尝试分析得出,采用UIScrollView加UITableView的方式实现。从右侧滚动条开始的位置,上部分是个view,下部分是个UITableView。topView和UITableView作为UIScrollView的subView。 ## 关键点分析 1.实现scrollView的代理方法`scrollViewDidScroll`,设置顶部topview的导航栏位置的视图的高度为KTopHeaderViewHeight。当scrollView的y轴偏移量大于0且小于KTopHeaderViewHeight时,计算出透明度的变化。 ``` CGFloat alpha = (offsetY*2/KTopHeaderViewHeight>0) ? offsetY*2/KTopHeaderViewHeight:0; if (alpha > 0.5) { self.navNewView.alpha = alpha*2-1; self.navView.alpha = 0; } else { self.navNewView.alpha = 0; self.navView.alpha = 1-alpha*2; } self.topHeaderView.alpha = 1-alpha; ``` 2.滚动条是从中部开始,也是从tableView的位置开始,因此设置scrollView的Indicator的显示位置。其中`KTopViewHeight`的高度是滚动条开始以上位置的高度,整个topView的高度。 ``` _scrollView.scrollIndicatorInsets = UIEdgeInsetsMake(KTopViewHeight, 0, 0, 0); ``` 3.scrollView和tableView同时具有滚动效果,当不做处理是,会出现滑动冲突。因此设置tableView的scrollEnabled为NO,解决滑动冲突。 ``` _tableView.scrollEnabled = NO; ``` 4.tableView作为scrollView的子视图,tableView的内容会随着刷新加载变化,为了正常的显示全部能容,需要监听tableView的contentSize,实时改变scrollView的contentSize ``` - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary
*)change context:(void *)context { if ([keyPath isEqualToString:@"contentSize"]) { CGRect tFrame = self.tableView.frame; tFrame.size.height = self.tableView.contentSize.height; self.tableView.frame = tFrame; self.scrollView.contentSize = CGSizeMake(0, self.tableView.contentSize.height+KTopViewHeight); } } ``` 5.在顶部视图收缩时,页面滑动时,topView和tableView的相对ScrollView的位置在发生变化。因此在UIScrollView的代理里面改变topView和tableView的frame值。 ``` - (void)scrollViewDidScroll:(UIScrollView *)scrollView { CGFloat offsetY = self.scrollView.contentOffset.y; if (offsetY <= 0.0) { CGRect frame = self.topView.frame; frame.origin.y = offsetY; self.topView.frame = frame; CGRect tFrame = self.tableView.frame; tFrame.origin.y = offsetY + KTopViewHeight; self.tableView.frame = tFrame; if (![self.tableView isRefreshing]) { self.tableView.contentOffset = CGPointMake(0, offsetY); } } else if (offsetY < KTopHeaderViewHeight && offsetY >0) { CGFloat alpha = (offsetY*2/KTopHeaderViewHeight>0) ? offsetY*2/KTopHeaderViewHeight:0; if (alpha > 0.5) { self.navNewView.alpha = alpha*2-1; self.navView.alpha = 0; } else { self.navNewView.alpha = 0; self.navView.alpha = 1-alpha*2; } self.topHeaderView.alpha = 1-alpha; } } ``` 注:下拉刷新控件是本人自己写的。可以替换成任意需要的控件,例如:MJRefresh,在相应的位置修改即可。 6、完整代码如下: ``` #import "ViewController.h" #import "UIScrollView+XYRefreshView.h" #define KScreenWidth [UIScreen mainScreen].bounds.size.width #define KScreenHeight [UIScreen mainScreen].bounds.size.height #define KTopViewHeight 300 #define KTopHeaderViewHeight 80 @interface ViewController ()
@property (nonatomic, strong) UIScrollView *scrollView; @property (nonatomic, strong) UITableView *tableView; @property (nonatomic, strong) UIView *topView; @property (nonatomic, strong) UIView *navBGView; @property (nonatomic, strong) UIView *navView; @property (nonatomic, strong) UIView *navNewView; @property (nonatomic, strong) UIView *topHeaderView; @property (nonatomic, assign) NSInteger dataCount; @end @implementation ViewController - (void)dealloc { [self removeObserver:self forKeyPath:@"contentSize"]; } - (void)viewDidLoad { [super viewDidLoad]; [self.view addSubview:self.navBGView]; [self.view addSubview:self.navView]; [self.view addSubview:self.navNewView]; [self.view addSubview:self.scrollView]; [self.scrollView addSubview:self.topView]; [self.scrollView addSubview:self.tableView]; //添加刷新控件 [self.tableView showPullRefreshViewWithDelegate:self]; [self.scrollView showPushRefreshViewWithDelegate:self]; [self.tableView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil]; self.dataCount = 20; } //根据tableView的contentSize改变scrollView的contentSize大小 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary
*)change context:(void *)context { if ([keyPath isEqualToString:@"contentSize"]) { CGRect tFrame = self.tableView.frame; tFrame.size.height = self.tableView.contentSize.height; self.tableView.frame = tFrame; self.scrollView.contentSize = CGSizeMake(0, self.tableView.contentSize.height+KTopViewHeight); } } #pragma mark - XYPullRefreshViewDelegate - (void)pullRefreshViewStartLoad:(XYPullRefreshView *)pullView { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [pullView endRefreshing]; self.dataCount += 5; [self.tableView reloadData]; }); } - (void)pushRefreshViewStartLoad:(XYPushRefreshView *)pushView { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [pushView endRefreshing]; self.dataCount += 5; [self.tableView reloadData]; }); } #pragma mark - UIScrollViewDelegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView { CGFloat offsetY = self.scrollView.contentOffset.y; if (offsetY <= 0.0) { CGRect frame = self.topView.frame; frame.origin.y = offsetY; self.topView.frame = frame; CGRect tFrame = self.tableView.frame; tFrame.origin.y = offsetY + KTopViewHeight; self.tableView.frame = tFrame; if (![self.tableView isRefreshing]) { self.tableView.contentOffset = CGPointMake(0, offsetY); } } else if (offsetY < KTopHeaderViewHeight && offsetY >0) { CGFloat alpha = (offsetY*2/KTopHeaderViewHeight>0) ? offsetY*2/KTopHeaderViewHeight:0; if (alpha > 0.5) { self.navNewView.alpha = alpha*2-1; self.navView.alpha = 0; } else { self.navNewView.alpha = 0; self.navView.alpha = 1-alpha*2; } self.topHeaderView.alpha = 1-alpha; } } - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { CGFloat offsetY = self.scrollView.contentOffset.y; if (offsetY < - 60) { [self.tableView startPullRefreshing]; } } #pragma mark - UITableViewDataSource - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.dataCount; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CELL"]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CELL"]; } cell.textLabel.text = [NSString stringWithFormat:@"%d",(int)indexPath.row]; return cell; } #pragma mark - getter && setter - (UIScrollView *)scrollView { if (_scrollView == nil) { _scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 64, KScreenWidth, KScreenHeight-64)]; _scrollView.delegate = self; //Indicator的显示位置 _scrollView.scrollIndicatorInsets = UIEdgeInsetsMake(KTopViewHeight, 0, 0, 0); _scrollView.contentSize = CGSizeMake(0, KScreenHeight*2); } return _scrollView; } - (UITableView *)tableView { if (_tableView == nil) { _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, KTopViewHeight, KScreenWidth, KScreenHeight*2-KTopViewHeight)]; _tableView.delegate = self; _tableView.dataSource = self; _tableView.scrollEnabled = NO; } return _tableView; } - (UIView *)topView { if (_topView == nil) { _topView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KTopViewHeight)]; _topView.backgroundColor = [UIColor colorWithRed:66/255.0 green:128/255.0 blue:240/255.0 alpha:1]; UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KTopHeaderViewHeight)]; headerView.backgroundColor = [UIColor colorWithRed:66/255.0 green:128/255.0 blue:240/255.0 alpha:1]; for (int i = 0; i<4; i++) { UIButton *button = [[UIButton alloc] init]; [button setImage:[UIImage imageNamed:[NSString stringWithFormat:@"%d",i+1]] forState:UIControlStateNormal]; [headerView addSubview:button]; button.frame = CGRectMake((KScreenWidth/4)*i, 0, KScreenWidth/4, KTopHeaderViewHeight); } self.topHeaderView = headerView; [_topView addSubview:headerView]; UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, KTopHeaderViewHeight, KScreenWidth, KTopViewHeight-KTopHeaderViewHeight)]; view.backgroundColor = [UIColor brownColor]; [_topView addSubview:view]; } return _topView; } - (UIView *)navBGView { if (_navBGView == nil) { _navBGView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, 64)]; _navBGView.backgroundColor = [UIColor colorWithRed:66/255.0 green:128/255.0 blue:240/255.0 alpha:1]; } return _navBGView; } - (UIView *)navView { if (_navView == nil) { _navView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, 64)]; _navView.backgroundColor = [UIColor clearColor]; UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(10, 20, 200, 44)]; searchBar.backgroundImage = [[UIImage alloc] init]; UITextField *searchField = [searchBar valueForKey:@"searchField"]; if (searchField) { [searchField setBackgroundColor:[UIColor colorWithRed:230/255 green:230/250 blue:230/250 alpha:0.1]]; } [_navView addSubview:searchBar]; UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(220, 20, 44, 44)]; [button setImage:[UIImage imageNamed:@"contacts"] forState:UIControlStateNormal]; [_navView addSubview:button]; } return _navView; } - (UIView *)navNewView { if (_navNewView == nil) { _navNewView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, 64)]; _navNewView.backgroundColor = [UIColor clearColor]; UIButton *cameraBtn = [[UIButton alloc] initWithFrame:CGRectMake(10, 20, 44, 44)]; [cameraBtn setImage:[UIImage imageNamed:@"nav_camera"] forState:UIControlStateNormal]; [_navNewView addSubview:cameraBtn]; UIButton *payBtn = [[UIButton alloc] initWithFrame:CGRectMake(64, 20, 44, 44)]; [payBtn setImage:[UIImage imageNamed:@"nav_pay"] forState:UIControlStateNormal]; [_navNewView addSubview:payBtn]; UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(118, 20, 44, 44)]; [button setImage:[UIImage imageNamed:@"nav_scan"] forState:UIControlStateNormal]; [_navNewView addSubview:button]; _navNewView.alpha = 0; } return _navNewView; } @end ``` ## 项目结构图 ![](/contentImages/image/20180329/OwoRjkYDBInxjjxP52b.png)
本实例支付的费用只是购买源码的费用,如有疑问欢迎在文末留言交流,如需作者在线代码指导、定制等,在作者开启付费服务后,可以点击“购买服务”进行实时联系,请知悉,谢谢
感谢
2
手机上随时阅读、收藏该文章 ?请扫下方二维码
相似例子推荐
评论
作者
Elina
3
例子数量
31
帮助
4
感谢
评分详细
可运行:
4.5
分
代码质量:
4.5
分
文章描述详细:
4.5
分
代码注释:
4.5
分
综合:
4.5
分
作者例子
iOS仿支付宝首页的刷新布局效果
JS与原生OC/Swift相互调用总结
KINavigationController使用演示例子