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

实现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的布局文件

<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();
 86         mHomeRadioGroup.check(R.id.mHomeHomeRb);
 87     }
 
     //用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代码是一样的,就不贴出来了,详见本文最后的源码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值