多层Scrollview
嵌套 【scroll顶部刷新】
底部是一个
scrllview
,子类是collectionview
,要求向上滑动的时候scrllview
和collectionview
可以做到连续滑动
约定: 底部ScollView
我们称之为MainScroll
,子类CollectionView
称之为SubCollectionView
首先我们写一个ScrollView
的基类
@interface RKScrollView : UIScrollView<UIGestureRecognizerDelegate>
@end
@implementation HoverPageScrollView
- (BOOL)touchesShouldCancelInContentView:(UIView *)view{
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
@end
MainScrollView
继承RKScrollView
//注意这里父类有个属性_canScroll默认设置为YES
_canScroll = YES;
_mainScrollview = [[RKScrollView alloc]initWithFrame:CGRectMake(0, 0, _window_width, _window_height-78-statusbarHeight-ShowDiff-49)];
_mainScrollview.backgroundColor = [UIColor whiteColor];
_mainScrollview.contentSize = CGSizeMake(0, _mainScrollview.height+400);
//重要属性【如果需要下拉刷新可在didscroll代理中更改此属性】
_mainScrollview.bounces = NO;
ybWeakSelf;
MJRefreshNormalHeader *mjheader= [MJRefreshNormalHeader headerWithRefreshingBlock:^{
[weakSelf mainScrollRefresh];
}];
_mainScrollView.mj_header = mjheader;
mjheader.stateLabel.textColor = [UIColor whiteColor];
mjheader.lastUpdatedTimeLabel.textColor = [UIColor whiteColor];
mjheader.loadingView.color = [UIColor whiteColor];
_mainScrollview.delegate = self;
_mainScrollview.scrollViewWhites = [NSMutableArray array];
[self.view addSubview:_mainScrollview];
-(void)mainScrollRefresh {
_friendView.pageing = 1;
[_friendView pullData:YES];
_voiceView.pageing = 1;
[_voiceView pullData:YES];
}
-(void)mainScrollEndfresh {
[_mainScrollView.mj_header endRefreshing];
}
MainScrollview
代理方法中的实现
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
//MainScrollview不需要刷新这里可不做处理
if (scrollView == _mainScrollview){
if (scrollView.contentOffset.y <= 0) {
_mainScrollview.bounces = YES;
subCollectionView.bounces = NO;
}else{
_mainScrollview.bounces = NO;
subCollectionView.bounces = YES;
}
}
CGFloat bottomCellOffset = tableHeaderView.height-40;//这里高度设置为头部视图高度即可
if (scrollView.contentOffset.y >= bottomCellOffset) {
scrollView.contentOffset = CGPointMake(0, bottomCellOffset);
if (_canScroll) {
_canScroll = NO;
subCollectionView.canScroll = YES;
}
}else{
if (!_canScroll) {//子视图没到顶部
scrollView.contentOffset = CGPointMake(0, bottomCellOffset);
}
}
_mainScrollview.showsVerticalScrollIndicator = _canScroll?YES:NO;
}
- (void)changeScrollStatus {
_canScroll = YES;
// 重要:子视图一定是canScroll = NO
subCollectionView.canScroll = NO;
}
子类subCollectionView
/// 嵌套滚动代理
@protocol MutElementScrollDelegate <NSObject>
-(void)changeScrollStatus;
@end
// 子视图属性
@property(nonatomic,assign)BOOL canScroll;
@property(nonatomic,assign)BOOL subBounces;
@property(nonatomic,weak)id <MutElementScrollDelegate>delegate;
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
if (!_canScroll) {
scrollView.contentOffset = CGPointZero;
}
if (scrollView.contentOffset.y <= 0) {
_canScroll = NO;
scrollView.contentOffset = CGPointZero;
//这里就是通知父类改变父类的canScroll属性
if (_delegate && [_delegate respondsToSelector:@selector(changeScrollStatus)]) {
[_delegate changeScrollStatus];
}
}
_subCollectionView.showsVerticalScrollIndicator = _canScroll?YES:NO;
}
// bounces
- (void)setSubBounces:(BOOL)subBounces {
_subBounces = subBounces;
_tableView.bounces = _subBounces;
}
仿支付宝首页刷新【tableview刷新】
完整代码
#import "TBRefreshVC.h"
#import <MJRefresh.h>
#define KScreenWidth [UIScreen mainScreen].bounds.size.width
#define KScreenHeight [UIScreen mainScreen].bounds.size.height
#define KTopViewHeight 300
#define KTopHeaderViewHeight 80
@interface TBRefreshVC ()<UITableViewDelegate,UITableViewDataSource>
@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 TBRefreshVC
- (void)dealloc {
[self removeObserver:self forKeyPath:@"contentSize"];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationController.navigationBar.hidden = YES;
[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];
//添加刷新控件
__weak TBRefreshVC *weakSelf = self;
self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[weakSelf.tableView.mj_header endRefreshing];
weakSelf.dataCount += 5;
[weakSelf.tableView reloadData];
});
}];
self.scrollView.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingBlock:^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[weakSelf.scrollView.mj_footer endRefreshing];
weakSelf.dataCount += 5;
[weakSelf.tableView reloadData];
});
}];
[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<NSKeyValueChangeKey,id> *)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 - 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.mj_header 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.mj_header beginRefreshing];
}
}
#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.grayColor;
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KTopHeaderViewHeight)];
headerView.backgroundColor = UIColor.blackColor;
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 systemPinkColor];
[_topView addSubview:view];
}
return _topView;
}
- (UIView *)navBGView {
if (_navBGView == nil) {
_navBGView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, 64)];
_navBGView.backgroundColor = UIColor.yellowColor;
}
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];
cameraBtn.backgroundColor = UIColor.redColor;
[_navNewView addSubview:cameraBtn];
UIButton *payBtn = [[UIButton alloc] initWithFrame:CGRectMake(64, 20, 44, 44)];
[payBtn setImage:[UIImage imageNamed:@"nav_pay"] forState:UIControlStateNormal];
payBtn.backgroundColor = UIColor.greenColor;
[_navNewView addSubview:payBtn];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(118, 20, 44, 44)];
[button setImage:[UIImage imageNamed:@"nav_scan"] forState:UIControlStateNormal];
button.backgroundColor = UIColor.blueColor;
[_navNewView addSubview:button];
_navNewView.alpha = 0;
}
return _navNewView;
}
@end