热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

iosscrollview嵌套tableview同向滑动的示例

我讨论的问题是嵌套同向滑动,能避免尽量避免。最好用一个tableview实现。一个tableview不够用了再嵌套,适用复杂场景。 首先我

我讨论的问题是嵌套同向滑动,能避免尽量避免。最好用一个tableview实现。一个tableview不够用了再嵌套,适用复杂场景。

首先我说下不适用的,免得大家浪费时间。

1.不适用上下拉刷新加载更多的页面。

2.不适用点击cell获取点击事件的页面,可以加入button点击获取事件。

官方文档说尽量不要进行两个竖直或两个水平方向滑动的视图嵌套。因为这个时候机器不知道用户要让哪个滑动,但在我们这个神奇的国度,项目中经常出现这样的需求,产品经理总爱这样做,andriod那边是比较容易实现的,ios这边十分复杂,我研究了一天,写了个demo,可以勉强实现,我的项目中就有上下拉,因此我就硬嵌套了,用户滑动的时候不能准确地按自己的意愿滑动scrollview、tableview。就这样了,这个没有解决方案的。

我做到的效果是手点在哪个视图上,哪个视图就滚动,当小的scroll滚到到自己的临界值就滚动大的scroll,当大的也到临界值就不滚动。顺便实现了一个伪悬浮的secView如果没有那个悬浮的就把那个悬浮高度floatViewHeight置0。剩下的根据页面调整frame即可通用。

这是效果图

下面我说一下在没有以上两点不适用的页面的实现的思路:

Scrollview在控制器的view上,是一个大的视图,tablewview在ScrollView上。根据拖拽手势配合,先判断首先触摸点在哪个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;
// 这个系数根据自己喜好设置大小,=屏幕视图滑动距离/手指滑动距离
#define moveScale 2


@interface ViewController ()
@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";
// 有导航最上部视图是scrollview 内部空间位置会下移,设置这个属性后不下移。
  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;
  
  
  //根据需求设置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的方法,原文件里没有,否则响应链条中断,scroll或tablew的按钮点击事件不执行。
  //这个类原文件继承于UIGestureRecognizer, 改为继承于UIPanGestureRecognizer 否则点击事件不执行。
  //运行效果详见我的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];
  
  //实现手势代理,解决交互冲突
  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已经滑动到了底部
  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已经在最上部了,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之外的区域 只能同过加按钮的方式接受点击事件
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
  NSLog(@"点击了第%ld行",indexPath.row);
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 在现代网络环境中,两台计算机之间的文件传输需求日益增长。传统的FTP和SSH方式虽然有效,但其配置复杂、步骤繁琐,难以满足快速且安全的传输需求。本文将介绍一种基于Go语言开发的新一代文件传输工具——Croc,它不仅简化了操作流程,还提供了强大的加密和跨平台支持。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 网络运维工程师负责确保企业IT基础设施的稳定运行,保障业务连续性和数据安全。他们需要具备多种技能,包括搭建和维护网络环境、监控系统性能、处理突发事件等。本文将探讨网络运维工程师的职业前景及其平均薪酬水平。 ... [详细]
  • 从零开始构建完整手机站:Vue CLI 3 实战指南(第一部分)
    本系列教程将引导您使用 Vue CLI 3 构建一个功能齐全的移动应用。我们将深入探讨项目中涉及的每一个知识点,并确保这些内容与实际工作中的需求紧密结合。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
  • Git管理工具SourceTree安装与使用指南
    本文详细介绍了Git管理工具SourceTree的安装、配置及团队协作方案,旨在帮助开发者更高效地进行版本控制和项目管理。 ... [详细]
  • Python 工具推荐 | PyHubWeekly 第二十一期:提升命令行体验的五大工具
    本期 PyHubWeekly 为大家精选了 GitHub 上五个优秀的 Python 工具,涵盖金融数据可视化、终端美化、国际化支持、图像增强和远程 Shell 环境配置。欢迎关注并参与项目。 ... [详细]
  • 本文基于对相关论文和开源代码的研究,详细介绍了LOAM(激光雷达里程计与建图)的工作原理,并对其关键技术进行了分析。 ... [详细]
  • 构建基于BERT的中文NL2SQL模型:一个简明的基准
    本文探讨了将自然语言转换为SQL语句(NL2SQL)的任务,这是人工智能领域中一项非常实用的研究方向。文章介绍了笔者在公司举办的首届中文NL2SQL挑战赛中的实践,该比赛提供了金融和通用领域的表格数据,并标注了对应的自然语言与SQL语句对,旨在训练准确的NL2SQL模型。 ... [详细]
  • 数据库内核开发入门 | 搭建研发环境的初步指南
    本课程将带你从零开始,逐步掌握数据库内核开发的基础知识和实践技能,重点介绍如何搭建OceanBase的开发环境。 ... [详细]
  • 本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ... [详细]
  • 本文介绍如何使用 Sortable.js 库实现元素的拖拽和位置交换功能。Sortable.js 是一个轻量级、无依赖的 JavaScript 库,支持拖拽排序、动画效果和多种插件扩展。通过简单的配置和事件处理,可以轻松实现复杂的功能。 ... [详细]
  • 深入解析 Spring Security 用户认证机制
    本文将详细介绍 Spring Security 中用户登录认证的核心流程,重点分析 AbstractAuthenticationProcessingFilter 和 AuthenticationManager 的工作原理。通过理解这些组件的实现,读者可以更好地掌握 Spring Security 的认证机制。 ... [详细]
  • 本文介绍如何在现有网络中部署基于Linux系统的透明防火墙(网桥模式),以实现灵活的时间段控制、流量限制等功能。通过详细的步骤和配置说明,确保内部网络的安全性和稳定性。 ... [详细]
  • 对象自省自省在计算机编程领域里,是指在运行时判断一个对象的类型和能力。dir能够返回一个列表,列举了一个对象所拥有的属性和方法。my_list[ ... [详细]
author-avatar
8023pxeb_256
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有