首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android 必知必会 - RadioGroup 和 ViewPager 联动

Android 必知必会 - RadioGroup 和 ViewPager 联动

作者头像
他叫自己MR.张
发布2019-07-01 17:09:54
1.1K0
发布2019-07-01 17:09:54
举报
文章被收录于专栏:Android必知必会Android必知必会

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

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

背景

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

主要知识点:

  • 自定义 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="-1dp"
                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" 设置背景,实际上是一个 selector
  • android:textColor="@drawable/top_r_text" 设置文字颜色,它也是一个 selector
  • 对于第二个 RadioButtonandroid:layout_marginLeft="-1dp" 和描边宽度一样,防止出现间隙

下面把 xml 代码放在一起看,它们都放在 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 文件,顶部的几个控件是可以封装成一个自定义 View 的,甚至加上中间的 ViewPager 一起封装。等待我后面的成果吧。如果有什么疑问或建议,可以通过文末的联系方式和我交流。

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

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年09月20日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 实现
    • 思路
      • 实现 UI
        • 实现联动事件
        • 总结
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档