android radiobutton获取选中的值_时隔一年,用新知识重构一个Android控件老库

128a586241c709d7aba72d4df9c9c124.png

一年前,用 Java 写了一个高可扩展选择按钮库。单个控件实现单选、多选、菜单选,且选择模式可动态扩展。

一年后,一个新的需求要用到这个库,项目代码已经全 Kotlin 化,强硬地插入一些 Java 代码显得格格不入,Java 冗余的语法也降低了代码的可读性,于是决定用 Kotlin 重构一番,在重构的时候也增加了一些新的功能。这一篇分享下重构的过程。

建议关注:不定时分享Android方面的技术、及大厂面试真题分析
Android技术进阶屋​zhuanlan.zhihu.com
226196731d44c3295139782ba7400d7a.png

选择按钮的可扩展性主要体现在 4 个方面:

  1. 选项按钮布局可扩展
  2. 选项按钮样式可扩展
  3. 选中样式可扩展
  4. 选择模式可扩展

扩展布局

原生的单选按钮通过RadioButton+ RadioGroup实现,他们在布局上必须是父子关系,而RadioGroup继承自LinearLayout,遂单选按钮只能是横向或纵向铺开,这限制的单选按钮布局的多样性,比如下面这种三角布局就难以用原生控件实现:

92fe9860f0360e747e0f6858b8f5fcfa.gif

为了突破这个限制,单选按钮不再隶属于一个父控件,它们各自独立,可以在布局文件中任意排列,图中 Activity 的布局文件如下(伪码):

<androidx.constraintlayout.widget.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Selector age"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <test.taylor.AgeSelector
        android:id="@+id/selector_teenager"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@id/title"
        app:layout_constraintStart_toStartOf="parent"/>

    <test.taylor.AgeSelector
        android:id="@+id/selector_man"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toStartOf="@id/selector_old_man"
        app:layout_constraintTop_toBottomOf="@id/selector_teenager"
        app:layout_constraintStart_toStartOf="parent"/>

    <test.taylor.AgeSelector
        android:id="@+id/selector_old_man"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@id/selector_teenager"
        app:layout_constraintStart_toEndOf="@id/selector_man"/>
</androidx.constraintlayout.widget.ConstraintLayout>

AgeSelector表示一个具体的按钮,本例中它是一个“上面是图片,下面是文字”的单选按钮。它继承自抽象的Selector。

扩展样式

从业务上讲,Selector长什么样是一个频繁的变化点,遂把“构建按钮样式”这个行为设计成Selector的抽象函数onCreateView(),供子类重写以实现扩展。

public abstract class Selector extends FrameLayout{
    

    public Selector(Context context) {
    
        super(context);
        initView(context, null);
    }

    private void initView(Context context, AttributeSet attrs) {
    
        // 初始化按钮算法框架
        View view = onCreateView();
        LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        this.addView(view, params);
    }
    
    // 如何构建按钮视图,延迟到子类实现
    protected abstract View onCreateView();
}

Selector继承自FrameLayout,实例化时会构建按钮视图,并把该视图作为孩子添加到自己的布局中。子类通过重写onCreateView()扩展按钮样式:

public class AgeSelector extends Selector {
    
    @Override
    protected View onCreateView() {
    
        View view = LayoutInflater.from(this.getContext()).inflate(R.layout.age_selector, null);
        return view;
    }
}

AgeSelector的样式被定义在 xml 中。

按钮被选中之后的样式,也是一个业务上的变化点,用同样的思路可以将Selector这样设计:

// 抽象按钮实现点击事件
public abstract class Selector extends FrameLayout implements View.OnClickListener {
    

    public Selector(Context context) {
    
        super(context);
        initView(context, null);
    }
    
    private void initView(Context context, AttributeSet attrs) {
    
        View view = onCreateView();
        LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        this.addView(view, params);
        // 设置点击事件
        this.setOnClickListener(this);
    }
    
    @Override
    public void onClick(View v) {
    
        // 原有选中状态
        boolean isSelect = this.isSelected();
        // 反转选中状态
        this.setSelected(!isSelect);
        // 展示选中状态切换效果
        onSwitchSelected(!isSelect);
        return !isSelect;
    }
    
    // 按钮选中状态变化时的效果延迟到子类实现
    protected abstract void onSwitchSelected(boolean isSelect);
}

将选中按钮状态变化的效果抽象成一个算法,延迟到子类实现:

public class 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值