zl程序教程

您现在的位置是:首页 >  移动开发

当前栏目

Android自定义控件----RadioGroup实现APP首页底部Tab的切换

AndroidApp 实现 自定义 控件 ---- 切换 tab
2023-09-14 08:57:57 时间

【正文】

实现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"

 6 tools:context=".MainActivity" 

 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" 

15 /FrameLayout 

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" 

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 / 

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 / 

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 / 

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"

 6 tools:context=".MainActivity" 

 8 TextView

 9 android:layout_width="wrap_content"

10 android:layout_height="wrap_content"

11 android:text="HomeFragment"

12 android:textSize="20sp"/ 

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" 

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" / 

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" 

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" / 

9 /selector 
复制代码

06行:默认的文字颜色是黑色,被切换时是白色。

 

二、Java代码:

(1)HomeActivity.java:

复制代码
 1 package com.smyhvae.radiogrouptabdemo;

 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;

 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;

 18 /**

 19 * Created by smyhvae on 2015/4/28.

 20 *

 21 */

 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;

 31 static final int NUM_ITEMS = 4;//一共四个fragment

 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 }

 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);

 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);

 75 }

 76 });

 77 }

 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 }

 89 //用adapter来管理四个Fragment界面的变化。注意,我这里用的Fragment都是v4包里面的

 90 FragmentStatePagerAdapter fragments = new FragmentStatePagerAdapter(getSupportFragmentManager()) {

 92 @Override

 93 public int getCount() {

 94 return NUM_ITEMS;//一共有四个Fragment

 95 }

 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;

109 case 2://搜索

110 fragment = new SearchFagment();

111 break;

113 case 3://我的

114 fragment = new ProfileFagment();

115 break;

116 default:

117 new HomeFagment();

118 break;

119 }

121 return fragment;

122 }

123 };

125 protected void initData() {

127 }

129 }
复制代码

代码注释已经很详细了。

尤其要注意的是第80行的注释,为了让app第一次启动时,默认就让第一个tab处于选中状态,我们现在activity_home.xml(76行)中让剩下的随便哪个radioButton的属性为checked,然后再重写上方java代码中的onStart方法(86行)。

 

(2)HomeFragment.java:

复制代码
 1 package com.smyhvae.radiogrouptabdemo.fragment;

 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;

 9 import com.smyhvae.radiogrouptabdemo.R;

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;

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);

31 }
复制代码

剩下三个Fragment的java代码是一样的,就不贴出来了,详见本文最后的源码。


Android Compose——一个简单的Bilibili APP 此Demo采用Android Compose声明式UI编写而成,主体采用MVVM设计框架,Demo涉及到的主要技术包括:Flow、Coroutines、Retrofit、Okhttp、Hilt以及适配了深色模式等;主要数据来源于Bilibili API。
App 自动化测试中有些常见痛点问题,如果框架不能很好的处理,就可能出现元素定位超时找不到的情况,自动化也就被打断终止了。很容易打消做自动化的热情,导致从入门到放弃。比如下面的两个问题:
App 自动化测试中有些常见痛点问题,如果框架不能很好的处理,就可能出现元素定位超时找不到的情况,自动化也就被打断终止了。很容易打消做自动化的热情,导致从入门到放弃。比如下面的两个问题:
生命壹号 个人网站:smyhvae.com。博客园:cnblogs.com/smyhvae。微信公众号:生命团队 | vitateam