自定义view之路--数量加减view--适用电商类

主要功能简介:根据设置的库存以及选择的数量左右图片可更换,且超过库存不可增加,最低为1.点击数量可弹出dialog输入数量。可监听数量变更以便保存当前选择数量供程序下一步操作。

主要思路:利用组合view的方式,完成数量加减的布局。本view主要是减少相同模块的逻辑代码,方便使用,增加复用性。自定义view创建的方式见本人另外的文章。主要使用、以及view介绍见下面基类说明。如有疑问,请留言。底部有下载链接,无分可点赞留邮箱,谢谢。
这里写图片描述

  • view类

/**
 * 说明:数值选择view,可以选择数量,并且在回调里处理具体逻辑
 * 功能简介:可以在xml里或者代码中设置左右view的图片、默认库存大小、当前数值、文本大小、文本颜色以及背景边框
 * 使用注意:
 * 1)需要在attr里面写入下面代码
 * <declare-styleable name="QuantityChooseView">
 * <attr name="maxQuantity" format="integer"/>
 * <attr name="quantity" format="integer"/>
 * <attr name="rightViewEnableSrc" format="integer"/>
 * <attr name="rightViewDisableSrc" format="integer"/>
 * <attr name="leftViewEnableSrc" format="integer"/>
 * <attr name="leftViewDisableSrc" format="integer"/>
 * <attr name="quantityTextSize" format="integer"/>
 * <attr name="quantityTextColor" format="color"/>
 * </declare-styleable>
 * 2)默认左右图片ic_launcher
 * 3)本view也需要下面strings
 * <string name="msg_null_number">Please input number!</string>
 * <string name="msg_error_onlyOneAbove">Can only enter one above!</string>
 * <string name="dialog_title_quantity">Input Quantity</string>
 * <string name="cancel">Cancel</string>
 * <string name="confirm">Confirm</string>
 * 4) dialog需要引用MaterialDialog
 * <p/>
 * by tc 2015/01/08
 * version 1.0
 */
public class QuantityChooseView extends LinearLayout {
    public static final String TAG = QuantityChooseView.class.getSimpleName();
    /**
     * 监听数量变化
     */
    private OnQuantityChangeListener mOnQuantityChangeListener;
    /**
     * 默认库存大小
     */
    private static final int DEFAULT_QUANTITY = 99999;
    /**
     * 最大数量
     */
    private int mMaxQuantity = DEFAULT_QUANTITY;
    /**
     * 数量
     */
    private int mQuantity = 1;

    /**
     * 右侧按钮图片
     */
    private ImageView mIvRight;
    /**
     * 右侧按钮图片数据源--可操作
     */
    private int mIvRightEnableSrc = -1;
    /**
     * 右侧按钮图片数据源--不可操作
     */
    private int mIvRightDisableSrc = -1;
    /**
     * 左侧按钮图片
     */
    private ImageView mIvLeft;
    /**
     * 左侧按钮图片数据源--可操作
     */
    private int mIvLeftEnableSrc = -1;
    /**
     * 左侧按钮图片数据源--不可操作
     */
    private int mIvLeftDisableSrc = -1;

    /**
     * 数量文本
     */
    private TextView mTvQuantity;
    /**
     * 数量文本的颜色
     */
    private int mQuantityTextColor = -1;
    /**
     * 选中数量的字体大小
     */
    private float mQuantityTextSize = 0;
    /**
     * 数字选择弹框
     */
    private MaterialDialog mMaterialDialog;
    /**
     * 上一次选择的数值
     */
    private int mLastSelectQuantity;

    public QuantityChooseView(Context context) {
        super(context);
        init(context, null);
    }

    public QuantityChooseView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);


    }

    public QuantityChooseView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public QuantityChooseView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        this.removeAllViews();
        if (attrs != null) {
            TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.QuantityChooseView);
            mMaxQuantity = a.getInt(R.styleable.QuantityChooseView_maxQuantity, DEFAULT_QUANTITY);
            mQuantity = a.getInt(R.styleable.QuantityChooseView_quantity, 1);
            mIvRightEnableSrc = a.getResourceId(R.styleable.QuantityChooseView_rightViewEnableSrc, -1);
            mIvRightDisableSrc = a.getResourceId(R.styleable.QuantityChooseView_rightViewDisableSrc, -1);
            mIvLeftEnableSrc = a.getResourceId(R.styleable.QuantityChooseView_leftViewEnableSrc, -1);
            mIvLeftDisableSrc = a.getResourceId(R.styleable.QuantityChooseView_leftViewDisableSrc, -1);
            mQuantityTextSize = a.getInt(R.styleable.QuantityChooseView_quantityTextSize, 0);
            mQuantityTextColor = a.getColor(R.styleable.QuantityChooseView_quantityTextColor, -1);
            a.recycle();
        }
        mMaterialDialog = new MaterialDialog(context);

        mIvRight = new ImageView(context);
        mTvQuantity = new TextView(context);
        mIvLeft = new ImageView(context);

        this.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        this.setOrientation(HORIZONTAL);
        mIvRight.setBackgroundDrawable(null);
        mIvLeft.setBackgroundDrawable(null);

        mIvRight.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        mTvQuantity.setLayoutParams(new ViewGroup.LayoutParams(dip2px(context, 50), ViewGroup.LayoutParams.MATCH_PARENT));
        mTvQuantity.setGravity(Gravity.CENTER);
        mIvLeft.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));

        JudgeNumberAndShowDifferentView(false);
        if (mQuantityTextSize <= 0) {
            mQuantityTextSize = 10;
        }
        mTvQuantity.setTextSize(mQuantityTextSize);
        if (mQuantityTextColor != -1) {
            mTvQuantity.setTextColor(mQuantityTextColor);
        } else {
            mTvQuantity.setTextColor(Color.BLACK);
        }
        this.addView(mIvLeft);
        this.addView(mTvQuantity);
        this.addView(mIvRight);
        initEvent();

    }


    /**
     * 初始化左右view的点击事件
     */
    private void initEvent() {
        mIvRight.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                mQuantity++;
                JudgeNumberAndShowDifferentView(true);
            }
        });
        mIvLeft.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                mQuantity--;
                JudgeNumberAndShowDifferentView(true);
            }
        });
        mTvQuantity.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                final EditText et = new EditText(getContext());
                et.setTextSize(14);
                et.setInputType(InputType.TYPE_CLASS_NUMBER);
                et.setTextColor(getContext().getResources().getColor(
                        R.color.blue_new));
                et.setSingleLine(true);
                et.setImeOptions(EditorInfo.IME_ACTION_SEARCH);
                et.setGravity(Gravity.CENTER);
                et.setWidth(dip2px(getContext(), 20));
                et.setText(String.valueOf(mQuantity));
                et.setSelection(et.getText().toString().length());
                et.setBackgroundResource(R.drawable.linearlayout_border_blue);
                mMaterialDialog = new MaterialDialog(getContext());
                mMaterialDialog.setTitle(getContext().getResources().getString(
                        R.string.dialog_title_quantity));
                mMaterialDialog.setContentView(et);
                mMaterialDialog.setTitle(getContext().getResources().getString(
                        R.string.dialog_title_quantity));
                mMaterialDialog.setPositiveButton(R.string.confirm, new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        mQuantity = toInt(et.getText().toString());
                        submitNumber(et);
                    }
                });
                mMaterialDialog.setNegativeButton(R.string.cancel, new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        mMaterialDialog.dismiss();
                    }
                });
                mMaterialDialog.setCanceledOnTouchOutside(true);
                mMaterialDialog.show();
                mMaterialDialog.showSoftInput();
            }
        });
    }

    /**
     * 弹出数值选择对话框的数值校验
     *
     * @param et
     */
    private void submitNumber(EditText et) {
        String intStr = et.getText().toString();
        if (TextUtils.isEmpty(intStr)) {
            Toast.makeText(getContext(), getContext().getResources().getString(R.string.msg_null_number), Toast.LENGTH_LONG).show();
            return;
        } else if (intStr.equals("0")) {
            Toast.makeText(getContext(), getContext().getResources().getString(R.string.msg_error_onlyOneAbove), Toast.LENGTH_LONG).show();
            return;
        } else if (toInt(intStr) > mMaxQuantity) {// 如果大于库存
            mQuantity = mMaxQuantity;

        } else {
            mQuantity = toInt(intStr);// 先格式化,避免用户输入01这种格式的数字
        }
        JudgeNumberAndShowDifferentView(true);
        mMaterialDialog.dismiss();

    }

    /**
     * 校验数值以及显示不同的左右图片
     */
    private void JudgeNumberAndShowDifferentView(boolean isInformToQuantityChangeListener) {
        if (mQuantity <= 1) {
            if (mQuantity >= mMaxQuantity) {//选择的数量等于库存
                mQuantity = mMaxQuantity;
                setRightAddEnable(false);
                setLeftSubtractEnable(false);
            } else {
                mQuantity = 1;
                setRightAddEnable(true);
                setLeftSubtractEnable(false);
            }
        } else {
            if (mQuantity >= mMaxQuantity) {//选择的数量大于等于库存
                mQuantity = mMaxQuantity;
                setRightAddEnable(false);
                setLeftSubtractEnable(true);
            } else {
                setRightAddEnable(true);
                setLeftSubtractEnable(true);
            }

        }
        mTvQuantity.setText(String.valueOf(mQuantity));
        if (isInformToQuantityChangeListener) {
            if (mLastSelectQuantity != mQuantity)
                if (mOnQuantityChangeListener != null) {
                    mOnQuantityChangeListener.onQuantityChange(mQuantity, mLastSelectQuantity);
                }
        }
        mLastSelectQuantity = mQuantity;
    }


    //---------------get,set------------------
    private void setRightAddEnable(boolean isEnable) {
        if (isEnable) {
            mIvRightEnableSrc = mIvRightEnableSrc != -1 ? mIvRightEnableSrc : R.mipmap.ic_launcher;
            mIvRight.setImageResource(mIvRightEnableSrc);
        } else {
            mIvRightDisableSrc = mIvRightDisableSrc != -1 ? mIvRightDisableSrc : R.mipmap.ic_launcher;
            mIvRight.setImageResource(mIvRightDisableSrc);
        }
    }

    private void setLeftSubtractEnable(boolean isEnable) {
        if (isEnable) {
            mIvLeftEnableSrc = mIvLeftEnableSrc != -1 ? mIvLeftEnableSrc : R.mipmap.ic_launcher;
            mIvLeft.setImageResource(mIvLeftEnableSrc);
        } else {
            mIvLeftDisableSrc = mIvLeftDisableSrc != -1 ? mIvLeftDisableSrc : R.mipmap.ic_launcher;
            mIvLeft.setImageResource(mIvLeftDisableSrc);
        }
    }

    public void setOnQuantityChangeListener(OnQuantityChangeListener mOnQuantityChangeListener) {
        this.mOnQuantityChangeListener = mOnQuantityChangeListener;
    }

    public int getMaxQuantity() {
        return mMaxQuantity;
    }

    public void setMaxQuantity(int mMaxQuantity) {
        this.mMaxQuantity = mMaxQuantity;
        invalidate();
    }

    public int getQuantity() {
        return mQuantity;
    }

    public void setQuantity(int mQuantity) {
        this.mQuantity = mQuantity;
        JudgeNumberAndShowDifferentView(false);
    }


    public void setIvRightEnableSrc(int mIvRightEnableSrc) {
        this.mIvRightEnableSrc = mIvRightEnableSrc;
    }


    public void setIvRightDisableSrc(int mIvRightDisableSrc) {
        this.mIvRightDisableSrc = mIvRightDisableSrc;
    }


    public void setIvLeftEnableSrc(int mIvLeftEnableSrc) {
        this.mIvLeftEnableSrc = mIvLeftEnableSrc;
    }


    public void setIvLeftDisableSrc(int mIvLeftDisableSrc) {
        this.mIvLeftDisableSrc = mIvLeftDisableSrc;
    }


    public void setQuantityTextColor(int mQuantityTextColor) {
        this.mQuantityTextColor = mQuantityTextColor;
    }

    public void setQuantityTextSize(float mQuantityTextSize) {
        this.mQuantityTextSize = mQuantityTextSize;
    }
//---------------get,set------------------


    public interface OnQuantityChangeListener {
        /**
         * 数量变更的监听
         *
         * @param currentSelectQuantity 当前选择的数量
         * @param lastSelectQuantity    上一次选择的数量
         */
        void onQuantityChange(int currentSelectQuantity, int lastSelectQuantity);
    }

//-----------------工具方法,为了避免过多引用util,所以本view自带下面方法----------------------------

    /**
     * 转换为整形
     *
     * @param value value
     * @return value
     */
    public static int toInt(String value) {
        int defaultValue = 0;
        if (!isNumeric(value)) {
            return defaultValue;
        }
        try {
            return Integer.parseInt(value);
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    /**
     * 判断是否为数字
     *
     * @param value value
     * @return true
     */
    public static boolean isNumeric(String value) {
        if (TextUtils.isEmpty(value))
            return false;
        Pattern pattern = Pattern.compile("^([-\\+]?[1-9]([0-9]*)(\\.[0-9]+)?)|(^0$)$");
        Matcher matcher = pattern.matcher(value);
        return matcher.find();
    }

    /**
     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
     */
    private int dip2px(Context context, final float dpValue) {
        float density = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * density + 0.5f);
    }

}
  • 具体布局
<com.xx.widgets.QuantityChooseView
    android:id="@+id/qcv_shopping_cart_quantity"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    android:background="@drawable/linearlayout_border_gray"
    android:padding="1px"
    app:leftViewDisableSrc="@mipmap/icon_subtract_gray"
    app:leftViewEnableSrc="@mipmap/icon_subtract_orange"
    app:quantity="1"
    app:quantityTextColor="@color/white"
    app:quantityTextSize="12"
    app:rightViewDisableSrc="@mipmap/icon_add_gray"
    app:rightViewEnableSrc="@mipmap/icon_add"/>

源码下载地址:http://download.csdn.net/detail/u010716109/9424223

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值