如果移动端访问不佳或需要更好的浏览体验,欢迎使用 ==> 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)
方法中修改 RadioGroup
中 RadioButton
的选中状态RadioGroup
setOnCheckedChangeListener
监听,并在其中修改 ViewPager
的状态<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
RadioButton
: android: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
的代码,这个比较简单,是 ViewPager
和 Fragment
的适配器:
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.张