## 感谢大佬:https://blog.csdn.net/fuchaosz/article/details/51513288

1 简介

最近在做侧滑的时候用到了SlidingMenu,在MainActivity中有个轮播图,用ViewPager实现的,结果发现ViewPager不能滑动了,ViewPager的滑动事件和SlidingMenu冲突了,然后自然想到调用Slidingmenu的addIgnoreView()方法,然而却发现并没有什么卵用,滑动事件还是冲突,于是研究了一下源码,发现是SlidingMenu的bug,然后修改后解决问题,遂著此文以记之。

2 Bug详细介绍

主界面上,如果有个ViewPager,那么侧滑菜单和ViewPager的滑动事件会冲突,也就是说向右滑动,这时候ViewPager是不翻页的,而是调出了左边的侧滑菜单。怎么办呢,一般解决办法是将调用

SlidingMenu.addIgnoreView(viewPager)

但是,如果这个ViewPager嵌套在一个ViewGroup中,那么上面这个方法就是失效了,看下面demo。

3 Bug示例

layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="滑动区域"
/> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="100dp"
> <android.support.v4.view.ViewPager
android:id="@+id/vp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</android.support.v4.view.ViewPager>
</LinearLayout> </LinearLayout>

侧滑菜单布局: layout/menu_left.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@android:color/holo_blue_light"
> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="30dp"
android:text="left menu item_1"
android:textSize="25sp"
/> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="30dp"
android:text="left menu item_2"
android:textSize="25sp"
/> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="30dp"
android:text="left menu item_3"
android:textSize="25sp"
/> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="30dp"
android:text="left menu item_4"
android:textSize="25sp"
/> </LinearLayout>

MainActiviy.java:

public class MainActivity extends Activity {

    private MyAdapter myAdapter;
private SlidingMenu menu;
private ViewPager vp; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.vp = (ViewPager) findViewById(R.id.vp);
this.init();
this.initMenu();
} private void init() {
//create views
List<View> views = new ArrayList<>();
for (int i = 0; i < 3; i++) {
TextView tv = new TextView(this);
tv.setText(i + "");
switch (i) {
case 0:
tv.setBackgroundColor(Color.RED);
break;
case 1:
tv.setBackgroundColor(Color.GREEN);
break;
case 2:
tv.setBackgroundColor(Color.BLUE);
break;
} tv.setGravity(Gravity.CENTER);
tv.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
views.add(tv);
}
//create myadapert
this.myAdapter = new MyAdapter(this, views);
//set adapter for viewpager
vp.setAdapter(myAdapter);
} //init slidingmenu
private void initMenu() {
menu = new SlidingMenu(this);
menu.setMode(SlidingMenu.LEFT);
menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
menu.setShadowWidthRes(R.dimen.shadow_width);
menu.setBehindOffset(200);
menu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT);
//set the left menu view
menu.setMenu(R.layout.menu_left);
menu.addIgnoredView(vp);
} class MyAdapter extends PagerAdapter { Context context;
List<View> views; public MyAdapter(Context context, List<View> views) {
this.context = context;
this.views = views;
} @Override
public int getCount() {
return views == null ? 0 : views.size();
} @Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
} @Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(views.get(position));
return views.get(position);
} @Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(views.get(position));
}
}
}

运行结果如下:



在MainActivity中已经添加了menu.addIgnoredView(vp)但是滑动viewPager左边空白区域,即下面图片的A区域,无法滑出侧滑菜单,此时A区域已经不属于viewPager了,正确的应该是可以滑出侧滑菜单的,所以这里是bug:

4 Bug原因

定位到SlidingMenu的源码中CustomViewAbove类的isInIgnoredView()方法:

 private boolean isInIgnoredView(MotionEvent ev) {
Rect rect = new Rect();
for (View v : mIgnoredViews) {
v.getHitRect(rect);
Log.d(TAG, String.format("rect=(%d,%d,%d,%d)", rect.left, rect.top, rect.right, rect.bottom));
Log.d(TAG, String.format("touch(%d,%d)", (int) ev.getX(), (int) ev.getY()));
if (rect.contains((int) ev.getX(), (int) ev.getY()))
return true;
}
return false;
}

添加两行打印,看看点击A区域之后,打印的日志:



从日志可以看出,明明点击的A区域在viewPager的外面,也就是说touch point的坐标应该在rect范围外面,但是打印出的日志却显示touch的点在rect内部,因此这个isInIgnoredView()返回true,导致事件被SlidingMenu拦截了,从而导致ViewPager接收不到事件,所以addIgnoreView()无效。

好了,可以明确原因是出在获取view的显示区域矩形出错,通过demo可以很明显的看出viewpager的区域不可能是从(0,0)开始的。

所以,bug出在v.getHitRect(rect),getHitRect()获取的坐标区域是相对于父view的.即viewpager相对于它的父ViewGroup,本例中的LinearLayout的坐标,由于没有padding,margin等参数,所以是从(0,0)开始的。

MotionEvent的touch point坐标是相对于整个屏幕的,所以两者当然不匹配,也就造成touch point始终在viewPager区域内了。

5 Bug解决

找到bug出错的原因是获取view的区域错误,那么改正就简单了,将SlidingMenu的源码中CustomViewAbove类的isInIgnoredView()方法中的

v.getHitRect(rect)

改为:

 v.getGlobalVisibleRect(rect)

getHitRect()获取的坐标是子view在父view中的坐标

getGlobalVisibleRect 获取的是view在整个屏幕的坐标

修改后的isInIgnoredView()方法如下:

private boolean isInIgnoredView(MotionEvent ev) {
Rect rect = new Rect();
for (View v : mIgnoredViews) {
//v.getHitRect(rect);
//这里稍微做了修改,v.getHitRect只能获取相对于父控件的位置,如果v嵌套在一个viewGroup中,
// 那么添加这个v到mIgnoredViews中将不会游任何效果,例如:LinearLayout嵌套一个ViewerPager,将ViewPager加入mIgnoredViews后,依然无法接受到滑动事件
//所以这里改为v.getGlobalVisibleRect,获取v在整个屏幕的坐标,而MotionEvent的坐标也是相对于整个屏幕来测量的
v.getGlobalVisibleRect(rect);
if (rect.contains((int)ev.getX(), (int)ev.getY())) return true;
}
return false;
}

6 小结

这个bug我已经提到github上SlidingMenu的issue中去了,小有成就感,哈哈。附上链接:

https://github.com/jfeinstein10/SlidingMenu/issues/751

7 bug demo下载地址

本文的bug示例已经上传了,下载地址:

http://download.csdn.net/detail/fuchaosz/9549168

SlidingMenu addIgnoreView() 无效的bug解决方法的更多相关文章

  1. 百度编辑器ueditor 异步加载时,初始化没办法赋值bug解决方法

    百度编辑器ueditor 异步加载时,初始化没办法赋值bug解决方法 金刚 前端 ueditor 初始化 因项目中使用了百度编辑器——ueditor.整体来说性能还不错. 发现问题 我在做一个编辑页面 ...

  2. android TextView多行文本(超过3行)使用ellipsize属性无效问题的解决方法

    这篇文章介绍了android TextView多行文本(超过3行)使用ellipsize属性无效问题的解决方法,有需要的朋友可以参考一下 布局文件中的TextView属性 复制代码代码如下: < ...

  3. 针对IE浏览器里面CSS的Bug解决方法

    IE6双倍边距bug 当页面内有多个连续浮动时,如本页的图标列表是采用左浮动,此时设置li的左侧margin值时,在最左侧呈现双倍情况.如外边距设置为10px, 而左侧则呈现出20px,解决它的方法是 ...

  4. [记录]mscorlib recursive resource lookup bug解决方法

    [Content]Expression: [mscorlib recursive resource lookup bug]Description: Infinite recursion during ...

  5. 项目总结---- imageLoder 的2个Bug解决方法、1.9.4如何选择性删除disk缓存和其它一些错误。

    我们不说废话,直接入主题,抓紧时间写完,好继续找bug... (PS:imageLoder的bug 百度不到的哦,不过我坚信我的观点没错) 版本1.9.2,1.9.4我没测试 1,imageLoder ...

  6. 浏览器css bug及bug解决方法

    Bugs及解决方案列表(以下实例默认运行环境都为Standard mode): 如何在IE6及更早浏览器中定义小高度的容器? 方法: #test{overflow:hidden;height:1px; ...

  7. 编写SqlHelper使用,在将ExecuteReader方法封装进而读取数据库中的数据时会产生Additional information: 阅读器关闭时尝试调用 Read 无效问题,解决方法与解释

    在自学杨中科老师的视频教学时,拓展编写SqlHelper使用,在将ExecuteReader方法封装进而读取数据库中的数据时 会产生Additional information: 阅读器关闭时尝试调用 ...

  8. table和div设置height:100%无效的完美解决方法

    刚接触网页排版的新手,常出现这种情况:设置table和div的高height="100%"无效,使用CSS来设置height:"100%"也无效,为什么会这样呢 ...

  9. 关于EasyUI 1.5版Datagrid组件在空数据时无法显示"空记录"提示的BUG解决方法

    问题:jQuery easyUI中Datagrid,在表格数据加载无数据的时候,如何显示"无记录"的提示语? 解决jQuery EasyUI 1.5.1版本的Datagrid,在处 ...

随机推荐

  1. .NetCore基于Jenkins和Gogs的自动化部署方案

    准备工作 Jenkins和gogs的安装配置可以看前两篇:Jenkins安装.配置与说明  和 gogs安装与说明(docker) 此外,因为还要安装.net core的SDK和Git工具: 安装.n ...

  2. 一种适合于MC与SMC算法的哈希表设计

    MC算法与SMC算法中的三角片焊接问题 在之前的关于MC算法与SMC算法的博文中介绍了算法的实现,文章主要围绕算法的核心问题,即三角片如何产生的问题进行了详细的描述.但由于实际应用中需要的等值面Mes ...

  3. golang 算法题 : 二维数组搜索值

    package mainimport "fmt"func main() { matrix := [][]int{ {1, 4, 7, 11, 15}, {2, 5, 8, 12, ...

  4. visual studio code 修改工具栏风格

    用windows版vscode的同学们是否发现它的工具栏是白色的跟整个界面看起来不太搭调,如下图: 其实要改变标题栏颜色也很简单,点击:文件> 首选项>设置 将 "window. ...

  5. Fuchsia OS入门官方文档

    Fuchsia Pink + Purple == Fuchsia (a new Operating System) Welcome to Fuchsia! This document has ever ...

  6. Flutter 让你的Dialog脱胎换骨吧!(Attach,Dialog,Loading,Toast)

    前言 Q:你一生中闻过最臭的东西,是什么? A:我那早已腐烂的梦. 兄弟萌!!!我又来了! 这次,我能自信的对大家说:我终于给大家带了一个,能真正帮助大家解决诸多坑比场景的pub包! 将之前的flut ...

  7. Nginx_安装配置

    一.安装gcc依赖库 检查是否安装(linux默认是安装了的) gcc –version  

  8. linux系统安装python3和pip

    一.安装python 1.安装依赖环境 yum install gcc -y yum -y install zlib-devel bzip2-devel openssl-devel ncurses-d ...

  9. sqlplus -S参数表示什么意思?

    sqlplus -S , -S选项是静默模式,是Silent的缩写.在这种模式下将会以最精简的形式完成SQL*Plus的交互过程. -S模式多用于脚本模式.在命令行sqlplus -S还有可能出现卡住 ...

  10. Word2010制作饭店活动宣传单

    原文链接: https://www.toutiao.com/i6492754127343321613/ 打开Word文档,选择"页面布局"选项卡."页面背景"功 ...