SlidingMenu 在 Android 5.0 上不能刷新界面的bug解决方法

来源:互联网 发布:秦美人盾牌进阶数据 编辑:程序博客网 时间:2024/06/08 20:59

1 简介

SlidingMenu在Android 5.0上存在兼容性问题,在有多个Fragment切换的Activity中,如果同时存在SlidingMenu,则打开一次侧滑菜单,界面就卡住了,不能刷新,不能切换Fragment。
最近,测试给提了个bug,说在华为P8手机上侧滑菜单打开后,不能切换卡项,经过一番研究,发现这个是Slidingmenu在5.0上存在的兼容问题,下面记录以下研究过程。

2 bug重现

先上图,MainActivity有侧滑菜单和多个Fragment,点击下面的按钮依次切换三个Fragment,如图是正常情况:

这里写图片描述

接着来看bug, 只要打开一次侧滑菜单,界面就卡住了,点击下面的按钮不能切换卡片,但是实际上是切换了的,只是界面没有刷新而已,如图:

这里写图片描述

看到了吗,虽然点击了卡项2,但是界面并没有刷新

3 bug示例

(1) 主界面布局就下面一排按钮,加一个FrameLayout作为Fragment的容器
layout\activity_main.xml:

<RelativeLayout    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    >    <LinearLayout        android:id="@+id/ly_bottom"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:orientation="horizontal"        >        <Button            android:id="@+id/btn1"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_weight="1"            android:text="卡片1"            />        <Button            android:id="@+id/btn2"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_weight="1"            android:text="卡片2"            />        <Button            android:id="@+id/btn3"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_weight="1"            android:text="卡片3"            />    </LinearLayout>    <FrameLayout        android:id="@+id/ly_content"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_above="@id/ly_bottom">    </FrameLayout></RelativeLayout>

(2) MainActivity中加入Slidigmenu,每次点击按钮就会切换Fragment
MainActivity:

public class MainActivity extends Activity implements View.OnClickListener {    private SlidingMenu menu;    private Fragment1 f1 = new Fragment1();    private Fragment2 f2 = new Fragment2();    private Fragment3 f3 = new Fragment3();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        findViewById(R.id.btn1).setOnClickListener(this);        findViewById(R.id.btn2).setOnClickListener(this);        findViewById(R.id.btn3).setOnClickListener(this);        this.initMenu();    }    private void initMenu() {        menu = new SlidingMenu(this);        menu.setMode(SlidingMenu.LEFT);        menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);        menu.setShadowWidth(300);        menu.setBehindOffset(200);        menu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT);        menu.setMenu(R.layout.left_menu);    }    @Override    public void onClick(View v) {        FragmentTransaction tr = getFragmentManager().beginTransaction();        switch (v.getId()) {            case R.id.btn1:                Toast.makeText(this, "点击了卡项1", Toast.LENGTH_SHORT).show();                tr.replace(R.id.ly_content, f1);                break;            case R.id.btn2:                Toast.makeText(this, "卡项2被点击了", Toast.LENGTH_SHORT).show();                tr.replace(R.id.ly_content, f2);                break;            case R.id.btn3:                Toast.makeText(this, "点击了卡项3", Toast.LENGTH_SHORT).show();                tr.replace(R.id.ly_content, f3);                break;        }        tr.commit();    }}

(3) 三个Fragment是相同的,就一个TextView,然后设一下背景,这里只列举第一个,其余两个改下字体颜色和背景
layout\layout_fragment_1.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"                android:layout_width="match_parent"                android:layout_height="match_parent">    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerInParent="true"        android:text="卡片1"        android:textColor="@android:color/holo_green_dark"        android:textSize="24sp"        /></RelativeLayout>

Fragment1.java:

public class Fragment1 extends Fragment {    public static Fragment1 newInstance(Context context) {        Fragment1 fragment = new Fragment1();        return fragment;    }    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        return inflater.inflate(R.layout.layout_fragment_1, null);    }}

详细代码请看附件

4 bug原因

这个具体原因也不清楚,只是在Android 5.0上出现,例如:华为P8。在Android 6.0则不存在,所以,归结为SlidingMenu的兼容问题

5 解决方法一:

第一种解决方法是开启硬件加速

在AndroidManifest.xml文件中在application标签中添加属性 android:hardwareAccelerated=”false”,如图:

这里写图片描述

但是,这种方法有个缺点,就是开启了硬件加速之后,如果碰到非常复杂的界面布局,嵌套太多的话,就会报StackOverflow的错误,可以自己百度一下,如果你恰好遇到一个喜欢留个FrameLayout,然后在代码里面不停的removeAllView()、addView(),动态添加布局的猪一样的队友,那么恭喜你,很有可能遇到我说的情况。顺便说一下,优雅的解决复杂布局的方法是用多个Fragment来拆开复杂界面、分离页面逻辑
万一你遇到开启硬件加速后,复杂界面报错的情况怎么办呢?别着急,临时关闭硬件加速就可以了,告诉机器,这个界面不要硬件加速。

首先找到报错的那个界面,例如MainActivity,然后设置这个Activity的属性,针对这个Activity不要使用硬件加速就可以了,如图:

这里写图片描述

如果这个猪一样的队友写的报错界面太多了,你总不能一个一个去找吧,所以,就有第二种方法,直接修改SlidingMenu的源码

6 解决方法二:

修改SlidingMenu.java,定位到第1005行,将下面的代码:

boolean layer = percentOpen > 0.0f && percentOpen < 1.0f;

改为:

boolean layer = percentOpen >= 0.0f && percentOpen <= 1.0f;

推荐使用这种方法,好了,问题解决。

7 后记

博主是参考了StackOverflower上面这篇文章解决的:

http://stackoverflow.com/questions/28563240/ui-not-refreshed-after-first-toggle-the-sliding-menu-on-android-5-0-lollipop

这个bug我已经提到Github上SlidingMenu的issue了,详见下面地址:

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

SlidingMenu的坑真是不少啊,已经发现两个了,之前博主发现一个bug,写了一篇博客,参见:

SlidingMenu addIgnoreView() 无效的bug解决方法

8 demo下载地址:

本文演示用的demo已上传,下载地址:http://download.csdn.net/detail/fuchaosz/9548810

9 转载请注明来自”梧桐那时雨”的博客:http://blog.csdn.net/fuchaosz/article/details/51657984

Tips
如果觉得这篇博客对你有帮助或者喜欢博主的写作风格,就给博主留个言或者顶一下呗,鼓励博主创作出更多优质博客,Thank you.

1 0
原创粉丝点击