Android底部导航栏创建——ViewPager + RadioGroup
原创文章,引用请注明出处:http://www.cnblogs.com/baipengzhan/p/6270201.html
Android底部导航栏有多种实现方式,本文详解其中的ViewPager + RadioGroup方式的实现步骤。
我们先来看以下看一下最终做出的效果,使大家有个基本概念。
本结构特点:
1,ViewPager部分触摸左右滑动切换页面,RadioGroup部分中的RadioButton随着自己对应的ViewPager页面出现选中时的状态,包括改变背景颜色,
改变文字颜色,改变图片。其他RadioButton则是未被选中时的状态;
2,当用户点击RadioGroup部分中的RadioButton,被点击的RadioButton出现被选中时的颜色,ViewPager界面对应于RadioButton的页面会出现在当前界面。
可以看到,ViewPager和RadioGroup可以双向联动,不是单向传递。
下面我们通过一个实例完全弄懂ViewPager + RadioGroup结构的用法
首先创建出我们界面的布局,上边一个ViewPager,中间 一条分隔线,下边一个RadioGroup
我们在一个Activity的布局中创建如下的xml文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<!--上边为ViewPager-->
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
<!--中间为一条分割线-->
<View
android:background="@color/divider"
android:layout_width="match_parent"
android:layout_height="1dp"/>
<!--最下边为RadioGroup-->
<RadioGroup
android:id="@+id/radioGroup"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--第一个RadioButton-->
<RadioButton
android:id="@+id/button_1"
android:text="button_1"
android:button="@null"
android:textColor="@color/radiobutton_color_selector"
android:background="@drawable/radiobutton_bg_selector"
android:gravity="center"
android:layout_weight="1"
android:drawableTop="@drawable/radiobutton_pic_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!--第二个RadioButton-->
<RadioButton
android:id="@+id/button_2"
android:text="button_2"
android:button="@null"
android:textColor="@color/radiobutton_color_selector"
android:background="@drawable/radiobutton_bg_selector"
android:gravity="center"
android:layout_weight="1"
android:drawableTop="@drawable/radiobutton_pic_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!--第三个RadioButton-->
<RadioButton
android:id="@+id/button_3"
android:text="button_3"
android:button="@null"
android:textColor="@color/radiobutton_color_selector"
android:background="@drawable/radiobutton_bg_selector"
android:gravity="center"
android:layout_weight="1"
android:drawableTop="@drawable/radiobutton_pic_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!--第四个RadioButton-->
<RadioButton
android:id="@+id/button_4"
android:text="button_4"
android:button="@null"
android:textColor="@color/radiobutton_color_selector"
android:background="@drawable/radiobutton_bg_selector"
android:gravity="center"
android:layout_weight="1"
android:drawableTop="@drawable/radiobutton_pic_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RadioGroup>
</LinearLayout>
布局中重要属性说明:
①ViewPager的android:layout_height属性值为0,android:layout_weight属性值为1。这两个属性值配合使用的意义是:
在竖直方向上ViewPager占满父控件的剩余空间,也就是占据LinearLayout中除去分隔线和RadioGroup的剩余空间。
关于android:layout_weight属性的详细用法请参考:http://www.cnblogs.com/baipengzhan/p/Android_layout_weight.html
②RadioButton的android:button属性值为@null。这个属性值的意义是,去除RadioGroup默认自带显示的小圆圈。
③RadioButton的android:gravity属性值为center。这个属性值的意义是,使RadioButton的内容(图片和文字)居中。注意,内容默认情况没有居中。
④RadioGroup的android:orientation属性值为horizontal。意为,水平布置其中的RadioButton。
⑤RadioButton的android:textColor属性值为@color/radiobutton_color_selector,是一个颜色状态选择器。颜色状态选择器就是一个定义在res/color目录
下的xml文件,color目录需要我们手动创建。颜色状态选择器的代码如下:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="#f00" android:state_checked="true"/> <item android:color="#f00" android:state_pressed="true"/> <item android:color="#f00" android:state_selected="true"/> <!--没被选中时的颜色--> <item android:color="#000"/> </selector>
关于状态选择器的更详细知识,请参考文章http://www.cnblogs.com/baipengzhan/p/6284682.html
⑥RadioButton的android:background属性值为@drawable/radiobutton_bg_selector,这一个背景状态选择器,用来改变背景颜色,代码如下:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="true" android:drawable="@color/radiobutton_bg_selected"/> <item android:state_checked="true" android:drawable="@color/radiobutton_bg_selected"/> <item android:state_pressed="true" android:drawable="@color/radiobutton_bg_selected"/> <!--未被选中--> <item android:drawable="@color/radiobutton_bg_normal" /> </selector>
这个状态选择器是放置在res/drawable目录下的一个普通状态选择器,该选择器的属性android:drawable的属性值不能直接设置颜色,
颜色要封装在values目录下的colors.xml文件中,否则出错。
⑦RadioButton的android:drawableTop属性值为@drawable/radiobutton_pic_selector,是一个普通的状态选择器,用来改变图片,代码如下:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="true" android:drawable="@mipmap/ic_selected"/> <item android:state_checked="true" android:drawable="@mipmap/ic_selected"/> <item android:state_pressed="true" android:drawable="@mipmap/ic_selected"/> <!--未被选中--> <item android:drawable="@mipmap/ic_launcher"/> </selector>
该状态选择器同样放置在res/drawable目录下,选择器的属性值android:drawable属性值变为了图片,注意代码写到此处时,系统可能不会提示,
需要手动将该属性值添加进来。
更多关于状态选择器的知识请参考文章http://www.cnblogs.com/baipengzhan/p/6284682.html
创建出ViewPager页面盛放的Fragment
我们创建出对应于四个RadioButton的四个Fragment,每个Fragment中盛放一个TextView。下边只列出一个Fragment的写法,剩余的相似,请各位朋友自己写写哦。
public class Fragment_1 extends Fragment {
private View mView;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//注意View对象的重复使用,以便节省资源
if(mView == null) {
mView = inflater.inflate(R.layout.fragment_1_layout,container,false);
}
return mView;
}
}
Fragment_1对应的布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:gravity="center" android:layout_width="match_parent" android:layout_height="match_parent"> <!--创建TextView--> <TextView android:text="pager_1" android:textSize="28sp" android:textColor="#00f" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
在Activity中进行主要逻辑处理
我们在Activity中主要进行的工作如下:
①监听ViewPager,改变RadioGroup中的RadioButton;
②监听RadioGroup中的RadioButton,改变ViewPager;
代码如下:
package com.example.chironmy.bottomnavigation; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.view.ViewGroup; import android.widget.RadioButton; import android.widget.RadioGroup; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity implements View.OnClickListener,ViewPager.OnPageChangeListener{ private ViewPager viewPager; private RadioGroup radioGroup; private RadioButton button_1; private RadioButton button_2; private RadioButton button_3; private RadioButton button_4; private Fragment_1 fragment_1; private Fragment_2 fragment_2; private Fragment_3 fragment_3; private Fragment_4 fragment_4; private List<Fragment> list; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化界面 initView(); } //初始化界面 private void initView() { viewPager = (ViewPager) findViewById(R.id.viewpager); radioGroup = (RadioGroup) findViewById(R.id.radioGroup); //找到四个按钮 button_1 = (RadioButton) findViewById(R.id.button_1); button_2 = (RadioButton) findViewById(R.id.button_2); button_3 = (RadioButton) findViewById(R.id.button_3); button_4 = (RadioButton) findViewById(R.id.button_4); //创建Fragment对象及集合 fragment_1 = new Fragment_1(); fragment_2 = new Fragment_2(); fragment_3 = new Fragment_3(); fragment_4 = new Fragment_4(); //将Fragment对象添加到list中 list = new ArrayList<>(); list.add(fragment_1); list.add(fragment_2); list.add(fragment_3); list.add(fragment_4); //给viewPager设置适配器,以显示内容 MyViewPagerAdapter adapter = new MyViewPagerAdapter(getSupportFragmentManager()); viewPager.setAdapter(adapter); //设置RadioGroup开始时设置的按钮,设置第一个按钮为默认值 radioGroup.check(R.id.button_1); //设置Viewpager第一次显示的页面 viewPager.setCurrentItem(0,true); //设置按钮点击监听 button_1.setOnClickListener(this); button_2.setOnClickListener(this); button_3.setOnClickListener(this); button_4.setOnClickListener(this); //设置ViewPager页面监听 viewPager.addOnPageChangeListener(this); } @Override public void finish() { ViewGroup viewGroup = (ViewGroup) getWindow().getDecorView(); viewGroup.removeAllViews(); super.finish(); } //创建ViewPager盛放Fragment的适配器类 public class MyViewPagerAdapter extends FragmentPagerAdapter { public MyViewPagerAdapter(FragmentManager fm) { super(fm); } //返回每个position对应的Fragment对象 @Override public Fragment getItem(int position) { return list.get(position); } //返回list的长度,也就是Fragment对象的个数 @Override public int getCount() { return list.size(); } } //处理点击的方法 @Override public void onClick(View v) { //我们根据参数的id区别不同按钮 //不同按钮对应着不同的ViewPager页面 switch (v.getId()) { case R.id.button_1: viewPager.setCurrentItem(0,true); break; case R.id.button_2: viewPager.setCurrentItem(1,true); break; case R.id.button_3: viewPager.setCurrentItem(2,true); break; case R.id.button_4: viewPager.setCurrentItem(3,true); break; default: break; } } //处理页面变化的方法 @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } //本文章中我们使用这个方法,本方法处理页面变化后,也就是切换了不同的页面后所做的操作 @Override public void onPageSelected(int position) { //根据当前展示的ViewPager页面,使RadioGroup对应的按钮被选中 switch (position) { case 0: radioGroup.check(R.id.button_1); break; case 1: radioGroup.check(R.id.button_2); break; case 2: radioGroup.check(R.id.button_3); break; case 3: radioGroup.check(R.id.button_4); break; default: break; } } @Override public void onPageScrollStateChanged(int state) { } }
注意:在onClick方法中,viewPager的setCurrentItem方法中的第二个参数的意义是:
当该参数为true时,viewPager换页时是平滑的换页,会有页面移动的效果;
该参数为false时,viewPager换页效果没有平滑的移动,页面会直接出现。
该方法有一个参数的重载方法,默认有平滑换页效果。
以上代码中很多可以优化,比如xml文件中大量的属性可以提取样式,等等,这里列出只是为了方便更多水平的读者读懂,请谅解。
好啦,ViewPager + RadioGroup结构我们到此就讲解完成了,感谢阅读!