Android之RadioGroup+ViewPager制作的底部导航栏

在日常开发中我们常常会用到类似微信或者QQ的底部导航。实现这样的效果有多种,今天就为大家介绍一种实现简单,可控性好的底部导航的实现方法。

首先创建activity_main.xml布局文件,里面主要由ViewPager和RadioGroup构成。ViewPager用来存放Fragment,RadioGroup布局底部导航。

<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"
    android:orientation="vertical" >

    <android.support.v4.view.ViewPager
        android:id="@+id/packpage_vPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_gravity="center"
        android:layout_weight="1.0" />

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/orange_line" />

    <RadioGroup
        android:id="@+id/main_navi_radiogroup"
        style="@style/main_navi_radiogroup">

        <RadioButton
            android:id="@+id/main_navi_msg_records"
            style="@style/main_navi_radiobutton"
            android:drawableTop="@drawable/menu_item_msg_records"
            android:text="@string/message"/>

        <RadioButton
            android:id="@+id/main_navi_contact"
            style="@style/main_navi_radiobutton"
            android:drawableTop="@drawable/menu_item_contacts"
            android:text="@string/call" />

    </RadioGroup>

</LinearLayout>

接着再创建两个fragment布局文件

fragment_message.xml

<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"
    android:orientation="vertical" >

    <TextView 
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:layout_gravity="center"
       android:gravity="center"
       android:textSize="20sp"
       android:text="@string/message"/>

</LinearLayout>

fragment_call.xml

<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"
    android:orientation="vertical" >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:gravity="center"
        android:text="@string/call"
        android:textSize="20sp" />

</LinearLayout>

两个fragment布局文件创建完成后,再创建两个Fragment类,MessageFragment和CallFragment,均继承android.support.v4.app.Fragment;

MessageFragment.java

package com.syz.bottommenu;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * @author syz
 * @date 2016-4-14
 */
public class MessageFragment extends Fragment {

    private View mView;
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if(mView == null){
            mView = inflater.inflate(R.layout.fragment_message, container, false);
        }
        return mView;
    }
    
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        ((ViewGroup) mView.getParent()).removeView(mView);
    }
}

CallFragment.Java

package com.syz.bottommenu;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * @author syz
 * @date 2016-4-14
 */
public class CallFragment extends Fragment {

    private View mView;

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (mView == null) {
            mView = inflater.inflate(R.layout.fragment_call, container, false);
        }
        return mView;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        ((ViewGroup) mView.getParent()).removeView(mView);
    }
}

最后我们在MainActivity中开始布局渲染。

MainActivity.java

package com.syz.bottommenu;

import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.RadioGroup;

public class MainActivity extends FragmentActivity implements OnPageChangeListener, OnClickListener {

    private ViewPager pager;
    private List<Fragment> fragments;
    private RadioGroup radioGroup;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        pager = (ViewPager) findViewById(R.id.packpage_vPager);
        radioGroup = (RadioGroup) findViewById(R.id.main_navi_radiogroup);
        findViewById(R.id.main_navi_msg_records).setOnClickListener(this);
        findViewById(R.id.main_navi_contact).setOnClickListener(this);
        fragments = new ArrayList<Fragment>();
        fragments.add(new MessageFragment());
        fragments.add(new CallFragment());

        pager.setAdapter(new FragmentPagerAdapter(this.getSupportFragmentManager()) {

            @Override
            public int getCount() {
                return fragments.size();
            }

            @Override
            public Fragment getItem(int arg0) {
                return fragments.get(arg0);
            }
        });
        // 添加页面切换事件的监听器
        pager.setOnPageChangeListener(this);
        radioGroup.check(R.id.main_navi_msg_records);
    }

    @Override
    public void finish() {
        ViewGroup view = (ViewGroup) getWindow().getDecorView();
        view.removeAllViews();
        super.finish();
    }

    /**
     * 这个方法在手指操作屏幕的时候发生变化。有三个值:0(END),1(PRESS) , 2(UP) 。
     * 当用手指滑动翻页时,手指按下去的时候会触发这个方法,state值为1,手指抬起时, 
     * 如果发生了滑动(即使很小),这个值会变为2,然后最后变为0
     * 。总共执行这个方法三次。一种特殊情况是手指按下去以后一点滑动也没有发生,
     * 这个时候只会调用这个方法两次,state值分别是1,0 。
     * 当setCurrentItem翻页时,会执行这个方法两次,state值分别为2 , 0 。
     */
    @Override
    public void onPageScrollStateChanged(int state) {

    }

    /**
     * 这个方法会在屏幕滚动过程中不断被调用。 有三个参数,第一个position,这个参数要特别注意一下。
     * 当用手指滑动时,如果手指按在页面上不动,position和当前页面index是一致的;
     * 如果手指向左拖动(相应页面向右翻动),这时候position大部分时间和当前页面是一致的,
     * 只有翻页成功的情况下最后一次调用才会变为目标页面;如果手指向右拖动(相应页面向左翻动),
     * 这时候position大部分时间和目标页面是一致的,只有翻页不成功的情况下最后一次调用才会变为原页面。
     * 当直接设置setCurrentItem翻页时,如果是相邻的情况(比如现在是第二个页面,跳到第一或者第三个页面),
     * 如果页面向右翻动,大部分时间是和当前页面是一致的,只有最后才变成目标页面;
     * 如果向左翻动,position和目标页面是一致的。这和用手指拖动页面翻动是基本一致的。如果不是相邻的情况,
     * 比如我从第一个页面跳到第三个页面,position先是0,然后逐步变成1,然后逐步变成2;
     * 我从第三个页面跳到第一个页面,position先是1,然后逐步变成0,并没有出现为2的情况。
     * positionOffset是当前页面滑动比例,如果页面向右翻动,这个值不断变大,最后在趋近1的情况后突变为0
     * 。如果页面向左翻动,这个值不断变小,
     * 最后变为0。positionOffsetPixels是当前页面滑动像素,变化情况和positionOffset一致
     */
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    /**
     * 这个方法有一个参数position,代表哪个页面被选中。当用手指滑动翻页的时候,如果翻动成功了(滑动的距离够长),
     * 手指抬起来就会立即执行这个方法,position就是当前滑动到的页面。如果直接setCurrentItem翻页,
     * 那position就和setCurrentItem的参数一致,这种情况在onPageScrolled执行方法前就会立即执行。
     */
    @Override
    public void onPageSelected(int position) {
        switch (position) {
        case 0:
            radioGroup.check(R.id.main_navi_msg_records);
            break;
        case 1:
            radioGroup.check(R.id.main_navi_contact);
            break;

        default:
            break;
        }

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.main_navi_contact:
            pager.setCurrentItem(1,true);
            break;
        case R.id.main_navi_msg_records:
            pager.setCurrentItem(0,true);
            break;

        default:
            break;
        }
    }

}

从上面的代码中可以看出,这种实现方式非常的简洁,可控性也非常好。之前看过的别人的实现方式都比较繁琐。所以推荐大家使用这种方式。当然,每个人都有不同看法,不同的实现方式,适合自己的才是最好的。

 

效果图:

       

在日常开发中我们常常会用到类似微信或者QQ的底部导航。实现这样的效果有多种,今天就为大家介绍一种实现简单,可控性好的底部导航的实现方法。

首先创建activity_main.xml布局文件,里面主要由ViewPager和RadioGroup构成。ViewPager用来存放Fragment,RadioGroup布局底部导航。

 

[html] view plain copy
 
 print?
  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.     android:orientation="vertical" >  
  6.   
  7.     <android.support.v4.view.ViewPager  
  8.         android:id="@+id/packpage_vPager"  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="0dp"  
  11.         android:layout_gravity="center"  
  12.         android:layout_weight="1.0" />  
  13.   
  14.     <View  
  15.         android:layout_width="match_parent"  
  16.         android:layout_height="1dp"  
  17.         android:background="@color/orange_line" />  
  18.   
  19.     <RadioGroup  
  20.         android:id="@+id/main_navi_radiogroup"  
  21.         style="@style/main_navi_radiogroup">  
  22.   
  23.         <RadioButton  
  24.             android:id="@+id/main_navi_msg_records"  
  25.             style="@style/main_navi_radiobutton"  
  26.             android:drawableTop="@drawable/menu_item_msg_records"  
  27.             android:text="@string/message"/>  
  28.   
  29.         <RadioButton  
  30.             android:id="@+id/main_navi_contact"  
  31.             style="@style/main_navi_radiobutton"  
  32.             android:drawableTop="@drawable/menu_item_contacts"  
  33.             android:text="@string/call" />  
  34.   
  35.     </RadioGroup>  
  36.   
  37. </LinearLayout>  

 

 

接着再创建两个fragment布局文件

fragment_message.xml

 

[html] view plain copy
 
 print?
  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.     android:orientation="vertical" >  
  6.   
  7.     <TextView   
  8.        android:layout_width="match_parent"  
  9.        android:layout_height="match_parent"  
  10.        android:layout_gravity="center"  
  11.        android:gravity="center"  
  12.        android:textSize="20sp"  
  13.        android:text="@string/message"/>  
  14.   
  15. </LinearLayout>  


fragment_call.xml

 

 

[html] view plain copy
 
 print?
  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.     android:orientation="vertical" >  
  6.   
  7.     <TextView  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="match_parent"  
  10.         android:layout_gravity="center"  
  11.         android:gravity="center"  
  12.         android:text="@string/call"  
  13.         android:textSize="20sp" />  
  14.   
  15. </LinearLayout>  


两个fragment布局文件创建完成后,再创建两个Fragment类,MessageFragment和CallFragment,均继承android.support.v4.app.Fragment;

 

MessageFragment.java

 

[java] view plain copy
 
 print?
  1. package com.syz.bottommenu;  
  2.   
  3. import android.os.Bundle;  
  4. import android.support.annotation.Nullable;  
  5. import android.support.v4.app.Fragment;  
  6. import android.view.LayoutInflater;  
  7. import android.view.View;  
  8. import android.view.ViewGroup;  
  9.   
  10. /** 
  11.  * @author syz 
  12.  * @date 2016-4-14 
  13.  */  
  14. public class MessageFragment extends Fragment {  
  15.   
  16.     private View mView;  
  17.     @Override  
  18.     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {  
  19.         if(mView == null){  
  20.             mView = inflater.inflate(R.layout.fragment_message, container, false);  
  21.         }  
  22.         return mView;  
  23.     }  
  24.       
  25.     @Override  
  26.     public void onDestroyView() {  
  27.         super.onDestroyView();  
  28.         ((ViewGroup) mView.getParent()).removeView(mView);  
  29.     }  
  30. }  

 

 

CallFragment.Java

 

[java] view plain copy
 
 print?
  1. package com.syz.bottommenu;  
  2.   
  3. import android.os.Bundle;  
  4. import android.support.annotation.Nullable;  
  5. import android.support.v4.app.Fragment;  
  6. import android.view.LayoutInflater;  
  7. import android.view.View;  
  8. import android.view.ViewGroup;  
  9.   
  10. /** 
  11.  * @author syz 
  12.  * @date 2016-4-14 
  13.  */  
  14. public class CallFragment extends Fragment {  
  15.   
  16.     private View mView;  
  17.   
  18.     @Override  
  19.     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {  
  20.         if (mView == null) {  
  21.             mView = inflater.inflate(R.layout.fragment_call, container, false);  
  22.         }  
  23.         return mView;  
  24.     }  
  25.   
  26.     @Override  
  27.     public void onDestroyView() {  
  28.         super.onDestroyView();  
  29.         ((ViewGroup) mView.getParent()).removeView(mView);  
  30.     }  
  31. }  

 

 

最后我们在MainActivity中开始布局渲染。

MainActivity.java

 

[java] view plain copy
 
 print?
  1. package com.syz.bottommenu;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import android.os.Bundle;  
  7. import android.support.v4.app.Fragment;  
  8. import android.support.v4.app.FragmentActivity;  
  9. import android.support.v4.app.FragmentPagerAdapter;  
  10. import android.support.v4.view.ViewPager;  
  11. import android.support.v4.view.ViewPager.OnPageChangeListener;  
  12. import android.view.View;  
  13. import android.view.View.OnClickListener;  
  14. import android.view.ViewGroup;  
  15. import android.widget.RadioGroup;  
  16.   
  17. public class MainActivity extends FragmentActivity implements OnPageChangeListener, OnClickListener {  
  18.   
  19.     private ViewPager pager;  
  20.     private List<Fragment> fragments;  
  21.     private RadioGroup radioGroup;  
  22.   
  23.     @Override  
  24.     protected void onCreate(Bundle savedInstanceState) {  
  25.         super.onCreate(savedInstanceState);  
  26.         setContentView(R.layout.activity_main);  
  27.         initView();  
  28.     }  
  29.   
  30.     private void initView() {  
  31.         pager = (ViewPager) findViewById(R.id.packpage_vPager);  
  32.         radioGroup = (RadioGroup) findViewById(R.id.main_navi_radiogroup);  
  33.         findViewById(R.id.main_navi_msg_records).setOnClickListener(this);  
  34.         findViewById(R.id.main_navi_contact).setOnClickListener(this);  
  35.         fragments = new ArrayList<Fragment>();  
  36.         fragments.add(new MessageFragment());  
  37.         fragments.add(new CallFragment());  
  38.   
  39.         pager.setAdapter(new FragmentPagerAdapter(this.getSupportFragmentManager()) {  
  40.   
  41.             @Override  
  42.             public int getCount() {  
  43.                 return fragments.size();  
  44.             }  
  45.   
  46.             @Override  
  47.             public Fragment getItem(int arg0) {  
  48.                 return fragments.get(arg0);  
  49.             }  
  50.         });  
  51.         // 添加页面切换事件的监听器  
  52.         pager.setOnPageChangeListener(this);  
  53.         radioGroup.check(R.id.main_navi_msg_records);  
  54.     }  
  55.   
  56.     @Override  
  57.     public void finish() {  
  58.         ViewGroup view = (ViewGroup) getWindow().getDecorView();  
  59.         view.removeAllViews();  
  60.         super.finish();  
  61.     }  
  62.   
  63.     /** 
  64.      * 这个方法在手指操作屏幕的时候发生变化。有三个值:0(END),1(PRESS) , 2(UP) 。 
  65.      * 当用手指滑动翻页时,手指按下去的时候会触发这个方法,state值为1,手指抬起时,  
  66.      * 如果发生了滑动(即使很小),这个值会变为2,然后最后变为0 
  67.      * 。总共执行这个方法三次。一种特殊情况是手指按下去以后一点滑动也没有发生, 
  68.      * 这个时候只会调用这个方法两次,state值分别是1,0 。 
  69.      * 当setCurrentItem翻页时,会执行这个方法两次,state值分别为2 , 0 。 
  70.      */  
  71.     @Override  
  72.     public void onPageScrollStateChanged(int state) {  
  73.   
  74.     }  
  75.   
  76.     /** 
  77.      * 这个方法会在屏幕滚动过程中不断被调用。 有三个参数,第一个position,这个参数要特别注意一下。 
  78.      * 当用手指滑动时,如果手指按在页面上不动,position和当前页面index是一致的; 
  79.      * 如果手指向左拖动(相应页面向右翻动),这时候position大部分时间和当前页面是一致的, 
  80.      * 只有翻页成功的情况下最后一次调用才会变为目标页面;如果手指向右拖动(相应页面向左翻动), 
  81.      * 这时候position大部分时间和目标页面是一致的,只有翻页不成功的情况下最后一次调用才会变为原页面。 
  82.      * 当直接设置setCurrentItem翻页时,如果是相邻的情况(比如现在是第二个页面,跳到第一或者第三个页面), 
  83.      * 如果页面向右翻动,大部分时间是和当前页面是一致的,只有最后才变成目标页面; 
  84.      * 如果向左翻动,position和目标页面是一致的。这和用手指拖动页面翻动是基本一致的。如果不是相邻的情况, 
  85.      * 比如我从第一个页面跳到第三个页面,position先是0,然后逐步变成1,然后逐步变成2; 
  86.      * 我从第三个页面跳到第一个页面,position先是1,然后逐步变成0,并没有出现为2的情况。 
  87.      * positionOffset是当前页面滑动比例,如果页面向右翻动,这个值不断变大,最后在趋近1的情况后突变为0 
  88.      * 。如果页面向左翻动,这个值不断变小, 
  89.      * 最后变为0。positionOffsetPixels是当前页面滑动像素,变化情况和positionOffset一致 
  90.      */  
  91.     @Override  
  92.     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {  
  93.   
  94.     }  
  95.   
  96.     /** 
  97.      * 这个方法有一个参数position,代表哪个页面被选中。当用手指滑动翻页的时候,如果翻动成功了(滑动的距离够长), 
  98.      * 手指抬起来就会立即执行这个方法,position就是当前滑动到的页面。如果直接setCurrentItem翻页, 
  99.      * 那position就和setCurrentItem的参数一致,这种情况在onPageScrolled执行方法前就会立即执行。 
  100.      */  
  101.     @Override  
  102.     public void onPageSelected(int position) {  
  103.         switch (position) {  
  104.         case 0:  
  105.             radioGroup.check(R.id.main_navi_msg_records);  
  106.             break;  
  107.         case 1:  
  108.             radioGroup.check(R.id.main_navi_contact);  
  109.             break;  
  110.   
  111.         default:  
  112.             break;  
  113.         }  
  114.   
  115.     }  
  116.   
  117.     @Override  
  118.     public void onClick(View v) {  
  119.         switch (v.getId()) {  
  120.         case R.id.main_navi_contact:  
  121.             pager.setCurrentItem(1,true);  
  122.             break;  
  123.         case R.id.main_navi_msg_records:  
  124.             pager.setCurrentItem(0,true);  
  125.             break;  
  126.   
  127.         default:  
  128.             break;  
  129.         }  
  130.     }  
  131.   
  132. }  


从上面的代码中可以看出,这种实现方式非常的简洁,可控性也非常好。之前看过的别人的实现方式都比较繁琐。所以推荐大家使用这种方式。当然,每个人都有不同看法,不同的实现方式,适合自己的才是最好的。

 

效果图:

       



最后附上源码下载地址:http://download.csdn.net/detail/loveyaozu/9490650

原文地址:https://www.cnblogs.com/zhujiabin/p/7301743.html