当前位置: 代码迷 >> Android >> Android组件式开发(二)——实现网格布局的RadioButton矩阵
  详细解决方案

Android组件式开发(二)——实现网格布局的RadioButton矩阵

热度:32   发布时间:2016-04-24 11:47:07.0
Android组件式开发(2)——实现网格布局的RadioButton矩阵

**

前言

**
在Android中,我们一般通过RadioGroup来管理一组RadioButton 来达到 单选按钮的互斥效果。但是,有些需求中,需要完成N行N列这样的RadioButton组成的矩阵,但是我们的RadioGroup是一个耿直的LinearLayout,无法完成网格布局╮(╯▽╰)╭。所以,下面我就像大家来介绍一种实现网格布局的RadioButton的思路。
无图无真相, 先上一下效果图~

这里写图片描述

**

思路

**
提到网格布局,最简单的就是使用系统的GridView来实现,我们需要做的就是 将RadioButton加入GridView中,然后自己来实现RadioButton之间的互斥。
1. 自定义RadioButton:
自定义一个RadioButton ,命名为IconRadioButton

/** * Created by jk on 2016/1/20. * 自定义 RadioButton */public class IconRadioButton extends LinearLayout  {    private Context mContext;    private Resources mResources;    private boolean mIsCheck;    private View mContentView;    private ImageView mRadio;    private TextView mTextView;    private ColorStateList mTextColor;    public IconRadioButton(Context context) {        this(context, null);    }    public IconRadioButton(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public IconRadioButton(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(context);    }    private void init(Context context) {        mContext = context;        mResources = context.getResources();        mContentView = LayoutInflater.from(context).inflate(R.layout.btn_icon_radio, this);        mRadio = (ImageView) mContentView.findViewById(R.id.radio);        mTextView = (TextView) mContentView.findViewById(R.id.text);    }    public void setChecked(boolean isChecked) {        mIsCheck = isChecked;        changeUIByChecked(isChecked);    }    public boolean isChecked() {        return mIsCheck;    }    private void changeUIByChecked(boolean isChecked) {        if (mRadio.getVisibility() != GONE) {            mRadio.setImageResource(isChecked ? R.drawable.radio_selected                    : R.drawable.radio_unselected);        }        mTextView.setEnabled(isChecked);    }    public void setTextColor(ColorStateList color){        mTextColor = color;        mTextView.setTextColor(color);    }    public void setText(CharSequence text) {        mTextView.setText(text);    }    public void setText(int resId) {        mTextView.setText(resId);    }    public void hiddenRadio(boolean isHidden) {        mRadio.setVisibility(isHidden ? GONE : VISIBLE);    }}

这个IconRadioButton很简单 就是一个LinearLayout,内部封装了根据是否选中来改变文字和按钮样式的方法。

btn_icon_radio.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:orientation="horizontal"    android:gravity="left"    android:paddingBottom="5dp"    android:paddingTop="5dp">    <ImageView        android:id="@+id/radio"        android:layout_width="42dp"        android:layout_height="match_parent"        android:layout_gravity="center_vertical"        android:gravity="center"        android:src="@drawable/radio_selected"        android:textColor="#FF1CBFA6"         />    <TextView        android:id="@+id/text"        android:layout_width="wrap_content"        android:layout_height="match_parent"        android:layout_gravity="center_vertical"        android:gravity="center"        android:textColor="#FF999999"        android:textSize="14dp" /></LinearLayout>

布局文件很简单 就是一个LinearLayout里面放了一个ImageView和一个TextView

2 . 定义数据模型

/** * Created by admin on 2016/1/20. */public class RadioItemModel {    public String text; //RadioButton的文字    public boolean isChecked;//是否选中    public boolean hiddenRadio;//是否需要隐藏radio    public ColorStateList textColor;//文字的不同状态的颜色    public RadioItemModel(String text, boolean isChecked, boolean hiddenRadio, ColorStateList textColor) {        this.text = text;        this.isChecked = isChecked;        this.hiddenRadio = hiddenRadio;        this.textColor = textColor;    }    public RadioItemModel(String text) {        this.isChecked = false;        this.hiddenRadio = false;        this.textColor = null;        this.text = text;    }    public void setText(String text) {        this.text = text;    }    public String getText() {        return text;    }    public boolean isChecked() {        return isChecked;    }}

我们定义了一个数据模型来存放RadioButton的各种属性。其中ColorStateList是用来控制TextView在不同状态下的颜色的 比如:state_pressed等。

3. 定义Adapter:
既然是使用GridView 那就需要定义我们的Adapter,我们的互斥逻辑也是在Adapter中实现的。

/** * Created by jk on 2016/1/20. * function: 单选矩阵的适配器 * purpose: 系统的RadioGroup是个耿直的LinearLayout╮(╯▽╰)╭  只能线性排列,无法完成 * N行N列的布局。So 为了实现单选按钮的网格布局 ,重定义 */public class GridRadioAdapter extends BaseAdapter {    private List<RadioItemModel> mList;    private Context mContext;    private Resources mResources;    private OnItemCheckedListener mListener;    //RadioButton选中时的回调函数    public interface OnItemCheckedListener {        void onItemChecked(RadioItemModel model, int position);    }    public void setOnItemCheckedListener(OnItemCheckedListener listener) {        this.mListener = listener;    }    public GridRadioAdapter(Context context, List<RadioItemModel> list) {        mContext = context;        mList = list;        check();    }    private void check() {        if (mList.size()>=0 && mList!=null) {            checkDefaultChecked();            checkMutex();        }    }    /**     * 检查互斥事件   默认只能选中一个 如果有多个选择,就选中最后一个     */    private void checkMutex() {        int checkCount = 0;        for (RadioItemModel item : mList) {            if (item.isChecked) {                checkCount++;            }        }        if (checkCount >= 2) {            setOtherUnChecked(checkCount - 1);        }    }    private void setOtherUnChecked(int position) {        for (int i = 0; i < mList.size(); i++) {            if (i != position) {                RadioItemModel item = mList.get(i);                item.isChecked = false;            } else {                mList.get(position).isChecked = true;            }        }    }    public RadioItemModel getItemChecked() {        for (int i = 0; i < mList.size(); i++) {            RadioItemModel item = mList.get(i);            if (item.isChecked)                return item;        }        return null;    }    /**     * 检查是否有默认选中的按钮  如果没有 默认第一个选中     */    private void checkDefaultChecked() {        for (RadioItemModel item : mList) {            if (item.isChecked)                return;        }        mList.get(0).isChecked = true;    }    @Override    public int getCount() {        return mList == null ? 0 : mList.size();    }    @Override    public Object getItem(int position) {        if (mList != null && mList.size() > position)            return mList.get(position);        return null;    }    @Override    public long getItemId(int position) {        return position;    }    @Override    public View getView(final int position, View convertView, ViewGroup parent) {        IconRadioButton iconBean = null;        iconBean = new IconRadioButton(mContext);        final RadioItemModel model = mList.get(position);        if (!TextUtils.isEmpty(model.text)) {            iconBean.setText(model.text);        }        iconBean.setChecked(model.isChecked);        if (model.textColor != null) {            iconBean.setTextColor(model.textColor);        }        iconBean.hiddenRadio(model.hiddenRadio);        final IconRadioButton finalIconBean = iconBean;        iconBean.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if (!finalIconBean.isChecked()) {                    setOtherUnChecked(position);                    if (mListener != null) {                        mListener.onItemChecked(model, position);                    }                    notifyDataSetChanged();                }            }        });        return iconBean;    }    public void addAll(List<RadioItemModel> list){        mList.clear();        if(list.size()>=0 && list!=null){            mList.addAll(list);            check();            notifyDataSetChanged();        }    }}

在构造函数中,我们调用了check方法来实现默认选中检查和 互斥检查。
(1)checkDefaultChecked函数用来实现默认选中功能,如果传递给我们的数据中没有按钮是默认选中的 ,那我们就让第一个按钮默认选中。
(2)checkMutex函数是用来检查互斥事件的,如果有多个按钮同时被选中,我们就设置被选中的最后一个按钮为选中状态,其他置为非选中状态。比如 按钮1,3,5同时被选中,那么我们就让5置为选中状态,1和3为非选中状态。
(3)OnItemCheckedListener是当按钮被选中时的回调方法。

4.使用方式

使用方式就非常简单粗暴了~

public class MainActivity extends Activity {    private GridView mGridLayout;    private GridRadioAdapter mAdapter;    private List<RadioItemModel> mItemList;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        }    private void initData() {        mItemList = new ArrayList<RadioItemModel>();        ColorStateList csl = getResources().getColorStateList(R.color.ddt_color_tab_text);        mItemList.add(new RadioItemModel("全部", false, true, csl));        mItemList.add(new RadioItemModel("早餐前", false, true, csl));        mItemList.add(new RadioItemModel("午餐前", false, true, csl));        mItemList.add(new RadioItemModel("晚餐前", false, true, csl));        mItemList.add(new RadioItemModel("早餐后", false, true, csl));        mItemList.add(new RadioItemModel("午餐后", false, true, csl));        mItemList.add(new RadioItemModel("晚餐后", false, true, csl));        mItemList.add(new RadioItemModel("睡前", false, true, csl));        mAdapter.notifyDataSetChanged();    }    }

PS: 如果设置hiddenRadio这个属性为true,我们就可以实现下面这种效果了。所以这个东西也是可以用来做切换Fragment的选项卡的哦~~~ O(∩_∩)O
这里写图片描述

以上。

1楼adfghjkl9小时前
挺好
  相关解决方案