自定义LinearLayout并搭配流式布局,实现商城app商品规格选择View

一:效果图镇楼

二:整个View的制作过程

  1. 继承自LinearLayout 设置为垂直走向
  2. 动态摆放每一个属性的title
  3. 绘制每一个规格属性,这里使用的是Flowlayout里面添加RadioButton这样就可以写一个selector实现选中效果
  4. 设计好属性规格的数据格式,这样在使用起来的时候就会感动很简便
  5. 动态添加RadioButton遇到的坑(填坑)……

三:首先确定好view所接收的数据格式,我这里采用的是大集合里面套着小集合 如下图:

创建的实体类,这个跟使用ExpandableListView的数据源格式还是差不多的也是很好理解的。

public class BigClassification {
    //大分类
    private String title;
    public List<SmallClassification> list;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public List<SmallClassification> getList() {
        return list;
    }

    public void setList(List<SmallClassification> list) {
        this.list = list;
    }

    //小分类
    public static class SmallClassification {
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

四:数据我们有了,就可以开始将我们设定的这些属性展示出来了;先来看下第一部分—将每个大规格的标题显示出来也就是 new 一个 TextView并添加至View里面来看一下代码。

    /** * 数据源 */
    private List<BigClassification> list;
    /** * 上下文 */
    private Context context;

    /** * 规格标题栏的文本间距 */
    private int titleMargin = 8;
    /** * 整个商品属性的左右间距 */
    private int flowLayoutMargin = 16;
    /** * 属性按钮的高度 */
    private int buttonHeight = 25;
    /** * 属性按钮之间的左边距 */
    private int buttonLeftMargin = 10;
    /** * 属性按钮之间的上边距 */
    private int buttonTopMargin = 8;
    /** * 文字与按钮的边距 */
    private int textPadding = 10;
    /** * 选择后的回调监听 */
    private OnSelectedListener listener;

————————(假装看不到我)以上为定义的一些属性————————

//遍历整个大集合,得到所有的规格
for (BigClassification attr : list) {
            //设置规格分类的标题
            TextView textView = new TextView(context);
            LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
            //根据手机的分辨率从 dip 的单位 转成为 px(像素)
            int margin = dip2px(context, titleMargin);
            //为textView设置上下左右的边距
            textView.setText(attr.getTitle());
            params.setMargins(margin, margin, margin, margin);
            textView.setLayoutParams(params);
            addView(textView);
        }

五:大的标题显示完了就要开始显示每个小规格了,我这里将小规格的属性添加到FlowLayou里面去了。

for (BigClassification attr : list) {
            //接上面添加大规格标题代码
            //.....

            //设置一个大规格下的所有小规格
            FlowLayout layout = new FlowLayout(context);
            //将标题设置进去
            layout.setTitle(attr.getTitle());
            layout.setPadding(dip2px(context, flowLayoutMargin), 0, dip2px(context, flowLayoutMargin), 0);
            //设置选择监听
            if (listener != null) {
                layout.setListener(listener);
            }
            for (BigClassification.SmallClassification smallAttr : attr.getList()) {
                //属性按钮
                RadioButton button = new RadioButton(context);
                //设置按钮的参数
                LayoutParams buttonParams = new LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
                        dip2px(context, buttonHeight));
                //设置文字的边距
                int padding = dip2px(context, textPadding);
                button.setPadding(padding, 0, padding, 0);
                //设置margin属性,需传入LayoutParams否则会丢失原有的布局参数
                MarginLayoutParams marginParams = new MarginLayoutParams(buttonParams);
                marginParams.leftMargin = dip2px(context, buttonLeftMargin);
                marginParams.topMargin = dip2px(context, buttonTopMargin);

                button.setLayoutParams(marginParams);
                button.setGravity(Gravity.CENTER);
                button.setBackgroundResource(R.drawable.tv_sel);
                button.setButtonDrawable(android.R.color.transparent);
                button.setText(smallAttr.getName());
                layout.addView(button);
            }
            addView(layout);
        }

1.这里一开始我通过buttonParams.setMargins();为RadioButton设置上下左右边距,但是运行出来发现还是挤在一坨完全没有任何效果特郁闷!突然灵光一闪查看一下FlowLayout的源码发现如下代码 他将LayoutParams强转为MarginLayoutParams所以自然而然的这样设置Margin是无效的。

2.设置MarginLayoutParams参数,设置margin属性时,需传入LayoutParams否则会丢失原有的布局参数

MarginLayoutParams marginParams = new MarginLayoutParams(buttonParams);
marginParams.leftMargin = dip2px(context, buttonLeftMargin);
marginParams.topMargin = dip2px(context, buttonTopMargin);

3.动态添加RadioButton,去除前面的圆圈只需要如下设置即可。

button.setButtonDrawable(android.R.color.transparent);

六:接下来就是设置选中监听了,重写FlowLayout的addView()函数为每一个RadioButton设置监听事件。

@Override
    public void addView(View child) {
        ((RadioButton) child).setOnCheckedChangeListener(this);
        super.addView(child);
    }

在回调中将选中的属性再回调出去,这样就知道选择的是哪一个了。

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        for (int i = 0; i < getChildCount(); i++) {
            RadioButton button = (RadioButton) getChildAt(i);
            button.setChecked(false);
        }
        if (isChecked) {
            buttonView.setChecked(true);
            if (listener != null) {
                listener.onSelected(getTitle(), buttonView.getText().toString());
            }
        }

    }

源码:完整代码看这里 Click Me

七:这里需要注意的是,设置选中结果监听必须在setData之前

ShoppingSelectView view = (ShoppingSelectView) findViewById(R.id.v);
//设置监听需要在设置数据之前
view.setOnSelectedListener(this);
view.setData(list);

八:写在最后其实自定义View也并不是大家想像的那么难(哪些非常叼的除外啊),只要你有想象力和动手能力就肯定可以实现你想要的效果不信你可以试试^_^,使用方法点击上面的链接即可,有什么问题欢迎留言哦!

你可能感兴趣的:(APP,button,Radio,商城,商品规格选择)