iOS ScrollView嵌套ScrolloView解决方案 - Swift

iOS_NestedScrollView(嵌套ScrollView) nested scrollView swift 实现 阅读详情

iOS ScrollView嵌套ScrolloView解决方案 - Swift

 
 
 

1. 基础版实现思路

1.1:层次结构

底部是一个UITableView,上面黄色部分为tableView的tableHeaderView,cell的数量为1,cell的contentView上防止了一个LTPageView, pageView上放置了一个scrollView且可以左右滑动分页,scrollView上放置控制器view,控制器view上放置各自的scrollView(tableView或collectionView)

1.2:使用方法(具体查看Demo)

(1)创建LTSimpleMabager,并添加到视图,传入frame,子控制器数组,标题数组,当前的控制器以及pageView的样式设置

LTSimpleManager(frame: <#T##CGRect#>, viewControllers: <#T##[UIViewController]#>, titles: <#T##[String]#>, currentViewController: <#T##UIViewController#>, layout: <#T##LTLayout#>)

(2)初始化子控制器的scrollView(tableView或collectionView),且tableView的y值从pageTitleView的高度开始,Demo中为44,具体可根据产品需求而定,tableView的height则为父view的高减去44

(3)将子控制器的scrollView(tableView或collectionView)赋值给glt_scollView即glt_scrollView = tableView,以下会说明原因。

1.3:实现思路

(1)当滑动底部tableView的时候,当tableView的contentOffset.y 小于 header的高的时候,将内容ScrollView的contentOffset设置为.zero

private func contentScrollViewScrollConfig(_ viewController: UIViewController) {
        viewController.glt_scrollView?.scrollHandle = {[weak self] scrollView in
            guard let `self` = self else { return }
            self.contentTableView = scrollView
            if self.tableView.contentOffset.y < self.kHeaderHeight {
                scrollView.contentOffset = .zero;
                scrollView.showsVerticalScrollIndicator = false
            }else{
                scrollView.showsVerticalScrollIndicator = true
            }
        }
    }

(2)当滑动内容ScrollView的时候, 当内容contentOffset.y 大于 0(说明滑动的是内容ScrollView) 或者 当底部tableview的contentOffset.y大于 header的高度的时候,将底部tableView的偏移量设置为kHeaderHeight, 并将其他的scrollView的contentOffset置为.zero

public func scrollViewDidScroll(_ scrollView: UIScrollView) {
        guard scrollView == tableView, let contentTableView = contentTableView else { return }
        let offsetY = scrollView.contentOffset.y
        if contentTableView.contentOffset.y > 0.0 || offsetY > kHeaderHeight {
            tableView.contentOffset = CGPoint(x: 0.0, y: kHeaderHeight)
        }
        if scrollView.contentOffset.y < kHeaderHeight {
            for viewController in viewControllers {
                guard viewController.glt_scrollView != scrollView else { continue }
                viewController.glt_scrollView?.contentOffset = .zero
            }
        }
    }

 

(3)headerView添加以及各个点击事件回调处理。

simpleManager.configHeaderView {[weak self] in
            guard let strongSelf = self else { return nil }
            let headerView = strongSelf.testLabel()
            return headerView
        }
simpleManager.didSelectIndexHandle { (index) in
           
        }
simpleManager.refreshTableViewHandle { (scrollView, index) in
            scrollView.mj_header = MJRefreshNormalHeader {
                DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: {
                    scrollView.mj_header.endRefreshing()
                })
            }
        }

2.进阶版实现思路

2.1:层次结构

底部是LTPageView, pageView上放置了一个scrollView且可以左右滑动分页,scrollView上放置控制器view,headerView是一个单独的View在顶部,利用scrollView的contentInset将其放置在了最上面

2.2:使用方法(具体查看Demo)

(1)创建LTAdvancedManager,并添加到视图,传入frame,子控制器数组,标题数组,当前的控制器以及pageView的样式设置和自己的headerView(在闭包中返回即可)

LTAdvancedManager(frame: <#T##CGRect#>, viewControllers: <#T##[UIViewController]#>, titles: <#T##[String]#>, currentViewController: <#T##UIViewController#>, layout: <#T##LTLayout#>, headerViewHandle: <#T##() -> UIView#>)

(2)初始化子控制器的scrollView(tableView或collectionView),且tableView的y值从0开始,tableView的height则为父view的高减去44

(3)将子控制器的的scrollView(tableView或collectionView)赋值给glt_scollView即glt_scrollView = tableView,以下会说明原因。

2.3:实现思路

(1)主要是利用子控制的滚动来控制headerView

//MARK: 当前控制器的滑动方法事件处理 
    private func contentScrollViewDidScroll(_ contentScrollView: UIScrollView, _ absOffset: CGFloat)  {
        
        //获取当前控制器
        let currentVc = viewControllers[currentSelectIndex]
        
        //外部监听当前ScrollView的偏移量
        self.delegate?.glt_scrollViewOffsetY?((currentVc.glt_scrollView?.contentOffset.y ?? kHeaderHeight) + self.kHeaderHeight + layout.sliderHeight)
        
        //获取偏移量
        let offsetY = contentScrollView.contentOffset.y
        
        //获取当前pageTitleView的Y值
        var pageTitleViewY = pageView.pageTitleView.frame.origin.y
        
        //pageTitleView从初始位置上升的距离
        let titleViewBottomDistance = offsetY + kHeaderHeight + layout.sliderHeight
        
        let headerViewOffset = titleViewBottomDistance + pageTitleViewY
        
        if absOffset > 0 && titleViewBottomDistance > 0 {//向上滑动
            if headerViewOffset >= kHeaderHeight {
                pageTitleViewY += -absOffset
                if pageTitleViewY <= hoverY {
                    pageTitleViewY = hoverY
                }
            }
        }else{//向下滑动
            if headerViewOffset < kHeaderHeight {
                pageTitleViewY = -titleViewBottomDistance + kHeaderHeight
                if pageTitleViewY >= kHeaderHeight {
                    pageTitleViewY = kHeaderHeight
                }
            }
        }
        
        pageView.pageTitleView.frame.origin.y = pageTitleViewY
        headerView?.frame.origin.y = pageTitleViewY - kHeaderHeight
        let lastDiffTitleToNavOffset = pageTitleViewY - lastDiffTitleToNav
        lastDiffTitleToNav = pageTitleViewY
        //使其他控制器跟随改变
        for subVC in viewControllers {
            guard subVC != currentVc else { continue }
            guard let vcGlt_scrollView = subVC.glt_scrollView else { continue }
            vcGlt_scrollView.contentOffset.y += (-lastDiffTitleToNavOffset)
            subVC.glt_upOffset = String(describing: vcGlt_scrollView.contentOffset.y)
        }
    }

 

3.问题以及补充

 

3.1:问题1:全局监听scrollView的滚动

实现思路是根据runtime,交换方法的实现,主要的坑就是当时采用的交换scrollViewDidScroll(_:),但它是UIScrollViewDelegate的协议方法,发现行不通,后来找到了UIScrollView中的一个方法Selector(("_notifyDidScroll")),发现拦截它是可行的,当然Swift中拦截方法,也是有很多坑的,和OC有很大不同,具体操作看源码吧!

3.2:进阶版遗留小问题

当headerView中有按钮需要响应事件的时候,我这里采用的是利用override func point(inside point: CGPoint, with event: UIEvent?) -> Bool方法进行判断,因为上面headerView的交互只有关闭了才能滑动headerView左右切换,所以在这里我只允许要响应事件的控件交互打开了,其他区域交互关闭。如果有更好的思路欢迎联系!!!不胜感激!

//MARK: 暂用,待优化。
    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        for tempView in self.subviews {
            if tempView.isKind(of: UILabel.self) {
                let button = tempView as! UILabel
                let newPoint = self.convert(point, to: button)
                if button.bounds.contains(newPoint) {
                    return true
                }
            }
        }
        return false
    }

 

iOS ScrollView嵌套tableView联动滚动的思路分析 阅读详情

相关推荐

ScrollView和ViewPager嵌套使用(导致左右、上下滑动冲突解决方案)

前言:解决ScrollView中嵌套ViewPager,导致焦点冲突,解决的方案都是根据事件分发的原理设计的。方案1:自定义Viewpager做为子控件public class ChildViewPager extends ViewPager{ /** 触摸时按下的点 **/ PointF downP = new PointF(); /** 触摸时当前的点 **/

huang_wei_cai的专栏 1995

推荐开源项目:LTScrollView —— 灵活且强大的Swift与Objective-C滚动视图管理库

LTScrollView 是一款由[gl_twy](https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=Mzg4OTYwMTc3NQ==#wechat_redirect)开发的高效滚动视图管理库,适用于iOS平台。它能够轻松处理多个`UIScrollView`、`UITableView`和`UICollectionView`的集成,提...

gitblog_00086的博客 604

解决iOS中scrollView嵌套tableView手势冲突的方案

本文还有配套的精品资源,点击获取 简介:在iOS开发中,ScrollView和TableView的嵌套使用经常会遇到手势识别问题。为解决滚动冲突,作者shunFSKi提供了一个开源项目FSScrollViewNestTableView。该项目尝试了多种方法处理ScrollView和TableView手势冲突,如自定义手势识别器、设置识别器优先级、重写视图的 hitT...

weixin_42143092的博客 1704

[Swift]UIScrollView嵌套UITableView联动

众所周知,UITableView和UICollectionView都继承于UIScrollView,实际本文说的就是UIScrollView嵌套UIScrollView的事。 首先,自定义NestScrollView继承于UIScrollView,实现UIGestureRecognizerDelegate协议中的方法允许手势同时识别。 import Foundation import UIKit class NestScrollView: UIScrollView { required init

Gamin 3688

iOS UIScrollView左右滑动

iOS使用UIScrollView实现左右滑动UITableView和UICollectionView

swift-collectionView嵌套tableView实现悬停交互

collectionView嵌套tableView实现悬停交互

iOS ScrollView嵌套ScrolloView滑动处理 swift

本文demo下载地址 DFLinkageViewDemo 实现效果:如下 层级结构: 核心内容; 1.让外层scrollView和内层scrollview同时滚动scroll DFLinkageScrollView 内部实现 public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognize..

WangFei 1422

IOS 使用XIB 自定义View

IOS 使用XIB 自定义View http://blog.youkuaiyun.com/li6185377/article/details/8131042

swift - scrollview 判断左右移动, 以及上下两个view联动

核心代码 1. 2. 3. 界面代码VFL /* 浏览作品view*/ import UIKit /** * 图片浏览器(大图和缩略图) */ class JYBrowseWorksView: UIView { /// 数据源参数(外界传入) var data...

weixin_34220963的博客 788

iOS ScrollView嵌套tableView联动滚动的思路与最佳实践

前言 随着业务的发展,页面的复杂度越来越高,嵌套滚动视图的方式也越来越受设计师们的青睐,在各大电商App十分常见。如下Demo图: 但是这样的交互官方并不推荐,而且对开发来说确是不那么友好,需要处理滚动手势的冲突,页面的多层级嵌套都给开发带来了一定程度的麻烦。接下里我聊聊我们的实现思路。 思路和过程 对应这种页面结构应该毫无疑问是最底层是一个纵向滚动的scrollView,它的页面上面放一个固定高度的header,紧接着下面一个支持横向滚动切换的容器scrollView,容器上面才是各个页面具体的tableView,如下图: 思路一 最先想到的是,既然是滚动视图那么我们是否可以通过

ios scrollview嵌套tableview同向滑动的示例

本篇文章主要介绍了ios scrollview嵌套tableview同向滑动的示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

UIScrollView 嵌套一

滚动视图,如果直接添加的话,就会出现手势的冲突造成了体验上的悲剧。目前网上大部分的方法都是自己写手势监听,实现起来太过繁琐,最近遇到了同样的问题,写了一个比较简单的方法。来控制内外嵌套scrollView的滚动 以及滚动到目标位置后 把后续的滚动传递给另一个scrollView 避免滚动终止的生硬。// 内外层滚动到目标位置后 把滚动距离 传给外层 scrollView。// 外层滚动到目标位置后 把滚动距离 传给内存 scrollView。通过scrollView的代理方法。

wang_gwei的博客 2030

IOS自定义UIView

IOS中一般会用到几种方式自定义UIView 1、继承之UIView的存代码的自定义View 2、使用xib和代码一起使用的自定义View 3、存xib的自定义View(不需要业务处理的那种) 本文主要就介绍下存代码的自定义UIView和能够在storeboard中实时显示效果的自定义UIView 先上效果图 上面为设计界面,能够直接显示一个View的圆角与边框线 上面那个圆形饼图是用纯代码自定义的 1.实现在storeboard中实时显示效果的自定义UIView  1、创建MyView.h 继承 UIView #import // 设置类为可视化设计 I

react-native中ScrollView套ScrollView

react-native中ScrollView套ScrollView(安卓环境);ScrollView嵌套;父ScrollView套子ScrollView;父ScrollView不滑动,子ScrollView滑动

诚实可靠小郎君的博客 3213

QMT与通达信代码实战:从预警到交易的自动化实现

本文详细介绍了如何利用QMT量化交易平台与通达信软件实现从预警到交易的全自动化。通过读取通达信预警生成的板块文件,QMT策略可自动执行买卖指令,有效解决手动交易滞后问题。文章提供了完整的代码框架、核心原理拆解及实盘注意事项,帮助投资者构建高效、纪律性的自动化交易系统。

ansible6ops的博客 648

NVMe-MI --- Message Servicing Model(消息服务模型)

本文主要介绍NVMe-MI消息服务模型,两个主要类别是请求消息和响应消息。并介绍带外机制消息服务状态机。

智小星的博客 2009

uinavigationController pop 导致crash

当pop时候出现了[UIScrollview(UIScrollViewInternal)] _notifyDidScroll] 然后引用计数变为-1就崩溃了,查了半天 可以参考:http://stackoverflow.com/questions/26103756/uiscrollview-internal-consistency-crash 在dealloc中 取消掉tableview得代理

巅峰寂寞. 1723

开关电源环路学习笔记(1)-为啥要知道传递函数?

做硬件都会接触到开关电源,或多或少会接触到环路补偿。很多兄弟们也提出来让我说说这个,说明大家也都很关心,也说明这个好像有点难。 就我个人而言,我也想搞明白环路这一块,也查了一些资料,视频,不过说实话,一直都还是懵的,感觉很困难。 具体感觉就是,看资料或视频的时候,感觉好像是那么回事。但是撇开之后,就又云里雾里的感觉,总有一些想法没有找到答案。 问题 比如下面我想过的问题: 开关电源有开关,根本就不是一个线性系统,传递函数是咋弄出来的? 系统环路框图的输入量为什么不是Vin,而是参考电压V

weixin_42005993的博客 1万+

Scrollview嵌套Tableview的手势冲突

scrollview和tableview手势冲突

qq_55655826的博客 1052

【开源】基于TI ADS1299与ESP32的8通道脑电采集设备YuEEG全解析

本文详细解析了基于TI ADS1299芯片与ESP32主控的开源8通道脑电采集设备YuEEG。内容涵盖硬件设计、固件驱动开发及Python上位机软件实现,提供了从电路连接、SPI通信配置到数据读取与实时波形显示的全套教程。该项目为学习脑机接口(BCI)与高精度生物电信号采集提供了完整的开源解决方案,适合创客、学生及嵌入式开发者实践。

weixin_42576410的博客 1234

【项目案例】前后端分离项目 【Web图书管理系统 】SpringBoot + Vue + Element UI + Mysql

Web图书管理系统

激流丶的博客 5394

uniapp,解决scroll-view嵌套scroll-view,被嵌套的scroll-view无法触发下拉刷新问题

在被嵌套的scroll-view中再嵌套一层view并且设置`min-height: calc(100vh + 1rpx); <scroll-view scroll-y="true" refresher-enabled="true" @refresherrefresh="refreshDate" :refresher-triggered="triggered" @refresherpulling="refresherpulling" refresher-threshold="100"

weixin_47085255的博客 3493

【android bluetooth 案例分析 01】【HiCar 详解 3】【hicar时如何交换Wifi参数的】

如果直接使用 L2CAP(不经过 RFCOMM),会需要额外的协议来保证可靠性,而 RFCOMM 天然支持。BLE 广播的数据长度受限(31 字节 / 255 字节扩展),不适合传输复杂的 Wi-Fi 连接参数。使用 RFCOMM 传输参数,可以兼容不同厂商的车机和手机,而无需依赖特殊的蓝牙功能。手机解析这些参数,并使用 Wi-Fi Direct 连接到车机。,然后才能让 Wi-Fi Direct 进行真正的数据传输。,适合传输 Wi-Fi 连接参数等关键数据。,可以安全地交换 Wi-Fi 连接信息。

奔跑吧 android 的博客 1740

TableView/ScrollView嵌套问题(附demo)

先看下效果图(正常状态\上滑状态\下拉状态)       思路:1.最底下是横向滑动的ScrollView,2.然后上面添加两个可以左右切换的tableView,3.tableView头部预留一片空白作为填充, 真正的头部添加在控制器的View上,4.监听tableView的滑动, 根据偏移量执行不同的操作上滑状态:改变headerView的纵坐标, 根据头部的高度设置悬停的位置,下拉状态:改变h...

lg767201403的博客 4539

20、啁啾脉冲光纤放大器:原理、设计与仿真

本文详细介绍了啁啾脉冲光纤放大器(FCPA)的原理、设计与仿真过程。内容涵盖CPA技术的基本原理、光纤基CPA系统的组成、Tm掺杂光纤放大器的工作机制、全光纤脉冲展宽器的设计以及仿真分析。通过MATLAB仿真展示了脉冲在光纤中的展宽与放大过程,并讨论了如何优化系统以减少非线性失真、控制峰值功率并提高整体性能。文章还总结了系统优化的关键策略,并展望了未来的发展方向。

v4w5x6的博客 317

用 i18n 驯服标准文案:SAP Fiori elements 的 UI 文本本地化与可替换实践全景

本文系统介绍了SAP Fiori elements应用中UI文本本地化的全面解决方案。从框架层与应用层文本的分类原则出发,详细解析了标准文本替换的四步法:资源准备、键值定位、模型配置和验证部署。文章特别针对不同开发场景,提供了XML、ABAP CDS和CAP CDS三种注解方式的文本覆盖写法示例。同时深入探讨了语言回退机制、表格组件标准键覆盖等关键技术细节,并指出了实际项目中的常见问题与解决方案。通过结合官方文档和社区实践,为开发人员在不破坏框架约定的前提下,实现稳定可靠的UI文本本地化提供了完整指导。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 295
上一篇: Theos的安装和使用-iOS逆向工程
下一篇: iOS Hook在IDA中显示为sub_xxx的函数
glt_code
博客等级 码龄10年 40粉丝 27原创
评论 42
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值