美文网首页
商品详情和购物车数量控件封装(造轮子QuantityView)

商品详情和购物车数量控件封装(造轮子QuantityView)

作者: aositeluoke | 来源:发表于2017-08-04 17:07 被阅读0次

使用效果如下:

QuantityView.gif

在商城类软件中,�数量控件可以说是必备控件之一,网上开源的数量控件也有很多,但是还是想通过自己实现一把,理解其中的奥秘之处。

1、需求分析(减号按钮和加号按钮 分割线 输入框)

1.1、最左边的控件和最右边的控件中的文字字体大小(op_text_size)、颜色(op_text_color)、宽度(op_width)都是一致的,不同之处在于:文字(sub_text和add_text)和圆角位置不同(背景sub_background和add_background)
1.2、分割线的宽度(divider_width)和颜色(divider_color)
1.3、输入框的文字大小(input_text_size)、颜色(input_text_color)、宽度(input_text_width)、背景(input_background)
1.4、最大值(max_num)、当前值(num)、最小值(min_num)、输入框是否可输入(can_input)、点击加减号是否立即改变输入框内的数值(is_now_change)
1.5、改变数值时,根据当前数值设置加减号按钮是否可用
1.6、添加数量改变监听(OnNumChangeListener)
1.7、输入框设置为不可编辑时,点击输入框回调(setCenterClickListener),弹出对话框,让用户输入数值
1.8、设置点击加减号按钮后,不能立刻改变输入框的值时,设置点击加减好回调(OnSubAddClickCallBack),接口调用成功后,再更改
最终的属性如下

<declare-styleable name="QuantityView">
        <!--加减号共同属性 op开头-->
        <attr name="op_width" format="dimension" />
        <attr name="op_text_size" format="dimension" />
        <attr name="op_text_color" format="color" />
        <!--减号按钮属性 sub开头-->
        <attr name="sub_background" format="reference|color" />
        <attr name="sub_text" format="string" />
        <!--加号按钮属性 add开头-->
        <attr name="add_background" format="color|reference" />
        <attr name="add_text" format="string" />
        <!--输入框属性  input开头-->
        <attr name="input_text_size" format="dimension" />
        <attr name="input_text_width" format="dimension" />
        <attr name="input_text_color" format="color" />
        <attr name="input_background" format="reference|color" />
        <!--分割线颜色和宽度-->
        <attr name="divider_width" format="dimension" />
        <attr name="divider_color" format="color" />
        <!--当前数量,最小值,最大值,是否可输入,点击加减号是否立刻修改输入框的值-->
        <attr name="num" format="integer" />
        <attr name="min_num" format="integer" />
        <attr name="max_num" format="integer" />
        <attr name="can_input" format="boolean" />
        <attr name="is_now_change" format="boolean" />
    </declare-styleable>
2、自定义控件QantityView源码
public class QuantityView extends LinearLayout {

    private static final String TAG = "QuantityView";

    //加减按钮公共属性
    private int opPadding;
    private int opWidth;
    private int opTextSize;
    private ColorStateList opTextColor;

    //减号按钮属性
    private Drawable subBackground;
    private String subText;
    //加号按钮属性
    private Drawable addBackground;
    private String addText;

    //输入框属性
    private int inputTextSize, inputTextWidth;
    private int inputTextColor;
    private Drawable inputBackground;
    private TextWatcher textWatcher = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

        }

        @Override
        public void afterTextChanged(Editable s) {
            afterTextChangedExecute = true;
            if (TextUtils.isEmpty(s)) {
                return;
            }
            setNum(Integer.parseInt(s.toString()));
        }
    };

    //当前数量,最大值,最小值,是否可输入,点击加减号是否立刻修改输入框的值
    private int num;
    private int maxNum;
    private int minNum;
    private boolean canInput, isNowChange = true;

    //分割线属性
    private int dividerWidth;
    private int dividerColor;


    //所有控件
    private ImageView addImageView, subImageView;
    private TextView addTextView, subTextView;
    private EditText editText;
    private View clickView, leftDivider, rightDivider;

    private boolean afterTextChangedExecute = false;//afterTextChanged执行了

    public QuantityView(Context context) {
        this(context, null);
    }

    public QuantityView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public QuantityView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.QuantityView, defStyle, 0);
        int n = a.getIndexCount();
        for (int i = 0; i < n; i++) {
            int attr = a.getIndex(i);

            switch (attr) {
                //加减按钮公共属性
                case R.styleable.QuantityView_op_width:
                    opWidth = a.getLayoutDimension(attr, 0);
                    break;
//                case R.styleable.QuantityView_op_padding:
//                    opPadding = a.getDimensionPixelSize(attr, 0);
//                    break;
                case R.styleable.QuantityView_op_text_color:
                    opTextColor = a.getColorStateList(attr);
                    break;
                case R.styleable.QuantityView_op_text_size:
                    opTextSize = a.getDimensionPixelSize(attr, 15);
                    break;
                //减号按钮属性
                case R.styleable.QuantityView_sub_background:
                    subBackground = a.getDrawable(attr);
                    break;
                case R.styleable.QuantityView_sub_text:
                    subText = a.getString(attr);
                    break;
                //加号按钮属性
                case R.styleable.QuantityView_add_background:
                    addBackground = a.getDrawable(attr);
                    break;
                case R.styleable.QuantityView_add_text:
                    addText = a.getString(attr);
                    break;

                //分割线属性
                case R.styleable.QuantityView_divider_color:
                    dividerColor = a.getColor(attr, 0);
                    break;

                case R.styleable.QuantityView_divider_width:
                    dividerWidth = a.getLayoutDimension(attr, 0);
                    break;
                //输入框属性
                case R.styleable.QuantityView_input_background:
                    inputBackground = a.getDrawable(attr);
                    break;
                case R.styleable.QuantityView_input_text_color:
                    inputTextColor = a.getColor(attr, Color.parseColor("#333333"));
                    break;
                case R.styleable.QuantityView_input_text_size:
                    inputTextSize = a.getDimensionPixelSize(attr, 15);
                    break;
                case R.styleable.QuantityView_input_text_width:
                    inputTextWidth = a.getLayoutDimension(attr, 0);
                    break;
                //其他公共属性
                case R.styleable.QuantityView_can_input:
                    canInput = a.getBoolean(attr, true);
                    break;
                case R.styleable.QuantityView_num:
                    num = a.getInt(attr, 0);
                    break;
                case R.styleable.QuantityView_min_num:
                    minNum = a.getInt(attr, 1);
                    break;
                case R.styleable.QuantityView_max_num:
                    maxNum = a.getInt(attr, 200);
                    break;
                case R.styleable.QuantityView_is_now_change:
                    isNowChange = a.getBoolean(attr, true);
                    break;
            }
        }
        a.recycle();
        initView();
    }

    private void initView() {
        setFocusable(true);
        setFocusableInTouchMode(true);
//        inputTextSize = dip2px(inputTextSize);
//        opPadding = dip2px(opPadding);
        //减号按钮
//        LayoutParams subParams = new LayoutParams(opWidth, ViewGroup.LayoutParams.MATCH_PARENT);
//        subImageView = new ImageView(getContext());
//        subImageView.setImageDrawable(subSrc);
//        subImageView.setPadding(opPadding, opPadding, opPadding, opPadding);
//        subImageView.setBackground(subBackground);
//        subImageView.setLayoutParams(subParams);
//        subImageView.setOnClickListener(new OnClickListener() {
//            @Override
//            public void onClick(View v) {
//                if (isNowChange) {
//                    num--;
//                    setNum(num);
//                } else {
//                    if (onSubAddClickCallBack != null) {
//
//                        onSubAddClickCallBack.onClickCallBack(QuantityView.this, num - 1);
//                    }
//                }
//
//            }
//        });

        LayoutParams subParams = new LayoutParams(opWidth, ViewGroup.LayoutParams.MATCH_PARENT);
        subTextView = new TextView(getContext());
//        subTextView.setPadding(opPadding, opPadding, opPadding, opPadding);
        subTextView.setBackgroundDrawable(subBackground);
        subTextView.setLayoutParams(subParams);
        subTextView.setClickable(true);
        subTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, opTextSize);
        subTextView.setTextColor(opTextColor);
        subTextView.setGravity(Gravity.CENTER);
        subTextView.setText(subText);
        subTextView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (isNowChange) {
                    num--;
                    setNum(num);
                } else {
                    if (onSubAddClickCallBack != null) {

                        onSubAddClickCallBack.onClickCallBack(QuantityView.this, num - 1);
                    }
                }

            }
        });

        //加号按钮
//        LayoutParams addParams = new LayoutParams(opWidth, ViewGroup.LayoutParams.MATCH_PARENT);
//        addImageView = new ImageView(getContext());
//        addImageView.setImageDrawable(addSrc);
//        addImageView.setPadding(opPadding, opPadding, opPadding, opPadding);
//        addImageView.setBackground(addBackground);
//        addImageView.setLayoutParams(addParams);
//
//        addImageView.setOnClickListener(new OnClickListener() {
//            @Override
//            public void onClick(View v) {
//                if (isNowChange) {
//                    if (!TextUtils.isEmpty(editText.getText() + ""))
//                        num++;
//                    setNum(num);
//                } else {
//                    if (onSubAddClickCallBack != null) {
//                        onSubAddClickCallBack.onClickCallBack(QuantityView.this, num + 1);
//                    }
//                }
//
//            }
//        });

        LayoutParams addParams = new LayoutParams(opWidth, ViewGroup.LayoutParams.MATCH_PARENT);
        addTextView = new TextView(getContext());
//        addTextView.setPadding(opPadding, opPadding, opPadding, opPadding);
        addTextView.setBackgroundDrawable(addBackground);
        addTextView.setLayoutParams(addParams);
        addTextView.setClickable(true);
        addTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, opTextSize);
        addTextView.setTextColor(opTextColor);
        addTextView.setGravity(Gravity.CENTER);
        addTextView.setText(addText);
        addTextView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (isNowChange) {
                    if (!TextUtils.isEmpty(editText.getText() + ""))
                        num++;
                    setNum(num);
                } else {
                    if (onSubAddClickCallBack != null) {
                        onSubAddClickCallBack.onClickCallBack(QuantityView.this, num + 1);
                    }
                }

            }
        });

        //分割线
        LayoutParams leftDividerParams = new LayoutParams(dividerWidth, ViewGroup.LayoutParams.MATCH_PARENT);
        leftDivider = new View(getContext());
        leftDivider.setBackgroundColor(dividerColor);
        leftDivider.setLayoutParams(leftDividerParams);
        LayoutParams rightDividerParams = new LayoutParams(dividerWidth, ViewGroup.LayoutParams.MATCH_PARENT);
        rightDivider = new View(getContext());
        rightDivider.setBackgroundColor(dividerColor);
        rightDivider.setLayoutParams(rightDividerParams);


        //输入布局
        FrameLayout frameLayout = new FrameLayout(getContext());
        frameLayout.setBackgroundColor(getContext().getResources().getColor(android.R.color.white));
        LayoutParams inputParams = new LayoutParams(inputTextWidth, ViewGroup.LayoutParams.MATCH_PARENT);
        inputParams.gravity = Gravity.CENTER;
        frameLayout.setLayoutParams(inputParams);
        //输入框
        FrameLayout.LayoutParams editTextParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        editText = new EditText(getContext());
        editText.setPadding(0, 0, 0, 0);
        editText.setBackgroundColor(getResources().getColor(android.R.color.white));
        editText.setInputType(InputType.TYPE_CLASS_NUMBER);
        editText.setSingleLine();
        editText.setGravity(Gravity.CENTER);
        editText.setTextSize(TypedValue.COMPLEX_UNIT_PX, inputTextSize);
        editText.setTextColor(inputTextColor);
        editText.setLayoutParams(editTextParams);
        editText.addTextChangedListener(textWatcher);
        editText.setClickable(true);
        editText.setEnabled(canInput);

        FrameLayout.LayoutParams clickViewParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        clickView = new View(getContext());
        clickView.setLayoutParams(clickViewParams);
        clickView.setClickable(true);
        clickView.setVisibility(canInput ? GONE : VISIBLE);
        frameLayout.addView(editText);
        frameLayout.addView(clickView);


        //数量控件点击按钮
        this.setClickable(true);
        this.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.e(TAG, "onClick:显示对话框界面");
            }
        });

        addView(subTextView);
        addView(leftDivider);
        addView(frameLayout);
        addView(rightDivider);
        addView(addTextView);
        setNum(num);
    }

    public int getNum() {
        return num;
    }

    public int getMinNum() {
        return minNum;
    }

    public int getMaxNum() {
        return maxNum;
    }

    /**
     * 设置当前数量
     *
     * @param newNum
     */
    public QuantityView setNum(int newNum) {
//        设置的数量小于最小值,使用最小值作为当前数量,大于最大值,使用最大值作为当前数量,修改按钮是否可用
        num = newNum;
        if (newNum >= maxNum) {
            num = maxNum;
            addTextView.setEnabled(false);
        } else {
            addTextView.setEnabled(true);
        }
        if (newNum <= minNum) {
            num = minNum;
            subTextView.setEnabled(false);
        } else {
            subTextView.setEnabled(true);
        }
        //设置之前先移除,再添加避免,重复触发afterTextChanged
        editText.removeTextChangedListener(textWatcher);
        editText.setText(num + "");
        editText.setSelection((num + "").length());
        editText.addTextChangedListener(textWatcher);
        if (onNumChangeListener != null)
            onNumChangeListener.onNuberChange(QuantityView.this
                    , editText, num);

        return this;
    }

    /**
     * 设置最小值
     *
     * @param minNum 最小值
     * @return
     */
    public QuantityView setMinNum(int minNum) {
        this.minNum = minNum;
        setNum(num);
        return this;
    }

    /**
     * @param maxNum 设置最大值
     * @return
     */
    public QuantityView setMaxNum(int maxNum) {
        this.maxNum = maxNum;
        setNum(num);
        return this;
    }

    /**
     * 设置是否可输入
     *
     * @param canInput
     * @return
     */
    public QuantityView setCanInput(boolean canInput) {
        this.canInput = canInput;
        editText.setEnabled(canInput);
        clickView.setVisibility(canInput ? GONE : VISIBLE);
        return this;
    }

    /**
     * @param nowChange 设置是否立即改变输入框的内容
     * @return
     */
    public QuantityView setNowChange(boolean nowChange) {
        isNowChange = nowChange;
        return this;
    }

    /**
     * 设置中间的点击事件
     *
     * @param onClickListener
     * @return
     */
    public QuantityView setCenterClickListener(@NonNull OnClickListener onClickListener) {
        clickView.setOnClickListener(onClickListener);
        return this;
    }


    /**
     * dp转像素
     *
     * @param dpValue
     * @return
     */
    public int dip2px(float dpValue) {
        final float scale = getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }


    //数量改变监听
    private OnNumChangeListener onNumChangeListener;

    public QuantityView setOnNumChangeListener(OnNumChangeListener onNumChangeListener) {
        this.onNumChangeListener = onNumChangeListener;
        return this;
    }

    public interface OnNumChangeListener {
        void onNuberChange(QuantityView cartQuantityView, EditText editText, int num);
    }


    //点击加号减号按钮回调接口
    private OnSubAddClickCallBack onSubAddClickCallBack;

    public QuantityView setOnSubAddClickCallBack(OnSubAddClickCallBack onSubAddClickCallBack) {
        this.onSubAddClickCallBack = onSubAddClickCallBack;
        return this;
    }

    public interface OnSubAddClickCallBack {
        void onClickCallBack(QuantityView quantitySkuDesView, int num);
    }

}
3、使用篇

3.1、在布局文件中使用

<com.aositeluoke.quantityviewdemo.QuantityView
        android:id="@+id/quantity"
        android:layout_width="wrap_content"
        android:layout_height="30dp"
        android:background="@drawable/shape_jd_quantity"
        android:padding="1dp"
        app:add_background="@drawable/selector_jd_add_bg"
        app:add_text="+"
        app:can_input="false"
        app:divider_color="@color/color_232326"
        app:divider_width="1dp"
        app:input_background="@android:color/white"
        app:input_text_color="@color/color_232326"
        app:input_text_size="16dp"
        app:input_text_width="50dp"
        app:max_num="15"
        app:min_num="0"
        app:num="10"
        app:op_text_color="@color/selector_jg_quantity"
        app:op_text_size="20dp"
        app:op_width="30dp"
        app:sub_background="@drawable/selector_jd_sub_bg"
        app:sub_text="-" />

<!--
        android:background="@drawable/shape_jd_quantity"//根布局背景(带四个圆角)
        android:padding="1dp"
        app:add_background="@drawable/selector_jd_add_bg" //加号按钮背景
        app:add_text="+"  //加号按钮文本
        app:can_input="false"  //是否可输入
        app:divider_color="@color/color_232326" //分割线颜色
        app:divider_width="1dp"  分割线宽度
        app:input_background="@android:color/white"  //输入框背景
        app:input_text_color="@color/color_232326" 输入框文字颜色
        app:input_text_size="16dp"  //输入框问题大小
        app:input_text_width="50dp"  //输入框宽度
        app:max_num="15"  // 最大值
        app:min_num="0" //最小值
        app:num="10" // 当前值
        app:op_text_color="@color/selector_jg_quantity" // 加减号按钮文字颜色
        app:op_text_size="20dp"   //加减按钮文字大小
        app:op_width="30dp"  加减按钮宽度
        app:sub_background="@drawable/selector_jd_sub_bg"  //减号按钮背景
        app:sub_text="-"  //减号按钮文本
    -->

shape_jd_quantity.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <stroke
        android:width="1dp"
        android:color="@color/color_232326" />
    <corners android:radius="@dimen/jd_quantity_radius" />

</shape>

selector_jd_add_bg.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <!--可点击按下时-->
    <item android:state_pressed="true">
        <shape>
            <solid android:color="@color/color_e3e5e9" />
            <corners android:bottomRightRadius="@dimen/jd_quantity_radius" android:topRightRadius="@dimen/jd_quantity_radius" />

        </shape>
    </item>


    <!--可点击 未按下时-->
    <item android:state_pressed="false">
        <shape>
            <solid android:color="@color/white" />
            <corners android:bottomRightRadius="@dimen/jd_quantity_radius" android:topRightRadius="@dimen/jd_quantity_radius" />
        </shape>
    </item>

</selector>

加减号文字颜色selector_jg_quantity.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!--不可点击时颜色-->
    <item android:color="#bfbfbf" android:state_enabled="false" />
    <!--可点击时颜色-->
    <item android:color="@color/color_232326" android:state_enabled="true" />
</selector>

减号按钮背景selector_jd_sub_bg.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <!--可点击按下时-->
    <item android:state_pressed="true">
        <shape>
            <solid android:color="@color/color_e3e5e9" />
            <corners android:bottomLeftRadius="@dimen/jd_quantity_radius" android:topLeftRadius="@dimen/jd_quantity_radius" />

        </shape>
    </item>


    <!--可点击 未按下时-->
    <item android:state_pressed="false">
        <shape>
            <solid android:color="@color/white" />
            <corners android:bottomLeftRadius="@dimen/jd_quantity_radius" android:topLeftRadius="@dimen/jd_quantity_radius" />
        </shape>
    </item>

</selector>

颜色文件colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorAccent">#FF4081</color>
    <color name="white">#ffffff</color>
    <color name="color_e3e5e9">#e3e5e9</color>
    <color name="color_232326">#232326</color>
    <color name="transparent">#00000000</color>
</resources>

尺寸文件dimens.xml

<resources>
    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
    <dimen name="jd_quantity_radius">2dp</dimen>
</resources>

3.2、在代码中设置监听

//点击加减号调用接口成功后,再改变数量控件的数量
        quantity.setNowChange(false);//设置不能立即改变,等接口调用成功后再更新
        quantity.setOnSubAddClickCallBack(new QuantityView.OnSubAddClickCallBack() {
            @Override
            public void onClickCallBack(QuantityView quantitySkuDesView, int num) {
                //数量为0,显示删除提示对话框
                if (num == 0) {
                    confirmDialog.show();
                } else {
                    quantitySkuDesView.setNum(num);
                }
            }
        });


        //点击中间输入框,弹出对话框让用户输入数量
        quantity.setCanInput(false);
        quantity.setCenterClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dialogQuantity.setMinNum(quantity.getMinNum() == 0 ? 1 : 0);
                dialogQuantity.setMaxNum(quantity.getMaxNum());
                dialogQuantity.setNum(quantity.getNum());
                inputDialog.show();
            }
        });


        //数量改变回调
        quantity.setOnNumChangeListener(new QuantityView.OnNumChangeListener() {
            @Override
            public void onNuberChange(QuantityView cartQuantityView, EditText editText, int num) {

            }
        });
4、GitHub地址

https://github.com/aositeluoke/QuantityViewDemo

相关文章

  • 商品详情和购物车数量控件封装(造轮子QuantityView)

    使用效果如下: 在商城类软件中,�数量控件可以说是必备控件之一,网上开源的数量控件也有很多,但是还是想通过自己实现...

  • Vue + Vuex 实现购物车

    功能点拆分 在商品详情页点击添加购物车按钮,对应商品将传到购物车页面 购物车页面顶部商品数量展示 购物车页面商品列...

  • SYNumberEditView数量编辑UI控件

    SYNumberEditView数量编辑视图控件(如购物车中商品数量的增减)特别说明: 限制只能输入0~9的阿拉伯...

  • 手机淘宝购物车加支付原型图

    购物车页面原型图 说明: 1.购物车(x) x为购物车中商品种类数量(非总商品数量,同理结算(0) 0为结算时商品...

  • SSM框架学习日记(6)——购物车模块

    购物车相关接口 添加购物车,购物车列表,更新商品数量,删除购物车先新建CartController和CartSer...

  • iOS开发造轮子 | 滚动菜单栏

    iu 封装目的: 滚动菜单栏在实际项目中十分常见,为避免重复造轮子今天来一波总结及封装。虽然这种自定义控件在网上就...

  • 小程序开发-计算购物车总金额

    小程序开发-计算购物车总金额:循环遍历购物车商品,用价格*数量 注意:价格在商品表中,数量是购物车表中的。并需要使...

  • 安卓应用之简易购物车实现

    基本要求 1、分三个界面,商品界面、购物车界面和商品详情界面 2、使用adapter填充数据 3、点击购买后购物车...

  • QMUI学习

    QMUI 简介 QMUI是腾讯开源的一套UI工具框架,对于日常常见的UI控件做了诸多封装,省去了开发者不断造轮子+...

  • 添加购物车

    商品添加购物车; 先判断当前用户购物车是否存在该商品,若存在就更新当前用的购物车商品数量,若不存在,则新增该商品到...

网友评论

      本文标题:商品详情和购物车数量控件封装(造轮子QuantityView)

      本文链接:https://www.haomeiwen.com/subject/ugnvlxtx.html