原創文章,引用請注明出處:http://www.cnblogs.com/baipengzhan/p/6270201.html
Android底部導航欄有多種實現方式,本文詳解其中的ViewPager + RadioGroup方式的實現步驟。
我們先來看以下看一下最終做出的效果,使大家有個基本概念。

本結構特點:
1,ViewPager部分觸摸左右滑動切換頁面,RadioGroup部分中的RadioButton隨着自己對應的ViewPager頁面出現選中時的狀態,包括改變背景顏色,
改變文字顏色,改變圖片。其他RadioButton則是未被選中時的狀態;
2,當用戶點擊RadioGroup部分中的RadioButton,被點擊的RadioButton出現被選中時的顏色,ViewPager界面對應於RadioButton的頁面會出現在當前界面。
可以看到,ViewPager和RadioGroup可以雙向聯動,不是單向傳遞。
下面我們通過一個實例完全弄懂ViewPager + RadioGroup結構的用法
首先創建出我們界面的布局,上邊一個ViewPager,中間 一條分隔線,下邊一個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"
>
<!--上邊為ViewPager-->
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
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>
布局中重要屬性說明:
①ViewPager的android:layout_height屬性值為0,android:layout_weight屬性值為1。這兩個屬性值配合使用的意義是:
在豎直方向上ViewPager占滿父控件的剩余空間,也就是占據LinearLayout中除去分隔線和RadioGroup的剩余空間。
關於android:layout_weight屬性的詳細用法請參考:http://www.cnblogs.com/baipengzhan/p/Android_layout_weight.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
創建出ViewPager頁面盛放的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中主要進行的工作如下:
①監聽ViewPager,改變RadioGroup中的RadioButton;
②監聽RadioGroup中的RadioButton,改變ViewPager;
代碼如下:
package com.example.chironmy.bottomnavigation;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements View.OnClickListener,ViewPager.OnPageChangeListener{
private ViewPager viewPager;
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;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化界面
initView();
}
//初始化界面
private void initView() {
viewPager = (ViewPager) findViewById(R.id.viewpager);
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);
//給viewPager設置適配器,以顯示內容
MyViewPagerAdapter adapter = new MyViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
//設置RadioGroup開始時設置的按鈕,設置第一個按鈕為默認值
radioGroup.check(R.id.button_1);
//設置Viewpager第一次顯示的頁面
viewPager.setCurrentItem(0,true);
//設置按鈕點擊監聽
button_1.setOnClickListener(this);
button_2.setOnClickListener(this);
button_3.setOnClickListener(this);
button_4.setOnClickListener(this);
//設置ViewPager頁面監聽
viewPager.addOnPageChangeListener(this);
}
@Override
public void finish() {
ViewGroup viewGroup = (ViewGroup) getWindow().getDecorView();
viewGroup.removeAllViews();
super.finish();
}
//創建ViewPager盛放Fragment的適配器類
public class MyViewPagerAdapter extends FragmentPagerAdapter {
public MyViewPagerAdapter(FragmentManager fm) {
super(fm);
}
//返回每個position對應的Fragment對象
@Override
public Fragment getItem(int position) {
return list.get(position);
}
//返回list的長度,也就是Fragment對象的個數
@Override
public int getCount() {
return list.size();
}
}
//處理點擊的方法
@Override
public void onClick(View v) {
//我們根據參數的id區別不同按鈕
//不同按鈕對應着不同的ViewPager頁面
switch (v.getId()) {
case R.id.button_1:
viewPager.setCurrentItem(0,true);
break;
case R.id.button_2:
viewPager.setCurrentItem(1,true);
break;
case R.id.button_3:
viewPager.setCurrentItem(2,true);
break;
case R.id.button_4:
viewPager.setCurrentItem(3,true);
break;
default:
break;
}
}
//處理頁面變化的方法
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
//本文章中我們使用這個方法,本方法處理頁面變化后,也就是切換了不同的頁面后所做的操作
@Override
public void onPageSelected(int position) {
//根據當前展示的ViewPager頁面,使RadioGroup對應的按鈕被選中
switch (position) {
case 0:
radioGroup.check(R.id.button_1);
break;
case 1:
radioGroup.check(R.id.button_2);
break;
case 2:
radioGroup.check(R.id.button_3);
break;
case 3:
radioGroup.check(R.id.button_4);
break;
default:
break;
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
注意:在onClick方法中,viewPager的setCurrentItem方法中的第二個參數的意義是:
當該參數為true時,viewPager換頁時是平滑的換頁,會有頁面移動的效果;
該參數為false時,viewPager換頁效果沒有平滑的移動,頁面會直接出現。
該方法有一個參數的重載方法,默認有平滑換頁效果。
以上代碼中很多可以優化,比如xml文件中大量的屬性可以提取樣式,等等,這里列出只是為了方便更多水平的讀者讀懂,請諒解。
好啦,ViewPager + RadioGroup結構我們到此就講解完成了,感謝閱讀!
