Android 必知必会 - RadioGroup 和 ViewPager 联动
如果移动端访问不佳或需要更好的阅读体验,欢迎使用 ==> Github 版
使用 RadioGroup 和 ViewPager 实现更加可定制的效果。
背景
昨天设计图刚出一点,写了《Android 必知必会 - 动态切换着色模式和全屏模式》,记录了动态修改页面显示模式的方式。今天又有新图,不过设计师只考虑 iOS 平台的设计,拿到设计图发现 TabLayout + ViewPager 的套路实现起来很麻烦,考虑了下,为了方便,决定使用 RadioGroup + ViewPager 来实现,之所以使用 RadioGroup ,是因为它内部多个 RadioButton 的状态是互斥的,也就是只有一个是选中状态,不需要我们进行多余的处理。总体来说比较简单,就是细节略多了点。
主要知识点:
- 自定义
RadioButton样式 :selector + shape - 自定义
RadioButton文字样式 :selector ViewPager + Fragment及其适配器RadioGroup状态监听ViewPager页面切换监听
实现
先看效果图:
思路
UI:
- 顶部是
RadioGroup,内部包含两个RadioButtonRadioButton需要自定义背景和文字
- 中间是
ViewPager
联动事件:
ViewPager- 需要为
ViewPager写适配器,以配合Fragment - 使用
addOnPageChangeListener()为其添加监听页面变动的事件- 在
onPageSelected(int position)方法中修改RadioGroup中RadioButton的选中状态
- 在
- 需要为
RadioGroup- 设置
setOnCheckedChangeListener监听,并在其中修改ViewPager的状态
- 设置
实现 UI
<LinearLayoutxmlns: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"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="45dp"android:background="@color/title_bar"><RadioGroupandroid: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"><RadioButtonandroid: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"/><RadioButtonandroid: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="-1dp"android:text="@string/main_tab2"android:textColor="@drawable/top_r_text"android:textColorHighlight="@color/title_bar"android:textSize="15sp"/>RadioGroup><ImageViewandroid: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.ViewPagerandroid: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"设置背景,实际上是一个selectorandroid:textColor="@drawable/top_r_text"设置文字颜色,它也是一个selector- 对于第二个
RadioButton:android:layout_marginLeft="-1dp"和描边宽度一样,防止出现间隙
下面把 xml 代码放在一起看,它们都放在 drawable 目录下:
<selector xmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:drawable="@drawable/top_r_bg_a"android:state_checked="false"/><itemandroid:drawable="@drawable/top_r_bg_b"android:state_checked="true"/>
selector>
<shape xmlns:android="http://schemas.android.com/apk/res/android"><cornersandroid:bottomLeftRadius="2dp"android:bottomRightRadius="0dp"android:topLeftRadius="2dp"android:topRightRadius="0dp"/><strokeandroid:width="1dp"android:color="@color/white"/><solid android:color="@color/transparent"/>
shape>
<shape xmlns:android="http://schemas.android.com/apk/res/android"><cornersandroid:bottomLeftRadius="2dp"android:topLeftRadius="2dp"/><solid android:color="@color/white"/>
shape>
<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() {@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}@Overridepublic void onPageSelected(int position) {if (position == 0) radioButtonA.setChecked(true);else radioButtonB.setChecked(true);}@Overridepublic void onPageScrollStateChanged(int state) {}});/*** 为 RadioGroup 设置选中变化事件监听,当 RadioButton 状态变化,我们同步 Viewpager 的选中页面**/mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Overridepublic 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 的代码,这个比较简单,是 ViewPager 和 Fragment 的适配器:
public class NotePagerAdapter extends FragmentStatePagerAdapter {private List<Fragment> mFragments;public NotePagerAdapter(FragmentManager fm, List<Fragment> fragments) {super(fm);mFragments = fragments;}@Overridepublic int getCount() {return mFragments.size();}@Overridepublic Fragment getItem(int position) {return mFragments.get(position);}}
总结
注意,以上代码使用的是 android.support.v4 包的类,理论上不使用 V4 包是没问题的。
看完整体的代码发现并没什么难点,纯属基础知识的叠加,主要是 UI 控件上的细节需要处理的比较多。
再者,如果顶部的控件超过2个,还需要更多的 xml 文件,顶部的几个控件是可以封装成一个自定义 View 的,甚至加上中间的 ViewPager 一起封装。等待我后面的成果吧。如果有什么疑问或建议,可以通过文末的联系方式和我交流。
最后,纪念一下自己今天正式成为 CSDN博客专家 ,祝愿广大程序员都能在编程的路上有所成就!
PS:你可以通过下面的方式和我联系
- 微博:cafeting
- Github: likfe
- CSDN:他叫自己Mr.张
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

