原創文章,引用請注明出處: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結構我們到此就講解完成了,感謝閱讀!