iOS-关于一些手势冲突问题(scrollView 嵌套 tableView)
简单说下关于开发中容易遇到的父试图添加手势与子试图点击事件冲突,UIScrollView 嵌套 UIScrollView 、 UIScrollView 嵌套 UITableView的情况手势冲突问题;
点击冲突
如果给现有的基于 UIView 的 xkTestView 上加一个点击手势 gestTap,然后在 xkTestView 中间区域添加一个 tableview,我们想响应 gestTap,同时也想响应 tableview 的 cell 点击代理事件,这时可以添加 gestTap 点击手势代理:
<UIGestureRecognizerDelegate>
然后在点击事件代理方法中实现
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([NSStringFromClass([touch.view class]) isEqualToString:@"xkTestView"]) {
return YES;
}
return NO;
}
scrollView 嵌套 tableView 类冲突
这里直接用 scrollView 嵌套 tableView 来处理下滑动时的手势冲突问题,其实苹果并不建议我们这样做,但是在实际项目中,有些需求会经常用嵌套来实现,在什么情况下滑动 tableView 不滑动 scrollView,什么情况下滑动 scrollView 不滑动 tableView,其实如果做其他的嵌套都是一样的,先看下最终效果图:

1)首先新建一个基于 UIScrollView 的 XKBaseScrollView ,并实现 <UIGestureRecognizerDelegate> 代理,XKBaseScrollView 用做主父试图来添加子试图内容
XKBaseScrollView.h
#import <UIKit/UIKit.h> @interface XKBaseScrollView : UIScrollView <UIGestureRecognizerDelegate> @end
XKBaseScrollView.m
#import "XKBaseScrollView.h" @implementation XKBaseScrollView //是否支持多时候触发,这里返回YES
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
} @end
2)然后新建一个基于 UITableView 的 XKTargetTableView ,并实现 <UIGestureRecognizerDelegate,UITableViewDelegate,UITableViewDataSource> 代理
XKTargetTableView.h
#import <UIKit/UIKit.h> @interface XKTargetTableView : UITableView
///可否滑动
@property (nonatomic,assign) BOOL canSlide;
///滑动block通知
@property (nonatomic,copy) void (^slideDragBlock)(void);
@end
XKTargetTableView.m
#import "XKTargetTableView.h"
@interface XKTargetTableView ()<UIGestureRecognizerDelegate,UITableViewDelegate,UITableViewDataSource>
@property (nonatomic,assign) CGFloat currOffsetY;
@end
@implementation XKTargetTableView - (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style{
self = [super initWithFrame:frame style:style];
if (self) {
self.backgroundColor = [UIColor whiteColor];
self.delegate = self;
self.dataSource = self;
self.tableFooterView = [UIView new];
[self registerClass:[UITableViewCell class] forCellReuseIdentifier:@"UITableViewCell"];
}
return self;
} //是否支持多时候触发,这里返回YES
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
} #pragma mark ========== tableView 代理 ==========
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return ;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return ;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
cell.textLabel.text = [NSString stringWithFormat:@"%ld",indexPath.row];
return cell;
} #pragma mark ========== scrollview 代理 ==========
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
_currOffsetY = scrollView.contentOffset.y;
} -(void)scrollViewDidScroll:(UIScrollView *)scrollView{
if (!self.canSlide) {
scrollView.contentOffset = CGPointMake(, scrollView.contentOffset.y == ? : _currOffsetY);
}
_currOffsetY = scrollView.contentOffset.y;
if (scrollView.contentOffset.y < ) {
self.canSlide = NO;
scrollView.contentOffset = CGPointZero;
//到顶通知父视图改变状态
if (self.slideDragBlock) {
self.slideDragBlock();
}
}
scrollView.showsVerticalScrollIndicator = self.canSlide ? YES : NO;
}
@end
3)最后在使用的 ViewController 中实现
#import "ViewController.h"
#import <SDAutoLayout.h> #import "XKBaseScrollView.h"
#import "XKTargetTableView.h" @interface ViewController ()<UIScrollViewDelegate>
///容器
@property (nonatomic,strong) XKBaseScrollView *scrollView;
@property (nonatomic,strong) XKTargetTableView *tableView;
///是否可以滑动 scrollView
@property (nonatomic,assign) BOOL canSlide;
@property (nonatomic,assign) CGFloat lastPositionY;
///滑动临界范围值
@property (nonatomic,assign) CGFloat dragCriticalY;
@end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_dragCriticalY = ;
[self.view addSubview:self.scrollView];
self.scrollView.sd_layout.
topSpaceToView(self.view, ).
leftSpaceToView(self.view, ).
rightSpaceToView(self.view, ).
bottomSpaceToView(self.view, ); [self.scrollView setupAutoContentSizeWithBottomView:self.tableView bottomMargin:];
__weak __typeof__(self) weekSelf = self;
self.tableView.slideDragBlock = ^{
weekSelf.canSlide = YES;
weekSelf.tableView.canSlide = NO;
}; } -(void)scrollViewDidScroll:(UIScrollView *)scrollView{
CGFloat currentPostion = scrollView.contentOffset.y;
/*
当 底层滚动式图滚动到指定位置时,
停止滚动,开始滚动子视图
*/
if (currentPostion >= self.dragCriticalY) {
scrollView.contentOffset = CGPointMake(, self.dragCriticalY);
if (self.canSlide) {
self.canSlide = NO;
self.tableView.canSlide = YES;
}
else{
if (_lastPositionY - currentPostion > ){
if (self.tableView.contentOffset.y > ) {
self.tableView.canSlide = YES;
self.canSlide = NO;
}
else{
self.tableView.canSlide = NO;
self.canSlide = YES;
}
}
}
}else{
if (!self.canSlide && scrollView.contentOffset.y == self.dragCriticalY ) {
scrollView.contentOffset = CGPointMake(, self.dragCriticalY);
}
else{
if (self.tableView.canSlide &&
self.tableView.contentOffset.y != ) {
scrollView.contentOffset = CGPointMake(, self.dragCriticalY);
}
else{ }
}
} _lastPositionY = currentPostion;
} - (XKBaseScrollView *)scrollView{
if (!_scrollView) {
_scrollView = [[XKBaseScrollView alloc]init];
_scrollView.showsVerticalScrollIndicator = NO; _scrollView.delegate = self;
_scrollView.backgroundColor = [UIColor redColor];
UIView *view = [[UIView alloc]init];
view.backgroundColor = [UIColor blueColor]; [_scrollView addSubview:view];
view.sd_layout.
topSpaceToView(_scrollView, ).
leftSpaceToView(_scrollView, ).
rightSpaceToView(_scrollView, ).
heightIs(); [_scrollView addSubview:self.tableView];
self.tableView.sd_layout.
topSpaceToView(view, ).
leftSpaceToView(_scrollView, ).
rightSpaceToView(_scrollView, ).
heightIs(self.view.bounds.size.height - ( - self.dragCriticalY));
}
return _scrollView;
}
- (XKTargetTableView *)tableView{
if(!_tableView){
_tableView = [[XKTargetTableView alloc]initWithFrame:CGRectZero style:UITableViewStylePlain];
}
return _tableView;
}
@end
注:此 demo 需引用 SDAutoLayout
iOS-关于一些手势冲突问题(scrollView 嵌套 tableView)的更多相关文章
- scrollview嵌套tableview
之前写过一次,忘记了, 用的通知 FS
- iOS LeftMenu抽屉效果与ScrollView共存时的手势冲突
公司有个项目,需要做左侧滑动,首页是ScrollView嵌套TableView.首页是一个ScrollView,所以当contentOffset是0.0的时候,无法直接滑动出抽屉效果,用户体验感非常差 ...
- 当ViewPager嵌套在ScrollView/ListView里时,手势冲突如何处理?
有时我们需要将ViewPager嵌套在其他已经含有手势动作的ViewGroup里,如ScrollView,ListView时,会造成手势冲突,如表现为ViewPager向左划时,不小心向上移动了一点距 ...
- 解决嵌套在ScrollView中的TableView滑动手势冲突问题
最近在迭代开发公司项目的时候遇到了一个问题,在可以左右切换标签视图的ScrollView中嵌套了两个TableView用于展示视图,感觉一切so easy的情况下,问题出现了,因为左右两个视图既可以实 ...
- (转)ViewPager,ScrollView 嵌套ViewPager滑动冲突解决
ViewPager,ScrollView 嵌套ViewPager滑动冲突解决 本篇主要讲解一下几个问题 粗略地介绍一下View的事件分发机制 解决事件滑动冲突的思路及方法 ScrollView 里面嵌 ...
- 解决ScrollView嵌套ViewPager出现的滑动冲突问题
/** * 解决ScrollView嵌套ViewPager出现的滑动冲突问题 */ public class ScrollView1 extends ...
- iOS手势冲突问题
今天在做一个效果的时候,由于子视图和父视图都有响应的事件,子视图的事件理所当然被父视图拦截掉了,接下来就做分析解决 1. tableviewcell可以触发点击,同时tableview的父视图有点击 ...
- 解决iOS手势冲突问题
今天在做一个效果的时候,由于子视图和父视图都有响应的事件,子视图的事件理所当然被父视图拦截掉了,接下来就做分析解决 1. tableviewcell可以触发点击,同时tableview的父视图有点击 ...
- Android——MeasureSpec学习 - 解决ScrollView嵌套ListView和GridView冲突的方法
原文地址:http://blog.csdn.net/yuhailong626/article/details/20639217 在自定义View和ViewGroup的时候,我们经常会遇到int ...
随机推荐
- 如何遍历newtonsoft.json的JObject里的JSON数据
这种问题,在网上搜,居然没有答案,又是一堆垃圾,连谷歌上都搜不到.老实说,我喜欢这边的工作环境,可以上谷歌,毕竟是大公司,有自己的VPN .某组织整天禁这个禁那个,去年居然连谷歌都禁了,丧心病狂至此, ...
- 【bzoj2003】[Hnoi2010]Matrix 矩阵
首先可以知道,如果已知第一行和第一列的数,那么可以很容易的计算出其余的数.进一步的,如果笔算将每个数的表达式写出可以得出如下结论: 第i行的第j个数(i>1,j>1)只与(1,1),(i, ...
- beego2---入门
package main //beego既可以建立web应用也可以建立api应用 //beego是一个gohttp服务器的高层封装, import ( _ "beego1/routers&q ...
- update-java-alternatives 更改默认Java环境
Ubuntu/debian 更改默认Java环境 我的电脑里安装了两个版本的Java,一个是java-6-sun,还有一个是java-gcjgcj是在JVM非常缓慢的时候诞生的,他可以把Java代码编 ...
- 转贴:获取元素CSS值之getComputedStyle方法熟悉
获取元素CSS值之getComputedStyle方法熟悉 一.碎碎念~前言 我们都用过jQuery的CSS()方法,其底层运作就应用了getComputedStyle以及getPropertyVal ...
- MySQL基础 — 详细安装
MySQL--安装 打开MySQL 5.5 安装文件开始: 点击Next 打上勾,再点击Next 点击Custom,说明如下: Typical(典型安装) Installs the mo ...
- bzoj 1618: [Usaco2008 Nov]Buying Hay 购买干草【背包】
好像是完全背包吧分不清了-- 好像是把数组二维压一维的时候,01背包倒序,完全背包正序 ```cpp include include using namespace std; const int N= ...
- P3482 [POI2009]SLO-Elephants
传送门 首先,交换关系肯定是构成一个环的时候最优 如果这个环是自环,不用交换了 如果环的大小为2,直接交换便是 否则的话,我们可以用环里最小的点最为交换媒介,然后去和其他交换直到到达正确的位置,那么环 ...
- 数据结构之单链表(C实现)
list.h #ifndef LIST_H #define LIST_H #include <iostream> #include <stdio.h> #include < ...
- 思维/构造 HDOJ 5353 Average
题目传送门 /* 思维/构造:赛后补的,当时觉得3题可以交差了,没想到这题也是可以做的.一看到这题就想到了UVA_11300(求最小交换数) 这题是简化版,只要判断行不行和行的方案就可以了,做法是枚举 ...