1. 程式人生 > >android使用Fragment實現底部選單使用show()和hide()來切換以保持Fragment狀態

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底部選單的效果圖

問題

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的時候會出現選單混亂的情況。
大功告成,大家有什麼問題或者建議請給我留言!!!
最後給出原始碼:下載