UITableview的滑动监听
2021-08-19 本文已影响0人
数字d
需求:
总共有两个View,ViewA和ViewB,当ViewA的frame发生了变化,B的frame也可以发生响应的变化.
这个功能点通过Masonry来实现,这里不做赘述.
下面说下系统提供的解决办法:
1.监听view的frame
[self.view addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil];
2.view的frame发生变化时候的回调
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
NSLog(@"滚动了tableview");
if ([keyPath isEqualToString:@"frame"]) {
CGPoint offset = [change[NSKeyValueChangeNewKey] CGPointValue];
}
}
3.移除监听
[self.view removeObserver:self forKeyPath:@"frame"];
实际在项目中的应用
一个scrollview上叠加一个tableView需求,scrollview的头部是一个View,用户点击一些操作之后,这个view的frame会增加或者减少(这里仅仅指高度),tableView在scrollview上,底部和scrollview对齐.
网上搜了大多数答案都是说要监听scrollview的contentOffset的值,来控制tableview和scrollview的的滑动事件.
网上搜索的几乎所有的实现都不包含tableview的下拉刷新功能.
所以最后找了个demo换了一种思路来实现
效果见
1.gif
1.将scrollview替换成view.给头部的view添加上拉手势,如果上拉就将tableview,contentoffset设置为上拉后的效果
2.tableview的contenteoffset效果监听
具体代码实现vc.m
#import "ViewController.h"
#import "Masonry.h"
#import "PinkViewCtl.h"
#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width)
#define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height)
@interface ViewController ()<UIScrollViewDelegate>
@property(nonatomic,strong)UIView * bgScrollView;
@property(nonatomic,strong)UIView * yzclientZBView;
@property(nonatomic,strong)UIView * tabBgView;
@property(nonatomic,strong)PinkViewCtl * vc;
@property(nonatomic,assign)CGFloat greenHeight;
@property(nonatomic,assign)CGFloat redheight;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.greenHeight = 220;
self.redheight = 200;
self.view.backgroundColor = [UIColor whiteColor];
UIView * greenView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, _greenHeight)];
greenView.backgroundColor = [UIColor greenColor];
[self.view addSubview:greenView];
[self.view addSubview:self.bgScrollView];
self.vc = [[PinkViewCtl alloc] init];
[self addChildViewController:self.vc];
[self.tabBgView addSubview:self.vc.view];
[self.vc.view mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.top.bottom.equalTo(self.tabBgView);
}];
[self.vc.tableView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
//
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
NSLog(@"滚动了tableview");
if ([keyPath isEqualToString:@"contentOffset"]) {
CGPoint offset = [change[NSKeyValueChangeNewKey] CGPointValue];
NSLog(@"滚动的offset.y = %f",offset.y);
if (offset.y < 0) {
self.yzclientZBView.frame = CGRectMake(0, 0, SCREEN_WIDTH, _redheight);
self.yzclientZBView.hidden = NO;
self.tabBgView.frame = CGRectMake(0, _redheight, self.bgScrollView.frame.size.width, self.bgScrollView.frame.size.height - _redheight);
}else if(offset.y == 0){
self.yzclientZBView.frame = CGRectMake(0, 0, SCREEN_WIDTH, _redheight);
self.yzclientZBView.hidden = NO;
self.tabBgView.frame = CGRectMake(0, _redheight, self.bgScrollView.frame.size.width, self.bgScrollView.frame.size.height - _redheight);
}else if (offset.y > 0){
self.yzclientZBView.hidden = YES;
self.tabBgView.frame = CGRectMake(0, 0, self.bgScrollView.frame.size.width, self.bgScrollView.frame.size.height);
self.vc.view.frame = self.tabBgView.frame;
self.vc.tableView.frame = self.tabBgView.frame;
}
}
}
-(UIView *)bgScrollView {
if (_bgScrollView == nil) {
_bgScrollView = [[UIView alloc] initWithFrame:CGRectMake(0, _redheight, SCREEN_WIDTH, SCREEN_HEIGHT - _greenHeight)];
_bgScrollView.backgroundColor = [UIColor yellowColor];
[_bgScrollView addSubview:self.yzclientZBView];
[_bgScrollView addSubview:self.tabBgView];
[_tabBgView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.yzclientZBView.mas_bottom);
make.left.equalTo(self.yzclientZBView.mas_left);
make.height.equalTo(@(SCREEN_HEIGHT - _redheight - _redheight));
make.width.equalTo(@(SCREEN_WIDTH));
}];
}
return _bgScrollView;
}
-(UIView *)yzclientZBView {
if (_yzclientZBView == nil) {
_yzclientZBView = [[UIView alloc] init];
_yzclientZBView.backgroundColor = [UIColor redColor];
UISwipeGestureRecognizer *recognizer;
recognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleSwipeFrom:)];
[recognizer setDirection:(UISwipeGestureRecognizerDirectionUp)];
[[self view] addGestureRecognizer:recognizer];
}
return _yzclientZBView;
}
-(void)handleSwipeFrom:(UISwipeGestureRecognizer *)recognizer{
if(recognizer.direction==UISwipeGestureRecognizerDirectionDown) {
NSLog(@"swipe down");
//执行程序
}
if(recognizer.direction==UISwipeGestureRecognizerDirectionUp) {
NSLog(@"swipe up");
//执行程序
self.vc.tableView.contentOffset = CGPointMake(0, 100);
}
if(recognizer.direction==UISwipeGestureRecognizerDirectionLeft) {
NSLog(@"swipe left");
//执行程序
}
if(recognizer.direction==UISwipeGestureRecognizerDirectionRight) {
NSLog(@"swipe right");
//执行程序
}
}
-(UIView *)tabBgView {
if (_tabBgView == nil) {
_tabBgView = [[UIView alloc] init];
_tabBgView.backgroundColor = [UIColor blueColor];
}
return _tabBgView;
}
@end
pinkvc.m
#import "PinkViewCtl.h"
#import "Masonry.h"
#import "MJRefresh.h"
@interface PinkViewCtl ()<UITableViewDelegate,UITableViewDataSource,UIScrollViewDelegate>
@property(nonatomic,strong)NSMutableArray * testArray;
@property(nonatomic,assign)BOOL canMove;
@end
@implementation PinkViewCtl
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor systemPinkColor];
self.testArray = [NSMutableArray arrayWithArray:@[
@"need1",
@"need2",
@"need3",
@"need4",
@"need5",
@"need6",
@"need7",
@"need8",
@"need1",
@"need2",
@"need3",
@"need4",
@"need5",
@"need6",
@"need7",
@"need8",
@"need1",
@"need2",
@"need3",
@"need4",
@"need5",
@"need6",
@"need7",
@"need8",
@"need1",
@"need2",
@"need3",
@"need4",
@"need5",
@"need6",
@"need7",
@"need8",
]];
[self.view addSubview:self.tableView];
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.top.bottom.equalTo(self.view);
}];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(acceptMsg:) name:@"kHomeGoTopNotification" object:nil];
}
-(UITableView *)tableView {
if (_tableView == nil) {
_tableView = [[UITableView alloc] initWithFrame:CGRectZero style:(UITableViewStylePlain)];
_tableView.dataSource = self;
_tableView.delegate = self;
_tableView.rowHeight = 70;
_tableView.backgroundColor = [UIColor groupTableViewBackgroundColor];
[_tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
_tableView.showsVerticalScrollIndicator = NO;
}
return _tableView;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.testArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell * cell = [[UITableViewCell alloc] init];
cell.textLabel.text = @"neeed";
return cell;
}
#pragma mark - UIScrollViewDelegate
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end
功能实现中有的瑕疵是:当头部view监听到了上拉手势的时候,对tableview进行上拉,这个过程不够平滑