程序员人生 网站导航

Android 必知必会 - RadioGroup 和 ViewPager 联动

栏目:综合技术时间:2016-09-25 08:58:42

如果移动端访问不佳或需要更好的浏览体验,欢迎使用 ==> Github 版

使用 RadioGroup 和 ViewPager 实现更加可定制的效果。

背景

昨天设计图刚出1点,写了《Android 必知必会 - 动态切换着色模式和全屏模式》,记录了动态修改页面显示模式的方式。今天又有新图,不过设计师只斟酌 iOS 平台的设计,拿到设计图发现 TabLayout + ViewPager 的套路实现起来很麻烦,斟酌了下,为了方便,决定使用 RadioGroup + ViewPager 来实现,之所以使用 RadioGroup ,是由于它内部多个 RadioButton 的状态是互斥的,也就是只有1个是选中状态,不需要我们进行过剩的处理。整体来讲比较简单,就是细节略多了点。

主要知识点:

  • 自定义 RadioButton 样式 : selector + shape
  • 自定义 RadioButton 文字样式 : selector
  • ViewPager + Fragment 及其适配器
  • RadioGroup 状态监听
  • ViewPager 页面切换监听

实现

先看效果图:

思路

UI:

  • 顶部是 RadioGroup ,内部包括两个 RadioButton
    • RadioButton 需要自定义背景和文字
  • 中间是 ViewPager

联动事件:

  • ViewPager
    • 需要为 ViewPager 写适配器,以配合 Fragment
    • 使用 addOnPageChangeListener() 为其添加监听页面变动的事件
    • onPageSelected(int position) 方法中修改 RadioGroupRadioButton 的选中状态
  • RadioGroup
    • 设置 setOnCheckedChangeListener 监听,并在其中修改 ViewPager 的状态

实现 UI

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <RelativeLayout android:layout_width="match_parent" android:layout_height="45dp" android:background="@color/title_bar"> <RadioGroup android:id="@+id/main_top_rg" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_centerInParent="true" android:gravity="center" android:orientation="horizontal"> <RadioButton android:id="@+id/top_rg_a" android:layout_width="76dp" android:layout_height="29dp" android:background="@drawable/top_r_bg" android:button="@null" android:checked="true" android:gravity="center" android:text="@string/main_tab1" android:textColor="@drawable/top_r_text" android:textColorHighlight="@color/title_bar" android:textSize="15sp"/> <RadioButton android:id="@+id/top_rg_b" android:layout_width="76dp" android:layout_height="29dp" android:background="@drawable/top_r_bg2" android:button="@null" android:gravity="center" android:layout_marginLeft="⑴dp" android:text="@string/main_tab2" android:textColor="@drawable/top_r_text" android:textColorHighlight="@color/title_bar" android:textSize="15sp"/> </RadioGroup> <ImageView android:id="@+id/main_top_right" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:paddingLeft="@dimen/left_padding" android:paddingRight="@dimen/right_padding" android:src="@drawable/main_search" /> </RelativeLayout> <android.support.v4.view.ViewPager android:id="@+id/main_viewpager" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> </LinearLayout>

重点在 RadioButton 的几个属性:

  • android:button="@null" 隐藏 RadioButton 默许的图标
  • android:background="@drawable/top_r_bg" 设置背景,实际上是1个 selector
  • android:textColor="@drawable/top_r_text" 设置文字色彩,它也是1个 selector
  • 对第2个 RadioButtonandroid:layout_marginLeft="⑴dp" 和描边宽度1样,避免出现间隙

下面把 xml 代码放在1起看,它们都放在 drawable 目录下:

<!-- drawable/top_r_bg --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/top_r_bg_a" android:state_checked="false"/> <item android:drawable="@drawable/top_r_bg_b" android:state_checked="true"/> </selector> <!-- drawable/top_r_bg_a --> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <corners android:bottomLeftRadius="2dp" android:bottomRightRadius="0dp" android:topLeftRadius="2dp" android:topRightRadius="0dp" /> <stroke android:width="1dp" android:color="@color/white"/> <solid android:color="@color/transparent"/> </shape> <!-- drawable/top_r_bg_b --> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <corners android:bottomLeftRadius="2dp" android:topLeftRadius="2dp"/> <solid android:color="@color/white"/> </shape> <!-- drawable/top_r_text --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@color/white" android:state_checked="false"/> <item android:color="@color/title_bar" android:state_checked="true"/> </selector>

上面只贴出了左侧按钮的样式,右侧的类似,不再张贴。UI 到这里已完成,下面看事件:

实现联动事件

private void init() { List<Fragment> fragments = new ArrayList<>(); fragments.add(new FragmentMain01A()); fragments.add(new FragmentMain01B()); NotePagerAdapter pagerAdapter = new NotePagerAdapter(getFragmentManager(), fragments); mainViewpager.setAdapter(pagerAdapter); /** * 为 Viewpager 设置页面切换监听,当页面切换完成被选中时,我们同步 RadioButton 的状态 **/ mainViewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { if (position == 0) radioButtonA.setChecked(true); else radioButtonB.setChecked(true); } @Override public void onPageScrollStateChanged(int state) { } }); /** * 为 RadioGroup 设置选中变化事件监听,当 RadioButton 状态变化,我们同步 Viewpager 的选中页面 **/ mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { if (checkedId == radioButtonA.getId()) mainViewpager.setCurrentItem(0); else if (checkedId == radioButtonB.getId()) mainViewpager.setCurrentItem(1); } }); //设置默许选中页 mainViewpager.setCurrentItem(0); }

对了,还有 NotePagerAdapter 的代码,这个比较简单,是 ViewPagerFragment 的适配器:

public class NotePagerAdapter extends FragmentStatePagerAdapter { private List<Fragment> mFragments; public NotePagerAdapter(FragmentManager fm, List<Fragment> fragments) { super(fm); mFragments = fragments; } @Override public int getCount() { return mFragments.size(); } @Override public Fragment getItem(int position) { return mFragments.get(position); } }

总结

注意,以上代码使用的是 android.support.v4 包的类,理论上不使用 V4 包是没问题的。

看完全体的代码发现并没甚么难点,纯属基础知识的叠加,主要是 UI 控件上的细节需要处理的比较多。

再者,如果顶部的控件超过2个,还需要更多的 xml 文件,顶部的几个控件是可以封装成1个自定义 View 的,乃至加上中间的 ViewPager 1起封装。等待我后面的成果吧。如果有甚么疑问或建议,可以通过文末的联系方式和我交换。

最后,记念1下自己今天正式成为 CSDN博客专家 ,祝贺广大程序员都能在编程的路上有所成绩!

PS:你可以通过下面的方式和我联系

  • 微博:cafeting
  • Github: likfe
  • CSDN:他叫自己Mr.张
------分隔线----------------------------
------分隔线----------------------------

最新技术推荐