原創文章,轉載請注明出處http://www.cnblogs.com/baipengzhan/p/6285881.html
Android底部導航欄有多種實現方式,本文詳細介紹FrameLayout + RadioGroup結構的實現方式。
主要的思路是,創建一個Fragment的容器,點擊RadioButton,動態地向容器中添加Fragment對象。
這種結構不同於ViewPager + RadioButton結構,本結構的Fragment展示部分不能左右滑動,只能
通過點擊RadioButton切換頁面,是一種單向傳遞的方式。
Fragment頁面可以滑動的底部導航欄結構(ViewPager + RadioButton)可以參考文章:
http://www.cnblogs.com/baipengzhan/p/6270201.html
我們先看一下最終做出來的效果吧,以便有個最初的印象。

好啦,那下面我們開始制作這種結構的底部導航欄吧。
本結構特點:
1,我們無法直接手動切換FrameLayout中的Fragment頁面,只能借助於RadioGroup;
2,當用戶點擊RadioGroup部分中的RadioButton,被點擊的RadioButton出現被選中時的狀態,FrameLayout界面對應於RadioButton的頁面會出現在當前界面。
可以看到,FrameLayout和RadioGroup是單向傳遞。
下面我們通過一個實例完全弄懂FrameLayout + RadioGroup結構的用法
首先創建出我們界面的布局,上邊一個FrameLayout,中間 一條分隔線,下邊一個RadioGroup
我們在一個Activity的布局中創建如下的xml文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<!--使用FrameLayout當做盛放Fragment對象的容器-->
<FrameLayout
android:id="@+id/framelayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
<!--中間為一條分割線-->
<View
android:background="@color/divider"
android:layout_width="match_parent"
android:layout_height="1dp"/>
<!--最下邊為RadioGroup-->
<RadioGroup
android:id="@+id/radioGroup"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--第一個RadioButton-->
<RadioButton
android:id="@+id/button_1"
android:text="button_1"
android:button="@null"
android:textColor="@color/radiobutton_color_selector"
android:background="@drawable/radiobutton_bg_selector"
android:gravity="center"
android:layout_weight="1"
android:drawableTop="@drawable/radiobutton_pic_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!--第二個RadioButton-->
<RadioButton
android:id="@+id/button_2"
android:text="button_2"
android:button="@null"
android:textColor="@color/radiobutton_color_selector"
android:background="@drawable/radiobutton_bg_selector"
android:gravity="center"
android:layout_weight="1"
android:drawableTop="@drawable/radiobutton_pic_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!--第三個RadioButton-->
<RadioButton
android:id="@+id/button_3"
android:text="button_3"
android:button="@null"
android:textColor="@color/radiobutton_color_selector"
android:background="@drawable/radiobutton_bg_selector"
android:gravity="center"
android:layout_weight="1"
android:drawableTop="@drawable/radiobutton_pic_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!--第四個RadioButton-->
<RadioButton
android:id="@+id/button_4"
android:text="button_4"
android:button="@null"
android:textColor="@color/radiobutton_color_selector"
android:background="@drawable/radiobutton_bg_selector"
android:gravity="center"
android:layout_weight="1"
android:drawableTop="@drawable/radiobutton_pic_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RadioGroup>
</LinearLayout>
布局中重要屬性說明:
①FrameLayout的android:layout_height屬性值為0,android:layout_weight屬性值為1。這兩個屬性值配合使用的意義是:
在豎直方向上FrameLayout占滿父控件的剩余空間,也就是占據LinearLayout中除去分隔線和RadioGroup的剩余空間。
關於android:layout_weight屬性的詳細用法請參考http://www.cnblogs.com/baipengzhan/p/6282826.html
②RadioButton的android:button屬性值為@null。這個屬性值的意義是,去除RadioGroup默認自帶顯示的小圓圈。
③RadioButton的android:gravity屬性值為center。這個屬性值的意義是,使RadioButton的內容(圖片和文字)居中。注意,內容默認情況沒有居中。
④RadioGroup的android:orientation屬性值為horizontal。意為,水平布置其中的RadioButton。
⑤RadioButton的android:textColor屬性值為@color/radiobutton_color_selector,是一個顏色狀態選擇器。顏色狀態選擇器就是一個定義在res/color目錄
下的xml文件,color目錄需要我們手動創建。顏色狀態選擇器的代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#f00" android:state_checked="true"/>
<item android:color="#f00" android:state_pressed="true"/>
<item android:color="#f00" android:state_selected="true"/>
<!--沒被選中時的顏色-->
<item android:color="#000"/>
</selector>
關於狀態選擇器的更詳細知識,請參考文章http://www.cnblogs.com/baipengzhan/p/6284682.html
⑥RadioButton的android:background屬性值為@drawable/radiobutton_bg_selector,這一個背景狀態選擇器,用來改變背景顏色,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@color/radiobutton_bg_selected"/>
<item android:state_checked="true" android:drawable="@color/radiobutton_bg_selected"/>
<item android:state_pressed="true" android:drawable="@color/radiobutton_bg_selected"/>
<!--未被選中-->
<item android:drawable="@color/radiobutton_bg_normal" />
</selector>
這個狀態選擇器是放置在res/drawable目錄下的一個普通狀態選擇器,該選擇器的屬性android:drawable的屬性值不能直接設置顏色,
顏色要封裝在values目錄下的colors.xml文件中,否則出錯。
⑦RadioButton的android:drawableTop屬性值為@drawable/radiobutton_pic_selector,是一個普通的狀態選擇器,用來改變圖片,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@mipmap/ic_selected"/>
<item android:state_checked="true" android:drawable="@mipmap/ic_selected"/>
<item android:state_pressed="true" android:drawable="@mipmap/ic_selected"/>
<!--未被選中-->
<item android:drawable="@mipmap/ic_launcher"/>
</selector>
該狀態選擇器同樣放置在res/drawable目錄下,選擇器的屬性值android:drawable屬性值變為了圖片,注意代碼寫到此處時,系統可能不會提示,
需要手動將該屬性值添加進來。
更多關於狀態選擇器的知識請參考文章http://www.cnblogs.com/baipengzhan/p/6284682.html
創建出FrameLayout頁面盛放的Fragment
我們創建出對應於四個RadioButton的四個Fragment,每個Fragment中盛放一個TextView。下邊只列出一個Fragment的寫法,剩余的相似,請各位朋友自己寫寫哦。
public class Fragment_1 extends Fragment {
private View mView;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//注意View對象的重復使用,以便節省資源
if(mView == null) {
mView = inflater.inflate(R.layout.fragment_1_layout,container,false);
}
return mView;
}
}
Fragment_1對應的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--創建TextView-->
<TextView
android:text="pager_1"
android:textSize="28sp"
android:textColor="#00f"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
在Activity中進行主要邏輯處理
我們在Activity中主要進行的工作如下:
監聽RadioGroup中的RadioButton,改變FrameLayout中盛放的Fragment對象;
package com.example.radiogroup_framelayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private RadioGroup radioGroup;
private RadioButton button_1;
private RadioButton button_2;
private RadioButton button_3;
private RadioButton button_4;
private Fragment_1 fragment_1;
private Fragment_2 fragment_2;
private Fragment_3 fragment_3;
private Fragment_4 fragment_4;
private List<Fragment> list;
private FrameLayout frameLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化頁面
initView();
}
//初始化頁面
private void initView() {
frameLayout = (FrameLayout) findViewById(R.id.framelayout);
radioGroup = (RadioGroup) findViewById(R.id.radioGroup);
//找到四個按鈕
button_1 = (RadioButton) findViewById(R.id.button_1);
button_2 = (RadioButton) findViewById(R.id.button_2);
button_3 = (RadioButton) findViewById(R.id.button_3);
button_4 = (RadioButton) findViewById(R.id.button_4);
//創建Fragment對象及集合
fragment_1 = new Fragment_1();
fragment_2 = new Fragment_2();
fragment_3 = new Fragment_3();
fragment_4 = new Fragment_4();
//將Fragment對象添加到list中
list = new ArrayList<>();
list.add(fragment_1);
list.add(fragment_2);
list.add(fragment_3);
list.add(fragment_4);
//設置RadioGroup開始時設置的按鈕,設置第一個按鈕為默認值
radioGroup.check(R.id.button_1);
//設置按鈕點擊監聽
button_1.setOnClickListener(this);
button_2.setOnClickListener(this);
button_3.setOnClickListener(this);
button_4.setOnClickListener(this);
//初始時向容器中添加第一個Fragment對象
addFragment(fragment_1);
}
@Override
public void finish() {
ViewGroup viewGroup = (ViewGroup) getWindow().getDecorView();
viewGroup.removeAllViews();
super.finish();
}
//點擊事件處理
@Override
public void onClick(View v) {
//我們根據參數的id區別不同按鈕
//不同按鈕對應着不同的Fragment對象頁面
switch (v.getId()) {
case R.id.button_1:
addFragment(fragment_1);
break;
case R.id.button_2:
addFragment(fragment_2);
break;
case R.id.button_3:
addFragment(fragment_3);
break;
case R.id.button_4:
addFragment(fragment_4);
break;
default:
break;
}
}
//向Activity中添加Fragment的方法
public void addFragment(Fragment fragment) {
//獲得Fragment管理器
FragmentManager fragmentManager = getSupportFragmentManager();
//使用管理器開啟事務
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
//使用事務替換Fragment容器中Fragment對象
fragmentTransaction.replace(R.id.framelayout,fragment);
//提交事務,否則事務不生效
fragmentTransaction.commit();
}
}
注意:
以上代碼中很多可以優化,比如xml文件中大量的屬性可以提取樣式,等等,這里列出只是為了方便更多水平的讀者讀懂,請諒解。
其實Fragment對象的容器不止FrameLayout一種,只是這種結構容器對Fragment支持比較好,更為常用,各位小伙伴可以使用其他容器嘗試哦,原理是一樣的。
本方式利用動態添加Fragment對象到Activity中,其實我們也可以有個設想,使用靜態方法添加到容器中,各個Fragment相互重疊,只有一個顯示,我還沒嘗試,
今后有機會了可以這樣試一下,各位小伙伴可以試試哦。
好啦,FrameLayout + RadioGroup結構我們到此就講解完成了,感謝閱讀!
