Android自定義控件----RadioGroup實現APP首頁底部Tab的切換


【聲明】 

歡迎轉載,但請保留文章原始出處→_→ 

生命壹號:http://www.cnblogs.com/smyhvae/

文章來源:http://www.cnblogs.com/smyhvae/p/4463931.html

 

【正文】

實現APP首頁底部Tab的切換已經見過四五種方式了,先來看運行的效果圖吧:

今天我們就用RadioGroup的方法來實現以下。

 

【開發環境】

物理機版本:win 7旗艦版(64位)

IDE版本:Android Studio 1.2 preview

工程文件結構:(本文最后有源碼)

70d49874-8327-4690-9882-eec70703bfbe

  • HomeActivity.java:整個首頁的界面
  • 四個Fragment.java:對應的四個Fragment界面
  • drawable文件夾中是對應tab和文字切換的狀態
  • 剩下的xml文件就是對應的Activity和Fragment的布局文件了。

 

一、布局文件:

(1)activity_home.xml:HomeActivity的布局文件

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5 
 6     tools:context=".MainActivity">
 7 
 8     <!--tab上方的顯示區域-->
 9     <FrameLayout
10         android:id="@+id/mHomeContent"
11         android:layout_width="match_parent"
12         android:layout_height="match_parent"
13         android:layout_above="@+id/mHomeRadioGroup">
14 
15         </FrameLayout>
16 
17     <!--底下的四個tab-->
18     <RadioGroup
19         android:id="@+id/mHomeRadioGroup"
20         android:layout_width="match_parent"
21         android:layout_height="56dp"
22         android:orientation="horizontal"
23         android:layout_alignParentBottom="true"
24         android:background="@color/tab_bg"  >
25 
26         <RadioButton
27             android:id="@+id/mHomeHomeRb"
28             android:layout_width="0dp"
29             android:layout_height="wrap_content"
30             android:layout_weight="1"
31             android:button="@null"
32             android:gravity="center"
33             android:text="@string/home_home"
34             android:textColor="@drawable/selector_tab_text_color"
35             android:background="@color/tab_bg"
36             android:drawableTop="@drawable/selector_tab_home"
37            />
38 
39         <RadioButton
40             android:id="@+id/mHomeFindRb"
41             android:layout_width="0dp"
42             android:layout_height="wrap_content"
43             android:layout_weight="1"
44             android:button="@null"
45             android:gravity="center"
46             android:text="@string/home_find"
47             android:textColor="@drawable/selector_tab_text_color"
48             android:background="@color/tab_bg"
49             android:drawableTop="@drawable/selector_tab_find"
50             />
51 
52         <RadioButton
53             android:id="@+id/mHomeSearchRb"
54             android:layout_width="0dp"
55             android:layout_height="wrap_content"
56             android:layout_weight="1"
57             android:button="@null"
58             android:gravity="center"
59             android:text="@string/home_search"
60             android:textColor="@drawable/selector_tab_text_color"
61             android:background="@color/tab_bg"
62             android:drawableTop="@drawable/selector_tab_search"
63            />
64 
65         <RadioButton
66             android:id="@+id/mHomeProfileRb"
67             android:layout_width="0dp"
68             android:layout_height="wrap_content"
69             android:layout_weight="1"
70             android:button="@null"
71             android:gravity="center"
72             android:text="@string/home_profile"
73             android:textColor="@drawable/selector_tab_text_color"
74             android:background="@color/tab_bg"
75             android:drawableTop="@drawable/selector_tab_profile"
76  android:checked="true"
77            />
78     </RadioGroup>
79 </RelativeLayout>

代碼有點多,無非就是一個FrameLayout對應的是tab上方的顯示區域,然后四個RadioButton湊成一組單選按鈕放在RadioGroup當中。

13行:能夠保證FrameLayout占據除開Tab之后的剩下的全部空間。

76行:android:checked="true"這個很重要,稍后在java代碼中講。

RadioButton的屬性有點多,我們選取就選取第一個RadioButton進行講解,上面的第一個RadioButton的屬性摘抄如下:

 1         <RadioButton
 2             android:id="@+id/mHomeHomeRb"
 3             android:layout_width="0dp"
 4             android:layout_height="wrap_content"
 5             android:layout_weight="1"
 6             android:button="@null"
 7             android:gravity="center"
 8             android:text="@string/home_home"
 9             android:textColor="@drawable/selector_tab_text_color"
10             android:background="@color/tab_bg"
11  android:drawableTop="@drawable/selector_tab_home"
12            />

上方代碼的解釋如下:

05行:weight為1,並且width為0dp,是保證四個tab能均分寬度。

06行:去掉RadioButton的樣式,也就是去掉那個小圖標,然后radiobutton就只剩下文字了。

07行:讓里面的內容居中

08行:顯示的文字

10行:設置這個tab的背景色和整個radioGroup的背景色一樣,不過,也可以刪掉(刪掉之后,在我的小米手機手機上的排版會有問題)

10行:在這個tab的上面添加對應的icon圖標(很重要,就是有了這個屬性,每個tab的圖標才會不一樣哦)

 

(2)fragment_home.xml:fragment的布局文件

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5 
 6     tools:context=".MainActivity">
 7 
 8     <TextView
 9         android:layout_width="wrap_content"
10         android:layout_height="wrap_content"
11         android:text="HomeFragment"
12         android:textSize="20sp"/>
13 
14 </LinearLayout>

其他三個fragment的布局文件都一樣,代碼就不貼出來了,本文最后有源碼下載。

 

(3)selector_tab_home.xml:tab被選中時對應icon的狀態

1 <?xml version="1.0" encoding="utf-8"?>
2 <selector xmlns:android="http://schemas.android.com/apk/res/android">
3 
4     <item android:drawable="@mipmap/tab_home_selected" android:state_pressed="false" android:state_selected="true" />
5     <item android:drawable="@mipmap/tab_home_selected" android:state_checked="true" android:state_pressed="false" />
6     <item android:drawable="@mipmap/tab_home_nomal" />
7 
8 
9 </selector>

06行是默認的狀態。

其他三個tab的狀態都差不多,代碼就不貼出來了,本文最后有源碼下載。

 

(4)selector_tab_text_color.xml:tab中的文字被選中時的狀態

1 <?xml version="1.0" encoding="utf-8"?>
2 <selector xmlns:android="http://schemas.android.com/apk/res/android">
3 
4 <item android:color="@color/white" android:state_pressed="false" android:state_selected="true" />
5 <item android:color="@color/white" android:state_checked="true" android:state_pressed="false" />
6 <item android:color="@color/black" />
7 
8 
9 </selector>

06行:默認的文字顏色是黑色,被切換時是白色。

 

二、Java代碼:

(1)HomeActivity.java:

  1 package com.smyhvae.radiogrouptabdemo;
  2 
  3 import android.os.Bundle;
  4 import android.support.v4.app.Fragment;
  5 import android.support.v4.app.FragmentActivity;
  6 import android.support.v4.app.FragmentStatePagerAdapter;
  7 import android.view.Window;
  8 import android.widget.FrameLayout;
  9 import android.widget.RadioButton;
 10 import android.widget.RadioGroup;
 11 
 12 import com.smyhvae.radiogrouptabdemo.fragment.FindFagment;
 13 import com.smyhvae.radiogrouptabdemo.fragment.HomeFagment;
 14 import com.smyhvae.radiogrouptabdemo.fragment.ProfileFagment;
 15 import com.smyhvae.radiogrouptabdemo.fragment.SearchFagment;
 16 
 17 
 18 /**
 19  * Created by smyhvae on 2015/4/28.
 20  *
 21  */
 22 
 23 public class HomeActivity extends FragmentActivity {
 24     private FrameLayout mHomeContent;
 25     private RadioGroup mHomeRadioGroup;
 26     private RadioButton mHomeHomeRb;
 27     private RadioButton mHomeFindRb;
 28     private RadioButton mHomeSearchRb;
 29     private RadioButton mHomeProfileRb;
 30 
 31     static final int NUM_ITEMS = 4;//一共四個fragment
 32 
 33     @Override
 34     protected void onCreate(Bundle savedInstanceState) {
 35         super.onCreate(savedInstanceState);
 36         requestWindowFeature(Window.FEATURE_NO_TITLE);
 37         setContentView(R.layout.activity_home);
 38         initView();
 39         initData();
 40     }
 41 
 42     protected void initView() {
 43         mHomeContent = (FrameLayout) findViewById(R.id.mHomeContent); //tab上方的區域
 44         mHomeRadioGroup = (RadioGroup) findViewById(R.id.mHomeRadioGroup);  //底部的四個tab
 45         mHomeHomeRb = (RadioButton) findViewById(R.id.mHomeHomeRb);
 46         mHomeFindRb = (RadioButton) findViewById(R.id.mHomeFindRb);
 47         mHomeSearchRb = (RadioButton) findViewById(R.id.mHomeSearchRb);
 48         mHomeProfileRb = (RadioButton) findViewById(R.id.mHomeProfileRb);
 49 
 50         //監聽事件:為底部的RadioGroup綁定狀態改變的監聽事件
 51         mHomeRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
 52             @Override
 53             public void onCheckedChanged(RadioGroup group, int checkedId) {
 54                 int index = 0;
 55                 switch (checkedId) {
 56                     case R.id.mHomeHomeRb:
 57                         index = 0;
 58                         break;
 59                     case R.id.mHomeFindRb:
 60                         index = 1;
 61                         break;
 62                     case R.id.mHomeSearchRb:
 63                         index = 2;
 64                         break;
 65                     case R.id.mHomeProfileRb:
 66                         index = 3;
 67                         break;
 68                 }
 69                 //通過fragments這個adapter還有index來替換幀布局中的內容
 70                 Fragment fragment = (Fragment) fragments.instantiateItem(mHomeContent, index);
 71                 //一開始將幀布局中 的內容設置為第一個
 72                 fragments.setPrimaryItem(mHomeContent, 0, fragment);
 73                 fragments.finishUpdate(mHomeContent);
 74 
 75             }
 76         });
 77     }
 78 
 79 
 80     //第一次啟動時,我們讓mHomeHomeRb這個radiobutton處於選中狀態。
 81     // 當然了,在這之前,先要在布局文件中設置其他的某一個radiobutton(只要不是mHomeHomeRb就行)
 82     // 的屬性為android:checked="true",才會出發下面的這個check方法切換到mHomeHomeRb
 83     @Override
 84     protected void onStart() {
 85         super.onStart();
 86  mHomeRadioGroup.check(R.id.mHomeHomeRb);  87     }
 88 
 89     //用adapter來管理四個Fragment界面的變化。注意,我這里用的Fragment都是v4包里面的
 90     FragmentStatePagerAdapter fragments = new FragmentStatePagerAdapter(getSupportFragmentManager()) {
 91 
 92         @Override
 93         public int getCount() {
 94             return NUM_ITEMS;//一共有四個Fragment
 95         }
 96 
 97         //進行Fragment的初始化
 98         @Override
 99         public Fragment getItem(int i) {
100             Fragment fragment = null;
101             switch (i) {
102                 case 0://首頁
103                     fragment = new HomeFagment();
104                     break;
105                 case 1://發現
106                     fragment = new FindFagment();
107                     break;
108 
109                 case 2://搜索
110                     fragment = new SearchFagment();
111                     break;
112 
113                 case 3://我的
114                     fragment = new ProfileFagment();
115                     break;
116                 default:
117                     new HomeFagment();
118                     break;
119             }
120 
121             return fragment;
122         }
123     };
124 
125     protected void initData() {
126 
127     }
128 
129 }

代碼注釋已經很詳細了。

尤其要注意的是第80行的注釋,為了讓app第一次啟動時,默認就讓第一個tab處於選中狀態,我們現在activity_home.xml(76行)中讓剩下的隨便哪個radioButton的屬性為checked,然后再重寫上方java代碼中的onStart方法(86行)。

 

(2)HomeFragment.java:

 1 package com.smyhvae.radiogrouptabdemo.fragment;
 2 
 3 import android.os.Bundle;
 4 import android.support.v4.app.Fragment;
 5 import android.view.LayoutInflater;
 6 import android.view.View;
 7 import android.view.ViewGroup;
 8 
 9 import com.smyhvae.radiogrouptabdemo.R;
10 
11 
12 /**
13  * Created by smyh on 2015/4/28.
14  */
15 public class HomeFagment extends Fragment {
16     @Override
17     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
18         View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_home, null);
19         return view;
20     }
21 
22     //重寫setMenuVisibility方法,不然會出現疊層的現象
23     @Override
24     public void setMenuVisibility(boolean menuVisibile) {
25         super.setMenuVisibility(menuVisibile);
26         if (this.getView() != null) {
27             this.getView().setVisibility(menuVisibile ? View.VISIBLE : View.GONE);
28         }
29     }
30 
31 }

剩下三個Fragment的java代碼是一樣的,就不貼出來了,詳見本文最后的源碼。

 

【工程文件】

2015-04-28-RadioGroupTabDemo

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM