前言

在写代码过程中,遇到一个问题,使用抽屉控制器实现抽屉效果时,如果主控制器含有 scrollView,那么 scrollView 的滑动会与 MMDrawController 的滑动产生冲突,从而无法实现抽屉效果,经过尝试找到两种解决办法,写了一个简单 Demo
这里就简单的介绍一下 MMDrawController 的使用及如何解决 MMDrawController 与 scrollView 手势共存问题。


MMDrawController 的简单介绍

MMDrawController 是一个非常实用的抽屉控制器第三方库,详情使用请参考 GitHub-MMDrawController
Demo 中减掉一些不常用的功能,实现抽屉效果使用 MMDrawController 分为两步:

1.设置抽屉控制器。

2.展示抽屉控制器。

第一步设置抽屉控制器

在 AppDelegate 的 didFinishLaunchingWithOptions 方法中,设置显示抽屉控制器。

​ 1.初始化控制器(左抽屉控制器、右抽屉控制器、中间导航主控制器)。

​ 2.使用 MMDrawController 实现左右抽屉效果。

​ 3.设置打开/关闭抽屉的手势。

​ 4.设置左右抽屉控制器的显示宽度。

​ 5.显示抽屉控制器。

第二步展示抽屉控制器

在主控制器 (centerNavVC.m) 中,按钮点击展示抽屉控制器。

  1. 设置左右导航按钮。

  2. 设置点击事件:展示抽屉效果。

Gif 示例:

一个简单的抽屉控制器就完成了,如图所示:

1.可以通过左右滑动,在主控制器左右展示抽屉控制器。

2.也可以通过点击左右导航栏中按钮对抽屉控制器进行展示。

ViewDemo

MMDrawControllerscrollView 手势共存问题

问题描述

实现抽屉效果时,如果主控制器含有 scrollView,那么 scrollView 的滑动会与 MMDrawController 的滑动产生冲突,从而无法实现抽屉效果。

设置 ScrollView

在主控制器中添加 scrollView 的步骤大概为以下三步:

1.创建 ScrollView 及三个子 View:设置尺寸、颜色:

2.添加 ScrollView 及三个子 View:

3.设置 scrollView 属性,关闭弹簧效果、启动分页效果、滚动范围为3倍屏幕宽度:

Gif 示例:

启动模拟器后,显示如图所示:

1.scrollView 可以正常滑动。

2.点击抽屉按钮,抽屉效果显示正常。

3.左右滑动的时候抽屉效果失效。

scrollView 与抽屉冲突

分析原因:

scrollView 中有拖拽手势,抽屉控制器也有拖拽手势两个手势冲突,导致抽屉效果失效。

解决办法1:

方法1:使用 scrollView 代理方法,此方法中有一个参数: targetContentOffset ,可以通过 targetContentOffset 变量来获取滑动偏移量,若偏移量X方向

该方法使用条件是:
– 控制器成为 ScrollView 的代理,准守代理协议

该方法使用场景:
– 滑动 scrollView,并且手指离开时执行。一次有效滑动,只执行一次。

该方法功能介绍:
– 该方法中有一个非常重要的参数 targetContentOffset 滑动位移指针。

  • 通过该指针 targetContentOffset->x 获取,手指离开时 scrollView 在 X 方向滑动偏移量: tagetX

  • 使用 scrollView 在 X 方向滑动偏移量 tagetX,进行判断:

    1.1 若:滑动后 tagetX 为最小(最小的 X 值:0) 并且 显示在 ScrollView 最左侧(contentOffsetX 为最小值:0)

    • 展开左抽屉效果。

    1.2 若:滑动后 tagetX 为最大(最大的 X 值:2倍屏幕宽度) 并且 显示在 ScrollView 最左侧(contentOffsetX 为最小值:0)

    • 展开右抽屉效果。

    1.3 若:不满足以上两项,则不进行抽屉效果展示。

代码示例

解决办法2:

方法2:给 scrollView 添加一个空手势,使用手势的代理方法。

该方法使用条件是:
– 控制器成为手势的代理,准守代理协议。

该方法使用场景:
– 当执行手势时.会调用该方法。

该方法功能介绍:

  • 当执行手势时,询问该手势接收者是否应该开始执行执行手势方法:
    • 若:return YES ,该手势会被拦截(不会传递给 ScrollView 进行滚动)。
    • 若:return NO, 该手势会传递下去(传递给 ScrollView 进行滚动)。
  • 在该方法中进行判断:

1 若:手势不为滑动手势,直接 return NO,该手势会传递下去(传递给 ScrollView 进行滚动)。

2 若:手势为滑动手势,在进行判断:

2.1 若:该滑动手势滑动距离(滑动方向向右并且此时 scrollView 的 X 在最左边),展开左抽屉效果;

  • 展开左抽屉效果。

  • return YES,该手势会被拦截(不会传递给 ScrollView 进行滚动)。

2.2 若:该滑动手势滑动距离(滑动方向向做并且此时 scrollView 的 X 在最右边),展开右抽屉效果;

  • 展开右抽屉效果。

  • return YES,该手势会被拦截(不会传递给 ScrollView 进行滚动)。

2.3 若:不满足以上两点,则 return NO,该手势会传递下去(传递给 ScrollView 进行滚动)。

代码示例

Gif 示例:

启动模拟器后,显示如图所示:

1.scrollView 可以正常滑动。

2.点击抽屉按钮,抽屉效果显示正常。

3.左右滑动 scrollView 抽屉控制器与 scrollView 不冲突。
解决 ScrollView 与抽屉冲突

小结

解决该问题的核心为是在 ScrollView 左右边缘进行滑动时,判断是否应该执行抽屉效果。
这里把两个方法的思路梳理了一下。流程图如下:
流程图

发表评论

电子邮件地址不会被公开。 必填项已用*标注