Android自定义CheckBox CheckGroup超好用

在MaterialDialog 仿Android 5.0原生的AlertDialog样式的对话框一文中以及详细介绍了单选/多选对话框的用法,但是在现实开发中,我们可能需要在Activity上进行单选多选操作,于是就在MaterialDialog库中进行了再次封装,其中CheckBox和CheckGroup这两个类是这次封装的结果,接下来将详细介绍这两个类的用法。

首先,先看效果图:Android自定义CheckBox CheckGroup超好用_第1张图片

先看下布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/hit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="提示对话框"/>

    <Button
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="列表对话框"/>

    <Button
        android:id="@+id/radio"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="单选对话框"/>

    <Button
        android:id="@+id/check"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="多选对话框"/>


    <com.common.design.CheckGroup
        android:id="@+id/checkGroup"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:shape="circle"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/look"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onClick"
            android:text="查看选择结果"/>

        <TextView
            android:id="@+id/result"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textColor="@android:color/black"/>

    </LinearLayout>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:orientation="horizontal">

        <com.common.design.CheckBox
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            app:text="默认属性"/>

        <com.common.design.CheckBox
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            app:colorChecked="#00AA00"
            app:colorUnchecked="#AAAAAA"
            app:middlePadding="20dp"
            app:shape="square"
            app:text="自定义属性"
            app:textColor="#0000FF"
            app:textSize="17sp"/>
    </LinearLayout>

</LinearLayout>

CheckBox属性介绍

<resources>
    <declare-styleable name="CheckBox">
        <attr name="text" format="reference|string"/><!--单选/多选旁边的文本-->
        <attr name="textColor" format="color|reference"/><!--文本颜色-->
        <attr name="textSize" format="dimension|reference"/><!--文本大小-->
        <attr name="middlePadding" format="dimension|integer"/><!--单选/多选与文本之间的距离-->
        <attr name="duration" format="integer"/><!--动画时长-->
        <attr name="strokeWidth" format="dimension"/><!--选中时,勾的宽度以及未选中时描边的宽度-->
        <attr name="colorTick" format="color|reference"/><!--选中时勾的颜色-->
        <attr name="colorChecked" format="color|reference"/><!--选中时的背景色-->
        <attr name="colorUnchecked" format="color|reference"/><!--未选中时的背景色-->
        <attr name="colorUncheckedStroke" format="color|reference"/><!--未选中时,描边的颜色-->
        <attr name="checkBoxWidth" format="dimension|integer"/><!--单选/多选框的宽度-->
        <attr name="checkBoxHeight" format="dimension|integer"/><!--单选/多选框的高度-->

        <attr name="shape" format="enum"><!--CheckView形状-->
            <enum name="circle" value="0"/><!--圆形-->
            <enum name="square" value="1"/><!--正方形-->
        </attr>
    </declare-styleable>
</resources>

Activity代码

public class MainActivity extends AppCompatActivity {
    CheckGroup mCheckGroup;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mCheckGroup = (CheckGroup) findViewById(R.id.checkGroup);
        OptionWrapper optionWrapper = new OptionWrapper();
        optionWrapper.setOptions("数学", "语文", "英语", "物理", "化学");
        optionWrapper.setChecked(1, 2, 4);
        mCheckGroup.setOptionWrapper(optionWrapper);
    }

    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.look:
                List<CharSequence> checkedText = mCheckGroup.getCheckedText();
                StringBuilder builder = new StringBuilder();
                for (CharSequence charSequence : checkedText) {
                    builder.append(charSequence).append("、");
                }
                if (builder.length() > 0)
                    builder.deleteCharAt(builder.length() - 1);
                ((TextView) findViewById(R.id.result)).setText(builder);
                break;

            case R.id.hit:
                new MaterialDialog.Builder(this)
                        .setTitle("提示")
                        .setMessage("仿原生AlertDialog样式的对话框,目的在于解决原生的在Android 5.0下样式丑陋问题")
                        .setPositiveButton(new MaterialDialog.OnClickListener() {
                            @Override
                            public boolean onClick(DialogInterface dialog, int which) {
                                return false;
                            }
                        })
                        .setNeutralButton("不再提示", null)
                        .setNegativeButton(null).show();
                break;
            case R.id.list:
                final String[] items = {"2016/01", "2016/02", "2016/03", "2016/04", "2016/05", "2016/06", "2016/07"};
                new MaterialDialog.Builder(this)
                        .setItems(items, new MaterialDialog.OnClickListener() {
                            @Override
                            public boolean onClick(DialogInterface dialog, int which) {
                                Toast.makeText(MainActivity.this, items[which], Toast.LENGTH_SHORT).show();
                                return false;
                            }
                        }).create().show();
                break;
            case R.id.radio:
                final String[] item2 = {"2016/01", "2016/02", "2016/03", "2016/04", "2016/05", "2016/06", "2016/07"};
                new MaterialDialog.Builder(this)
                        .setTitle("单选框")
                        .setSingleChoiceItems(item2, 2, new MaterialDialog.OnClickListener() {
                            @Override
                            public boolean onClick(DialogInterface dialog, int which) {
                                Toast.makeText(MainActivity.this, item2[which], Toast.LENGTH_SHORT).show();
                                return true;
                            }
                        }).setPositiveButton("确定", null)
                        .setNegativeButton("取消", null)
                        .setNeutralButton("不在提示", null).show();
                break;
            case R.id.check:
                final String[] item1 = {"2016/01", "2016/02", "2016/03", "2016/04", "2016/05", "2016/06", "2016/07"};
                new MaterialDialog.Builder(this)
                        .setTitle("多选框")
                        .setMultiChoiceItems(item1, new int[]{1, 2, 3}, new MaterialDialog.OnMultiChoiceClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which, boolean isChecked) {
                                Toast.makeText(MainActivity.this, which + "--" + isChecked, Toast.LENGTH_SHORT).show();
                            }
                        })
                        .setMCResultButton(new MaterialDialog.OnMCResultListener() {
                            @Override
                            public boolean onClick(DialogInterface dialog, List<Integer> checkItems) {
                                return false;
                            }
                        })
                        .setNegativeButton("取消", null)
                        .setNeutralButton("不在提示", null).show();
                break;

        }
    }
}

可能有人会有疑问:单选/多选用原生的RadioButton、RadioGroup和CheckBox就可以实现,为什么还要去写这些呢?
我的回答是:原生的固然好用,但是自己写的更好用,这个稍后会有介绍;而且原生的在Android 5.0以下手机上显示是非常丑的,自己写的则向下兼容到Api 10,所以即使在低版本的手机显示也是跟高版本的手机上显示的是一样的界面

在这,只讲解CheckBox和CheckGroup两个类的用法,具体实现请到我的github上下载源码阅读,源码上都有注解,且通俗易懂

1、CheckBox
在上面的代码中已经有了详细的用法,且大部分用法跟原生的RadioButton一致,例如:setChecked(Boolean),setOnCheckedChangeListener等方法都是一致的。
CheckBox的优势在于提供了一系列自定义的属性,例如:自定义形状(方形还是圆形),自定义选中/未选中时的颜色,文本的大小,颜色等等都可以自定义,最主要的是样式向下兼容到Api 10
CheckBox基本上可以代替原生的RadioButton和CheckBox,如有发现某些功能不能替代,请联系我,我会加上这些功能。

2、CheckGroup
CheckGroup继承于ListView,所以它其实就是一个ListView,通过列表去展示单选/多选列表

mCheckGroup = (CheckGroup) findViewById(R.id.checkGroup);
OptionWrapper optionWrapper = new OptionWrapper();//Option的封装类
optionWrapper.setOptions("数学", "语文", "英语", "物理", "化学");
optionWrapper.setChecked(1, 2, 4);//默认选中position为1 2 4的选项
mCheckGroup.setShape(CheckGroup.SQUARE);//画方形,圆形传:CheckGroup.CIRCLE
mCheckGroup.setOptionWrapper(optionWrapper);

通过以上代码就可以在Activity上展示单选/多选列表,如果要拿到选择结果,只需调用

List<CharSequence> checkedText = mCheckGroup.getCheckedText();

就可以拿到已选择的列表的文本集合,或者调用

 List<Integer> checkedIndex = mCheckGroup.getCheckedIndex();

就可以拿到已选择的列表的下标position集合,亦可调用

 List<Option> checked = mCheckGroup.getChecked();

就可以拿到已选择的列表的对象集合,Option是一个实体累,OptionWrapper是对Option的一个简单封装类,两个类里面都是只有3个字段而已,代码就不贴了,可以自己下载源码查看。

如需要把列表设置为单选列表,只需要在构造方法中传入一个true即可,例如:

OptionWrapper optionWrapper = new OptionWrapper(true);

如果在单选时,通过optionWrapper.setChecked(1, 2, 4);方法设置了多个默认选中的选项,则只会取第一个有效值做为默认选中的选项;
如果在多选时,亦通过optionWrapper.setChecked(1, 2, 4);方法设置了n个默认选中的选项,假设共有10个选项,其中n>10,则会取前10个有效值做为默认选中的选项。何为有效值,请看代码:

    /**
     * 设置默认选中的item
* 注:此方法一定要在setOptions之后调用才会有效
* 单选时,默认取第一个有效值做为默认的选中 * * @param positions 选中item的position集合 */
public void setChecked(List<Integer> positions) { if (positions == null || positions.size() == 0) return; for (int position : positions) { //当用户传过来的position大于等于集合的长度时,认为是无效值 if (position >= mOptions.size()) continue; mOptions.get(position).setCheck(true); if (isSingleChoice) break; } }

如需设置监听器,调用如下代码:

        mCheckGroup.setOnChangeListener(new CheckGroup.OnChangeListener() {
            @Override
            public void onChange(AdapterView<?> parent, View view, int position) {

            }
        });

监听器看着眼熟是不是?没错,里面的3个参数都是从ListView 的OnItemClickListener监听器中传过去的,因为CheckGroup继承ListView,本质上就是一个ListView。

好了,基本就介绍到这里了,怎么样,用起来是不是更简单,更顺手(没有?那好吧,我会继续努力的)

本人小白一个,各位大神如发现错误之处,请指出,本人感激不尽。

源码下载:https://github.com/liujingxing/MaterialDialogApplication

你可能感兴趣的:(实用工具)