Android自定义控件----RadioGroup实现APP首页底部Tab的切换
【正文】
实现APP首页底部Tab的切换已经见过四五种方式了,先来看运行的效果图吧:
今天我们就用RadioGroup的方法来实现以下。
【开发环境】
物理机版本:win 7旗舰版(64位)
IDE版本:Android Studio 1.2 preview
工程文件结构:(本文最后有源码)
一、布局文件:
(1)activity_home.xml:HomeActivity的布局文件
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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
![复制代码](http://common.cnblogs.com/images/copycode.gif)
代码有点多,无非就是一个FrameLayout对应的是tab上方的显示区域,然后四个RadioButton凑成一组单选按钮放在RadioGroup当中。
13行:能够保证FrameLayout占据除开Tab之后的剩下的全部空间。
76行:android:checked="true"这个很重要,稍后在java代码中讲。
RadioButton的属性有点多,我们选取就选取第一个RadioButton进行讲解,上面的第一个RadioButton的属性摘抄如下:
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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 /
![复制代码](http://common.cnblogs.com/images/copycode.gif)
上方代码的解释如下:
05行:weight为1,并且width为0dp,是保证四个tab能均分宽度。
06行:去掉RadioButton的样式,也就是去掉那个小图标,然后radiobutton就只剩下文字了。
07行:让里面的内容居中
08行:显示的文字
10行:设置这个tab的背景色和整个radioGroup的背景色一样,不过,也可以删掉(删掉之后,在我的小米手机手机上的排版会有问题)
10行:在这个tab的上面添加对应的icon图标(很重要,就是有了这个属性,每个tab的图标才会不一样哦)。
(2)fragment_home.xml:fragment的布局文件
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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
![复制代码](http://common.cnblogs.com/images/copycode.gif)
其他三个fragment的布局文件都一样,代码就不贴出来了,本文最后有源码下载。
(3)selector_tab_home.xml:tab被选中时对应icon的状态
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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
![复制代码](http://common.cnblogs.com/images/copycode.gif)
06行是默认的状态。
其他三个tab的状态都差不多,代码就不贴出来了,本文最后有源码下载。
(4)selector_tab_text_color.xml:tab中的文字被选中时的状态
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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
![复制代码](http://common.cnblogs.com/images/copycode.gif)
06行:默认的文字颜色是黑色,被切换时是白色。
二、Java代码:
(1)HomeActivity.java:
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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 }
![复制代码](http://common.cnblogs.com/images/copycode.gif)
代码注释已经很详细了。
尤其要注意的是第80行的注释,为了让app第一次启动时,默认就让第一个tab处于选中状态,我们现在activity_home.xml(76行)中让剩下的随便哪个radioButton的属性为checked,然后再重写上方java代码中的onStart方法(86行)。
(2)HomeFragment.java:
![复制代码](http://common.cnblogs.com/images/copycode.gif)
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 }
![复制代码](http://common.cnblogs.com/images/copycode.gif)
剩下三个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
相关文章
- 加密狗android,Android系统加密狗的设计与实现
- android图片资源加密,Android平台图像文件加密
- 跨平台移动APP开发进阶(二):HTML5+、mui开发移动app教程[通俗易懂]
- Android平台GB28181设备接入端对接编码前后音视频源类型浅析
- android app 退出功能,Android 完美退出 App (Exit)
- android-短信验证功能,Android实现获取短信验证码的功能以及自定义GUI短信验证详解…
- uni-app引入sortable列表拖拽,兼容App和H5
- android触摸屏事件,Android Touch事件分析
- Android preference_android studio preview
- android 复制控件,Android长按复制文本功能[通俗易懂]
- android 锁屏壁纸时钟,桌面锁屏时钟下载-桌面锁屏时钟app安卓版v2.8.0-七度网「建议收藏」
- uni-app 安卓APP开发记录
- 软件测试|一键搞定centos7的docker+selenium+appium+jenkins+android_app源码打包成apk的环境搭建
- 【Android 异步操作】线程池 ( 线程池 execute 方法源码解析 )
- 【Android 逆向】获取安装在手机中的应用的 APK 包 ( 进入 adb shell | 获取 root 权限 | 进入 /data/app/ 目录 | 拷贝 base.apk 到外置存储 )
- android studio gradle自动签名构建实现详解手机开发
- 网购Android App购物车点击动画实现详解编程语言
- Android实现PHP连接MySQL进行数据交互(android通过php连接mysql)
- APP与MySQL实现无缝连接让你办公更轻松(app连接mysql实例)
- APP连接MySQL,实现数据互联互通(app调用mysql)
- APP如何连接MySQL数据库(app怎样链接mysql)
- APP端如何实现连接MySQL数据库(app如何连接mysql)
- App联手Oracle实现多样化应用(app与oracle)
- 在Android中动态添加Panel框架的实现代码
- Android开发笔记之:HandlerRunnable与Thread的区别详解
- Erlang实现的百度云推送Android服务端实例