android使用Fragment实现底部菜单使用show()和hide()来切换以保持Fragment状态

在android开发的布局中,国内大量的使用底部菜单,这个本来不符合android的规范,我个人是深恶痛绝的,但是产品是这样设计的,也只能是这样做了。在这篇博客中,我将结合网上的资料以及自己的使用经验来实现一个底部菜单,解决了很多网友提出的各种问题,在文章中,我只贴出部分的实现代码以及效果图,免得占用大量的篇幅,让大家看的不爽,在最后我会给出整个demo的源码!!!

底部菜单的设计

一般来说,底部菜单是做多五个tab,这里面我做了四个tab,比较符合需求,实现的方式主要有tabhost,直接TextView,RadioButton等,我在这里使用的是RadioButton,觉得RadioButton比较简单控制,又能很好的实现我们的需求,底部菜单的activity_main.xml的代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                tools:context=".MainActivity">


    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/divide"
        android:layout_alignParentTop="true">

    FrameLayout>

    <View
        android:id="@+id/divide"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_above="@+id/activity_group_radioGroup"
        android:background="#cccccc"/>

    <RadioGroup
        android:id="@+id/activity_group_radioGroup"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="#ffffff"
        android:checkedButton="@+id/order_process"
        android:gravity="center"
        android:orientation="horizontal"
        android:paddingBottom="3dp"
        android:paddingTop="3dp">

        <RadioButton
            android:id="@+id/order_process"
            style="@style/main_tab_bottom"
            android:layout_width="fill_parent"
            android:layout_height="match_parent"
            android:layout_weight="1.0"
            android:drawableTop="@drawable/main_tab_1"
            android:gravity="center"
            android:text="订单处理"/>

        <RadioButton
            android:id="@+id/order_query"
            style="@style/main_tab_bottom"
            android:layout_width="fill_parent"
            android:layout_height="match_parent"
            android:layout_weight="1.0"
            android:checked="false"
            android:drawableTop="@drawable/main_tab_2"
            android:gravity="center"
            android:text="订单查询"/>

        <RadioButton
            android:id="@+id/merchant_manager"
            style="@style/main_tab_bottom"
            android:layout_width="fill_parent"
            android:layout_height="match_parent"
            android:layout_weight="1.0"
            android:checked="false"
            android:drawableTop="@drawable/main_tab_3"
            android:gravity="center"
            android:text="门店管理"/>

        <RadioButton
            android:id="@+id/setting"
            style="@style/main_tab_bottom"
            android:layout_width="fill_parent"
            android:layout_height="match_parent"
            android:layout_weight="1.0"
            android:checked="false"
            android:drawableTop="@drawable/main_tab_4"
            android:gravity="center"
            android:text="设置"/>
    RadioGroup>

RelativeLayout>

这个应该很好理解,就是在底部一个RadioGroup,内部放RadioButton来实现,上面放一个FrameLayout来放内容,这是xml部分。

Java代码控制Fragment的切换

在进行tab切换的过程中,我使用show()和hide()来处理,这样可以保存Fragment的状态,核心代码如下

public void onCheckedChanged(RadioGroup group, int checkedId) {
                FragmentManager fm = getSupportFragmentManager();
                FragmentTransaction ft = fm.beginTransaction();
                Fragment fragment1 = fm.findFragmentByTag(fragment1Tag);
                Fragment fragment2 = fm.findFragmentByTag(fragment2Tag);
                Fragment fragment3 = fm.findFragmentByTag(fragment3Tag);
                Fragment fragment4 = fm.findFragmentByTag(fragment4Tag);
                if (fragment1 != null) {
                    ft.hide(fragment1);
                }
                if (fragment2 != null) {
                    ft.hide(fragment2);
                }
                if (fragment3 != null) {
                    ft.hide(fragment3);
                }
                if (fragment4 != null) {
                    ft.hide(fragment4);
                }
                switch (checkedId) {
                    case R.id.order_process:
                        if (fragment1 == null) {
                            fragment1 = new Fragment1();
                            ft.add(R.id.container, fragment1, fragment1Tag);
                        } else {
                            ft.show(fragment1);
                        }
                        break;
                    case R.id.order_query:
                        if (fragment2 == null) {
                            fragment2 = new Fragment2();
                            ft.add(R.id.container, fragment2, fragment2Tag);
                        } else {
                            ft.show(fragment2);
                        }
                        break;
                    case R.id.merchant_manager:
                        if (fragment3 == null) {
                            fragment3 = new Fragment3();
                            ft.add(R.id.container, fragment3,
                                    fragment3Tag);
                        } else {
                            ft.show(fragment3);
                        }
                        break;
                    case R.id.setting:
                        if (fragment4 == null) {
                            fragment4 = new Fragment4();
                            ft.add(R.id.container, fragment4, fragment4Tag);
                        } else {
                            ft.show(fragment4);
                        }
                        break;
                    default:
                        break;
                }
                ft.commit();
            }
        });

切换的很完美,我们看下效果:
android使用Fragment实现底部菜单使用show()和hide()来切换以保持Fragment状态_第1张图片
android底部菜单的效果图

问题

1、上面的实现底部菜单,能够很好的实现Fragment的切换,还能够保存Fragment之前的状态,但是有个很大的问题,就是,我们把app退到后台,我们去玩其他的app,过一段时间回来,这个时候我们的app已经被销毁,我们按多任务键切换回来,发现界面上多个Fragment出现了重叠的情况,这是因为多个Fragment同时显示了,出现了重叠的情况,解决的办法如下:重写Activity的onRestoreInstanceState方法

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        for (int i = 0; i < radioGroup.getChildCount(); i++) {
            RadioButton mTab = (RadioButton) radioGroup.getChildAt(i);
            FragmentManager fm = getSupportFragmentManager();
            Fragment fragment = fm.findFragmentByTag((String) mTab.getTag());
            FragmentTransaction ft = fm.beginTransaction();
            if (fragment != null) {
                if (!mTab.isChecked()) {
                    ft.hide(fragment);
                }
            }
            ft.commit();
        }
    }

很好的解决了Fragment重叠的情况
2、如果在Fragment有操作toolbar的菜单的情况,除了要在Fragment中设置setHasOptionsMenu(true);之外,还需要Fragment中重写onHiddenChanged方法:

@Override
public void onHiddenChanged(boolean hidden) {
    super.onHiddenChanged(hidden);
    if (!hidden) {
        ((AppCompatActivity) getActivity()).setSupportActionBar(mToolbar);
        ((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayShowTitleEnabled(false);
        setHasOptionsMenu(true);
    }
}

不然的话,在恢复Fragment的时候会出现菜单混乱的情况。

=============如果设置的图片显示较小可以通过以下代码修改=====================

rgGroup = (RadioGroup) findViewById(R.id.re_group);  
        rbWeiHui = (RadioButton) findViewById(R.id.rb_wei_hui);  
        rbAdd = (RadioButton) findViewById(R.id.rb_add);  
        rbMine = (RadioButton) findViewById(R.id.rb_mine);  

        //定义底部标签图片大小  
        Drawable drawableWeiHui = getResources().getDrawable(R.drawable.btn_tab_wei_hui_selector);  
        drawableWeiHui.setBounds(0, 0, 69, 69);//第一0是距左右边距离,第二0是距上下边距离,第三69长度,第四宽度  
        rbWeiHui.setCompoundDrawables(null, drawableWeiHui, null, null);//只放上面  

        Drawable drawableAdd = getResources().getDrawable(R.drawable.btn_tab_add_selector);  
        drawableAdd.setBounds(0, 0, 168, 120);  
        rbAdd.setCompoundDrawables(drawableAdd, null, null, null);  

        Drawable drawableRight = getResources().getDrawable(R.drawable.btn_tab_mine_selector);  
        drawableRight.setBounds(0, 0, 69, 69);  
        rbMine.setCompoundDrawables(null, drawableRight, null, null);  

        //初始化底部标签  
        rgGroup.check(R.id.rb_wei_hui);// 默认勾选首页,初始化时候让首页默认勾选  

你可能感兴趣的:(android)