ios scrollview嵌套tableview同向滑動的示例
我討論的問題是嵌套同向滑動,能避免盡量避免。最好用一個tableview實現(xiàn)。一個tableview不夠用了再嵌套,適用復(fù)雜場景。
首先我說下不適用的,免得大家浪費時間。
1.不適用上下拉刷新加載更多的頁面。
2.不適用點擊cell獲取點擊事件的頁面,可以加入button點擊獲取事件。
官方文檔說盡量不要進行兩個豎直或兩個水平方向滑動的視圖嵌套。因為這個時候機器不知道用戶要讓哪個滑動,但在我們這個神奇的國度,項目中經(jīng)常出現(xiàn)這樣的需求,產(chǎn)品經(jīng)理總愛這樣做,andriod那邊是比較容易實現(xiàn)的,ios這邊十分復(fù)雜,我研究了一天,寫了個demo,可以勉強實現(xiàn),我的項目中就有上下拉,因此我就硬嵌套了,用戶滑動的時候不能準確地按自己的意愿滑動scrollview、tableview。就這樣了,這個沒有解決方案的。
我做到的效果是手點在哪個視圖上,哪個視圖就滾動,當(dāng)小的scroll滾到到自己的臨界值就滾動大的scroll,當(dāng)大的也到臨界值就不滾動。順便實現(xiàn)了一個偽懸浮的secView如果沒有那個懸浮的就把那個懸浮高度floatViewHeight置0。剩下的根據(jù)頁面調(diào)整frame即可通用。
這是效果圖

下面我說一下在沒有以上兩點不適用的頁面的實現(xiàn)的思路:
Scrollview在控制器的view上,是一個大的視圖,tablewview在ScrollView上。根據(jù)拖拽手勢配合,先判斷首先觸摸點在哪個view上,再對哪個view滑動操作。解決手勢和button點擊沖突。下面看代碼,注釋十分清晰。github有demo,歡迎閱讀: https://github.com/qingyindaoren/ScrollInsetTable.git
核心代碼如下:
#import "ViewController.h"
#import "YYGestureRecognizer.h"
#import "ScrollTableViewCell.h"
#import "MBProgressHUD+Add.h"
#define ScreenWidth [UIScreen mainScreen].bounds.size.width
#define ScreenHeight [UIScreen mainScreen].bounds.size.height
//虛假的懸浮效果
static CGFloat floatViewHeight = 30.0;
static CGFloat navHeitht = 64;
// 這個系數(shù)根據(jù)自己喜好設(shè)置大小,=屏幕視圖滑動距離/手指滑動距離
#define moveScale 2
@interface ViewController ()<UITableViewDelegate,UITableViewDataSource,UIGestureRecognizerDelegate>
@property (nonatomic,weak)UIScrollView *scroll;
@property (nonatomic, strong) NSArray *titles;
@property (nonatomic,weak)UITableView *insetTableView;
@property (nonatomic,assign)CGFloat tableY;
@property (nonatomic,assign)CGFloat tableStartY;
@property (nonatomic,assign)CGFloat scrollY;
@property (nonatomic,assign)CGFloat scrollStartY;
//tableview 的y值 在scrollview中的位置
@property (nonatomic,assign)CGFloat tableFrameY;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"ScrollScroll";
// 有導(dǎo)航最上部視圖是scrollview 內(nèi)部空間位置會下移,設(shè)置這個屬性后不下移。
if ([self respondsToSelector:@selector(setAutomaticallyAdjustsScrollViewInsets:)]) {
self.automaticallyAdjustsScrollViewInsets = NO;
}
UIScrollView *scroll = [[UIScrollView alloc]initWithFrame:CGRectMake(0,navHeitht, ScreenWidth, ScreenHeight-navHeitht)];
scroll.backgroundColor = [UIColor colorWithRed:0.4 green:0.3 blue:0.2 alpha:1.0];;
[self.view addSubview:scroll];
self.scroll = scroll;
//根據(jù)需求設(shè)置tableview的y值 暫寫scroll高的2分之一
self.tableFrameY = self.scroll.frame.size.height/2;
UIImageView *headImage = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, ScreenWidth, self.tableFrameY-floatViewHeight)];
headImage.image = [UIImage imageNamed:@"scrollHead"];
headImage.contentMode = UIViewContentModeScaleAspectFill;
[self.scroll addSubview:headImage];
NSArray *titles = @[@"ICO詳情",@"央行放大招",@"比特幣會漲",@"神秘中本村"];
self.titles = titles;
UISegmentedControl *segment = [[UISegmentedControl alloc] initWithFrame:CGRectMake(5, scroll.bounds.size.height/2-30, self.scroll.bounds.size.width - 10, 30)];
[segment addTarget:self action:@selector(segmentValueChanged:) forControlEvents:UIControlEventValueChanged];
for (NSString *title in _titles) {
[segment insertSegmentWithTitle:title atIndex:segment.numberOfSegments animated:false];
}
segment.selectedSegmentIndex = 0;
[self.scroll addSubview:segment];
UITableView *insetTable = [[UITableView alloc]initWithFrame:CGRectMake(0,self.tableFrameY, self.view.bounds.size.width, ScreenHeight-navHeitht-floatViewHeight)];
insetTable.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1.0];
insetTable.dataSource = self;
insetTable.delegate = self;
[self.scroll addSubview:insetTable];
self.insetTableView = insetTable;
//github搜索 yykit 或yytext 里面有 yygestureRecognizer這個類,這個類需要做一些修改, // 在yygesture中所有觸摸事件方法里 加上super的方法,原文件里沒有,否則響應(yīng)鏈條中斷,scroll或tablew的按鈕點擊事件不執(zhí)行。
//這個類原文件繼承于UIGestureRecognizer, 改為繼承于UIPanGestureRecognizer 否則點擊事件不執(zhí)行。
//運行效果詳見我的demo
YYGestureRecognizer *yyges = [YYGestureRecognizer new];
yyges.action = ^(YYGestureRecognizer *gesture, YYGestureRecognizerState state){
if (state != YYGestureRecognizerStateMoved) return ;
if (CGRectContainsPoint(self.insetTableView.frame, gesture.startPoint)) {
//滑動tableview
[self tableScrollWithGesture:gesture];
}else{
//滑動scrollview
[self scrollScrollWithGesture:gesture];
}
};
//必須給scroll 加上手勢 不要給view加,不然滑動tablew的時候會錯誤判斷去滑動scroll。
[self.scroll addGestureRecognizer:yyges];
//實現(xiàn)手勢代理,解決交互沖突
yyges.delegate = self;
scroll.contentSize = CGSizeMake(self.view.bounds.size.width, self.tableFrameY+self.insetTableView.frame.size.height);
}
//解決手勢按鈕沖突
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
//如果是 segment或scroll上的其他按鈕,取消手勢
if([NSStringFromClass(touch.view.superclass) isEqualToString:@"UIControl"]){
return NO;
}
//
return YES;
}
//
- (void)segmentValueChanged:(UISegmentedControl *)segment {
//scroll 到底部
CGFloat offset = self.scroll.contentSize.height - self.insetTableView.bounds.size.height-floatViewHeight;
if (offset > 0)
{
self.scrollY = offset;
[self.scroll setContentOffset:CGPointMake(0, offset) animated:YES];
}
//TableView到頂部
self.tableY = 0;
[self.insetTableView setContentOffset:CGPointMake(0, self.tableY) animated:YES];
}
- (void)tableScrollWithGesture:(YYGestureRecognizer *)gesture{
CGFloat scrolly;
if (self.tableStartY != gesture.startPoint.y) {
scrolly = -(gesture.currentPoint.y-gesture.startPoint.y) ;
}else{
scrolly = -(gesture.currentPoint.y-gesture.lastPoint.y) ;
}
self.tableStartY = gesture.startPoint.y;
self.tableY += scrolly*moveScale;
//為了顯示底部超出屏幕的tableview那部分 滑動scrollview 此時tablewview已經(jīng)滑動到了底部
if (self.tableY> self.insetTableView.contentSize.height-self.insetTableView.bounds.size.height){
self.scrollY += self.tableY-(self.insetTableView.contentSize.height-self.insetTableView.bounds.size.height);
//tablewview滑動到底部就不要滑了
self.tableY = self.insetTableView.contentSize.height-self.insetTableView.bounds.size.height;
//scrollview 滑動到了底部就不要滑動了
if (self.scrollY> self.scroll.contentSize.height-self.insetTableView.bounds.size.height-floatViewHeight){
self.scrollY = self.scroll.contentSize.height-self.insetTableView.bounds.size.height-floatViewHeight;
//如果scrollview意外的contentsize 小于自己的大小,scrollview就不要滑了
if (self.scrollY<0) {
self.scrollY = 0;
}
}
[self.scroll setContentOffset:CGPointMake(0, self.scrollY) animated:YES];
//如果tablewview的cell過少或行高過少致使其contentsize 小于自己的大小,tableview就不要滑了
if (self.tableY<0) {
self.tableY = 0;
}
}
//如果滑到了tableview的最上部,停止滑動tablewview, 如果此時scrollview 沒有在最上部就滑動scrollview到最上部
if (self.tableY<0){
self.scrollY += self.tableY;
//scroll已經(jīng)在最上部了,scroll就不滑了
if (self.scrollY<0) {
self.scrollY = 0;
}
NSLog(@"scroll %lf",self.scrollY);
[self.scroll setContentOffset:CGPointMake(0, self.scrollY) animated:YES];
//停止滑動tablewview
self.tableY = 0;
}
NSLog(@"table %lf",self.tableY);
[self.insetTableView setContentOffset:CGPointMake(0, self.tableY) animated:YES];
}
- (void)scrollScrollWithGesture:(YYGestureRecognizer *)gesture{
CGFloat scrolly;
if (self.scrollStartY != gesture.startPoint.y) {
scrolly = -(gesture.currentPoint.y-gesture.startPoint.y) ;
}else{
scrolly = -(gesture.currentPoint.y-gesture.lastPoint.y) ;
}
self.scrollStartY = gesture.startPoint.y;
self.scrollY += scrolly*moveScale;
//如果滑到了scroll的底部就不要滑了
if (self.scrollY> self.scroll.contentSize.height-self.insetTableView.bounds.size.height-floatViewHeight){
self.scrollY = self.scroll.contentSize.height-self.insetTableView.bounds.size.height-floatViewHeight;
//如果scrollview意外的contentsize 小于自己的大小,scrollview就不要滑了
if (self.scrollY<0) {
self.scrollY = 0;
}
}
//如果滑到了scroll頂部就不要滑了
if (self.scrollY<0){
self.scrollY = 0;
}
NSLog(@"scroll %lf",self.scrollY);
[self.scroll setContentOffset:CGPointMake(0, self.scrollY) animated:YES];
}
#pragma mark - 展示tableview的代理
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 70;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ScrollTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"ScrollTableViewCell"];
if (!cell)
{
[tableView registerNib:[UINib nibWithNibName:@"ScrollTableViewCell" bundle:nil] forCellReuseIdentifier:@"ScrollTableViewCell"];
cell = [tableView dequeueReusableCellWithIdentifier:@"ScrollTableViewCell"];
}
cell.backgroundColor = [UIColor clearColor];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.Titletext.text = [NSString stringWithFormat:@"\t第%zd行",indexPath.row];
cell.detailText.text = @"滑屏呀滑屏呀劃呀";
cell.detailText.textColor = self.navigationController.navigationBar.tintColor;
cell.indexPath = indexPath;
cell.selectCellBlock = ^(NSIndexPath *indexPath) {
NSString *tip = [NSString stringWithFormat:@"點擊了第%ld組%ld行",indexPath.section,indexPath.row];;
[MBProgressHUD showMessage:tip view:nil];
NSLog(@"%@",tip);
};
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 3;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
UIView *v = [[UIView alloc]initWithFrame:CGRectMake(0, 0, ScreenWidth, 50)];
v.backgroundColor = [UIColor orangeColor];
UILabel *l = [[UILabel alloc]initWithFrame:v.bounds];
l.text =[NSString stringWithFormat:@"tableview的組頭%ld",section];
l.textColor = [UIColor whiteColor];
l.textAlignment = NSTextAlignmentCenter;
[v addSubview:l];
return v;
}
//組頭高
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
return 50;
}
//這個方法不可用了,除非點擊了cellcontenview之外的區(qū)域 只能同過加按鈕的方式接受點擊事件
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(@"點擊了第%ld行",indexPath.row);
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
iOS開發(fā)中TabBar再次點擊實現(xiàn)刷新效果
這篇文章主要介紹了iOS開發(fā)中TabBar再次點擊實現(xiàn)刷新效果,實現(xiàn)方法也很簡單,需要的朋友可以參考下2018-04-04
iOS App中調(diào)用iPhone各種感應(yīng)器的方法總結(jié)
Xcode環(huán)境中包含CoreMotion框架,能夠幫助我們調(diào)用硬件設(shè)備的加速度傳感器和陀螺儀等感應(yīng)器,下面比較詳細地整理了iOS App中調(diào)用iPhone各種感應(yīng)器的方法總結(jié),需要的朋友可以參考下:2016-07-07

