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
工程文件结构:(本文最后有源码)

- HomeActivity.java:整个首页的界面
- 四个Fragment.java:对应的四个Fragment界面
- drawable文件夹中是对应tab和文字切换的状态
- 剩下的xml文件就是对应的Activity和Fragment的布局文件了。
一、布局文件:
(1)activity_home.xml:HomeActivity的布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".MainActivity"> <!--tab上方的显示区域-->
<FrameLayout
android:id="@+id/mHomeContent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/mHomeRadioGroup"> </FrameLayout> <!--底下的四个tab-->
<RadioGroup
android:id="@+id/mHomeRadioGroup"
android:layout_width="match_parent"
android:layout_height="56dp"
android:orientation="horizontal"
android:layout_alignParentBottom="true"
android:background="@color/tab_bg" > <RadioButton
android:id="@+id/mHomeHomeRb"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:button="@null"
android:gravity="center"
android:text="@string/home_home"
android:textColor="@drawable/selector_tab_text_color"
android:background="@color/tab_bg"
android:drawableTop="@drawable/selector_tab_home"
/> <RadioButton
android:id="@+id/mHomeFindRb"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:button="@null"
android:gravity="center"
android:text="@string/home_find"
android:textColor="@drawable/selector_tab_text_color"
android:background="@color/tab_bg"
android:drawableTop="@drawable/selector_tab_find"
/> <RadioButton
android:id="@+id/mHomeSearchRb"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:button="@null"
android:gravity="center"
android:text="@string/home_search"
android:textColor="@drawable/selector_tab_text_color"
android:background="@color/tab_bg"
android:drawableTop="@drawable/selector_tab_search"
/> <RadioButton
android:id="@+id/mHomeProfileRb"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:button="@null"
android:gravity="center"
android:text="@string/home_profile"
android:textColor="@drawable/selector_tab_text_color"
android:background="@color/tab_bg"
android:drawableTop="@drawable/selector_tab_profile"
android:checked="true"
/>
</RadioGroup>
</RelativeLayout>
代码有点多,无非就是一个FrameLayout对应的是tab上方的显示区域,然后四个RadioButton凑成一组单选按钮放在RadioGroup当中。
13行:能够保证FrameLayout占据除开Tab之后的剩下的全部空间。
76行:android:checked="true"这个很重要,稍后在java代码中讲。
RadioButton的属性有点多,我们选取就选取第一个RadioButton进行讲解,上面的第一个RadioButton的属性摘抄如下:
<RadioButton
android:id="@+id/mHomeHomeRb"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:button="@null"
android:gravity="center"
android:text="@string/home_home"
android:textColor="@drawable/selector_tab_text_color"
android:background="@color/tab_bg"
android:drawableTop="@drawable/selector_tab_home"
/>
上方代码的解释如下:
05行:weight为1,并且width为0dp,是保证四个tab能均分宽度。
06行:去掉RadioButton的样式,也就是去掉那个小图标,然后radiobutton就只剩下文字了。
07行:让里面的内容居中
08行:显示的文字
10行:设置这个tab的背景色和整个radioGroup的背景色一样,不过,也可以删掉(删掉之后,在我的小米手机手机上的排版会有问题)
10行:在这个tab的上面添加对应的icon图标(很重要,就是有了这个属性,每个tab的图标才会不一样哦)。
(2)fragment_home.xml:fragment的布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".MainActivity"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="HomeFragment"
android:textSize="20sp"/> </LinearLayout>
其他三个fragment的布局文件都一样,代码就不贴出来了,本文最后有源码下载。
(3)selector_tab_home.xml:tab被选中时对应icon的状态
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@mipmap/tab_home_selected" android:state_pressed="false" android:state_selected="true" />
<item android:drawable="@mipmap/tab_home_selected" android:state_checked="true" android:state_pressed="false" />
<item android:drawable="@mipmap/tab_home_nomal" /> </selector>
06行是默认的状态。
其他三个tab的状态都差不多,代码就不贴出来了,本文最后有源码下载。
(4)selector_tab_text_color.xml:tab中的文字被选中时的状态
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@color/white" android:state_pressed="false" android:state_selected="true" />
<item android:color="@color/white" android:state_checked="true" android:state_pressed="false" />
<item android:color="@color/black" /> </selector>
06行:默认的文字颜色是黑色,被切换时是白色。
二、Java代码:
(1)HomeActivity.java:
package com.smyhvae.radiogrouptabdemo; import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.view.Window;
import android.widget.FrameLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup; import com.smyhvae.radiogrouptabdemo.fragment.FindFagment;
import com.smyhvae.radiogrouptabdemo.fragment.HomeFagment;
import com.smyhvae.radiogrouptabdemo.fragment.ProfileFagment;
import com.smyhvae.radiogrouptabdemo.fragment.SearchFagment; /**
* Created by smyhvae on 2015/4/28.
*
*/ public class HomeActivity extends FragmentActivity {
private FrameLayout mHomeContent;
private RadioGroup mHomeRadioGroup;
private RadioButton mHomeHomeRb;
private RadioButton mHomeFindRb;
private RadioButton mHomeSearchRb;
private RadioButton mHomeProfileRb; static final int NUM_ITEMS = 4;//一共四个fragment @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_home);
initView();
initData();
} protected void initView() {
mHomeContent = (FrameLayout) findViewById(R.id.mHomeContent); //tab上方的区域
mHomeRadioGroup = (RadioGroup) findViewById(R.id.mHomeRadioGroup); //底部的四个tab
mHomeHomeRb = (RadioButton) findViewById(R.id.mHomeHomeRb);
mHomeFindRb = (RadioButton) findViewById(R.id.mHomeFindRb);
mHomeSearchRb = (RadioButton) findViewById(R.id.mHomeSearchRb);
mHomeProfileRb = (RadioButton) findViewById(R.id.mHomeProfileRb); //监听事件:为底部的RadioGroup绑定状态改变的监听事件
mHomeRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
int index = 0;
switch (checkedId) {
case R.id.mHomeHomeRb:
index = 0;
break;
case R.id.mHomeFindRb:
index = 1;
break;
case R.id.mHomeSearchRb:
index = 2;
break;
case R.id.mHomeProfileRb:
index = 3;
break;
}
//通过fragments这个adapter还有index来替换帧布局中的内容
Fragment fragment = (Fragment) fragments.instantiateItem(mHomeContent, index);
//一开始将帧布局中 的内容设置为第一个
fragments.setPrimaryItem(mHomeContent, 0, fragment);
fragments.finishUpdate(mHomeContent); }
});
} //第一次启动时,我们让mHomeHomeRb这个radiobutton处于选中状态。
// 当然了,在这之前,先要在布局文件中设置其他的某一个radiobutton(只要不是mHomeHomeRb就行)
// 的属性为android:checked="true",才会出发下面的这个check方法切换到mHomeHomeRb
@Override
protected void onStart() {
super.onStart();
mHomeRadioGroup.check(R.id.mHomeHomeRb);
} //用adapter来管理四个Fragment界面的变化。注意,我这里用的Fragment都是v4包里面的
FragmentStatePagerAdapter fragments = new FragmentStatePagerAdapter(getSupportFragmentManager()) { @Override
public int getCount() {
return NUM_ITEMS;//一共有四个Fragment
} //进行Fragment的初始化
@Override
public Fragment getItem(int i) {
Fragment fragment = null;
switch (i) {
case 0://首页
fragment = new HomeFagment();
break;
case 1://发现
fragment = new FindFagment();
break; case 2://搜索
fragment = new SearchFagment();
break; case 3://我的
fragment = new ProfileFagment();
break;
default:
new HomeFagment();
break;
} return fragment;
}
}; protected void initData() { } }
代码注释已经很详细了。
尤其要注意的是第80行的注释,为了让app第一次启动时,默认就让第一个tab处于选中状态,我们现在activity_home.xml(76行)中让剩下的随便哪个radioButton的属性为checked,然后再重写上方java代码中的onStart方法(86行)。
(2)HomeFragment.java:
package com.smyhvae.radiogrouptabdemo.fragment; import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup; import com.smyhvae.radiogrouptabdemo.R; /**
* Created by smyh on 2015/4/28.
*/
public class HomeFagment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_home, null);
return view;
} //重写setMenuVisibility方法,不然会出现叠层的现象
@Override
public void setMenuVisibility(boolean menuVisibile) {
super.setMenuVisibility(menuVisibile);
if (this.getView() != null) {
this.getView().setVisibility(menuVisibile ? View.VISIBLE : View.GONE);
}
} }
剩下三个Fragment的java代码是一样的,就不贴出来了,详见本文最后的源码。
【工程文件】
Android自定义控件----RadioGroup实现APP首页底部Tab的切换的更多相关文章
- Android之RadioGroup+ViewPager制作的底部导航栏
在日常开发中我们常常会用到类似微信或者QQ的底部导航.实现这样的效果有多种,今天就为大家介绍一种实现简单,可控性好的底部导航的实现方法. 首先创建activity_main.xml布局文件,里面主要由 ...
- Fragment实现底部Tab,切换可保存状态
activity_main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android& ...
- react native底部tab栏切换
1.安装tab栏插件 npm i react-native-tab-navigator --save 2.引入对应的组件和tab插件 import { Platform, StyleSheet, Te ...
- Android Studio精彩案例(二)《仿微信动态点击底部tab切换Fragment》
转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 现在很多的App要么顶部带有tab,要么就底部带有tab.用户通过点击tab从而切换不同的页面(大部分情况时去切换fragment). ...
- Android典型界面设计——FragmentTabHost+Fragment实现底部tab切换
一.问题描述 在上次博文中,我们使用RadioGroup+ViewPage+Fragmen实现了顶部滑动导航(查看文章:http://www.cnblogs.com/jerehedu/p/460759 ...
- Android 自定义控件之app标题栏的封装
在app的开发中,每一个页面都有上面的标题栏,总不能在开发的过程中没个界面都写一个标题栏的布局,所以为了开发的方便,将该标题栏进行的封装,以后在实际的开发工作中,也可以将该封装好的标题栏控件直接拿来使 ...
- 使用hubuild,mui开发微信app—首页(一)
写在前面 本系列文章我将介绍一下从零开始利用hubuild,mui实现微信app的开发,该系列是个人学习记录,所以在每篇文章中,都是从怎么去实现开始讲解,然后再把实例中涉及知识点做一个概述. 创建一个 ...
- 界面底部Tab实现
现在基本上大部分的手机APP都要实现底部Tab,底部实现Tab的实现方式有很多种,那么有没有好的实现方式呢? 今天我将使用一个开源插件来实现底部Tab 参考自zhangli_的博客:http://bl ...
- [Android] Android 使用 FragmentTabHost + Fragment 实现 微信 底部菜单
Android 使用 FragmentTabHost + Fragment 实现 微信 底部菜单 利用FragmentTabHost实现底部菜单,在该底部菜单中,包括了4个TabSpec,每个TabS ...
随机推荐
- Linux C 静态库(.a) 与 动态库(.so) 的详解
库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行.库分静态库和动态库两种. 一.静态库和动态库的区别 1.静态函数库 这类库的名字一般是libxxx.a:利用静态函数库编译成的文件比较 ...
- C和指针 第八章 习题
8.5矩阵运算,A是一个x行,y列矩阵,B是y行z列矩阵,把A和B相乘,结果是另外一个x行z列矩阵,每个位置的值由下公式决定,编写函数: #include <stdio.h> void m ...
- 2.1WebApi的路由
这篇文章描述 ASP.NET Web API如何将 HTTP 请求通过路由去访问控制器. 如果你熟悉 ASP.NET MVC,Web API 路由是非常类似于 MVC 路由.主要的区别是 Web AP ...
- mapReduce编程之Recommender System
1 协同过滤算法 协同过滤算法是现在推荐系统的一种常用算法.分为user-CF和item-CF. 本文的电影推荐系统使用的是item-CF,主要是由于用户数远远大于电影数,构建矩阵的代价更小:另外,电 ...
- 【krpano】krpano xml资源解密(破解)软件说明与下载(v1.2)
欢迎加入qq群551278936讨论krpano技术以及获取最新软件. 该软件已经不再维护,现在已经被KRPano资源分析工具取代,详情参见 http://www.cnblogs.com/reac ...
- InnoDB全文索引:N-gram Parser【转】
本文来自:http://mysqlserverteam.com/innodb%E5%85%A8%E6%96%87%E7%B4%A2%E5%BC%95%EF%BC%9An-gram-parser/ In ...
- seajs和requirejs
一.seajs 1. 使用seajs的一般步骤 a)在主页面引入sea.js b)写模块 c)在主页面使用模块 2.模块的写法 math.js define(function(require, exp ...
- October 23rd Week 44th Sunday 2016
When ambition ends, happiness begins. 野心消亡之日,正是快乐破茧之时. No ambition, no annoyance. No ambition, no ac ...
- navigation和tabbar上的文字.图片 自定义
[[UITabBarItem appearance] setTitleTextAttributes:@{ UITextAttributeTextColor : [UIColor blackColor] ...
- 适配器模式/adapter模式/结构型模式
定义 将类的接口转化为客户端希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作,别名Wrapper(包装器). 适配器模式,最终改变一个已有对象的接口. 使用场景 当有那么个类, ...