【Android】HorizontalNumberPicker

好久没写了,发一个项目中用到的
支持单点,长按的 加减器

效果如如下

这里写图片描述

定义如下

private final int NUMBER_MIN = 0;//最小值
    private final int NUMBER_MAX = 100;//最大值
    private FrameLayout mFrameLayoutReduce;//减号
    private FrameLayout mFrameLayoutAdd;//加号
    private ImageView ivReduce;//减号图标
    private ImageView ivAdd;//加号图标
    private TextView tvNumber;//中间的文字
    private int number;//当前数字
    private boolean isStop;//是否停止
    private int longTime = 120;//长按的间隔
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    };
     private OnNumberChangeListener mOnNumberChangeListener;//监听器

初始化如下

public HorizontalNumberPicker(Context context) {
        super(context);
        initView();
    }

 public HorizontalNumberPicker(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

/**
 * 这里之所以要使用FrameLayout包在ImageView外面是为了不改变ImageView大小的前提下增大触摸范围
 */
 private void initView() {
        setGravity(Gravity.CENTER);
        mFrameLayoutReduce = new FrameLayout(getContext());
        mFrameLayoutAdd = new FrameLayout(getContext());
        mFrameLayoutReduce.setOnClickListener(this);
        mFrameLayoutReduce.setOnLongClickListener(this);
        mFrameLayoutReduce.setOnTouchListener(this);
        mFrameLayoutAdd.setOnClickListener(this);
        mFrameLayoutAdd.setOnLongClickListener(this);
        mFrameLayoutAdd.setOnTouchListener(this);
        ivReduce = new ImageView(getContext());
        ivAdd = new ImageView(getContext());
        tvNumber = new TextView(getContext());
        ivReduce.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
        ivReduce.setImageResource(R.mipmap.joinus_iv_reduce);
        ivAdd.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
        ivAdd.setImageResource(R.mipmap.joinus_iv_add);
        tvNumber.setGravity(Gravity.CENTER);
        tvNumber.setTextColor(getResources().getColor(R.color.line_gray));
        tvNumber.setTextSize(20);
        tvNumber.setText("0");
        int padding = DipPxUtil.dip2px(getContext(), 4);
        tvNumber.setPadding(padding, 0, padding, 0);
        LinearLayout.LayoutParams frameParams = new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT);
        frameParams.weight = 1;
        LayoutParams tvParams = new LayoutParams((int) tvNumber.getPaint().measureText(String.valueOf(NUMBER_MAX)) + 2 * padding, LayoutParams.MATCH_PARENT);//计算最大值需要多长的宽度
        addView(mFrameLayoutReduce, frameParams);
        addView(tvNumber, tvParams);
        addView(mFrameLayoutAdd, frameParams);
        FrameLayout.LayoutParams ivParamsReduce = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        ivParamsReduce.gravity = Gravity.CENTER_VERTICAL | Gravity.RIGHT;//往右
        mFrameLayoutReduce.addView(ivReduce, ivParamsReduce);
        FrameLayout.LayoutParams ivParamsAdd = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        ivParamsAdd.gravity = Gravity.CENTER_VERTICAL | Gravity.LEFT;//往左
        mFrameLayoutAdd.addView(ivAdd, ivParamsAdd);


    }

onMeasure

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        int widthMeasure = widthMeasureSpec;
        int heightMeasure = heightMeasureSpec;
        int paddingLeft = getPaddingLeft();
        int paddingTop = getPaddingTop();
        int paddingRight = getPaddingRight();
        int paddingBottom = getPaddingBottom();

        if (widthMode != MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY) {  //width,height均为wrap_content下的默认宽高
            int width = DipPxUtil.dip2px(getContext(), 80) + paddingLeft + paddingRight;
            int height = DipPxUtil.dip2px(getContext(), 30) + paddingTop + paddingBottom;
            widthMeasure = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
            heightMeasure = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
        } else if (widthMode != MeasureSpec.EXACTLY) {
            int width = DipPxUtil.dip2px(getContext(), 80) + paddingLeft + paddingRight;
            widthMeasure = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
        } else if (heightMode != MeasureSpec.EXACTLY) {
            int height = DipPxUtil.dip2px(getContext(), 30) + paddingTop + paddingBottom;
            heightMeasure = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
        }
        super.onMeasure(widthMeasure, heightMeasure);
    }

处理

/**
 *处理单击
 */
    @Override
    public void onClick(View v) {
        if (v == mFrameLayoutAdd) {
            number++;
        } else if (v == mFrameLayoutReduce) {
            number--;
        }
        setNumber(number);
    }

/**
 *处理长按,这里是按得越久速度越快
 */
    @Override
    public boolean onLongClick(final View v) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (!isStop) {
                    mHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            if (v == mFrameLayoutAdd) {
                                number++;
                            } else if (v == mFrameLayoutReduce) {
                                number--;
                            }
                            setNumber(number);
                            longTime = longTime < 30 ? 30 : longTime - 8;
                        }
                    }, longTime);
                    try {
                        Thread.sleep(longTime);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        return true;
    }

/**
 *处理长按后松开手机后,恢复速度
 */
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                isStop = false;
                break;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_UP:
                isStop = true;
                longTime = 120;
                break;
        }

        return false;
    }
/**
 *检查
 */
    private void CheckNumber() {
        if (number < NUMBER_MIN) {
            number = NUMBER_MIN;
        } else if (number > NUMBER_MAX) {
            number = NUMBER_MAX;
        }
    }

    public int getNumber() {
        return number;
    }

/**
 *设置数字
 */
    public void setNumber(int number) {
        this.number = number;
        CheckNumber();
        tvNumber.setText(String.valueOf(this.number));
        if (this.number == 0) {
            tvNumber.setTextColor(getResources().getColor(R.color.line_gray));
        } else {
            tvNumber.setTextColor(getResources().getColor(R.color.joinus_main_text_gold));
        }
        if (mOnNumberChangeListener != null) {
            mOnNumberChangeListener.onNumber(this, this.number);
        }
    }

/**
 *数字变化的监听
 */
    public interface OnNumberChangeListener {
        void onNumber(HorizontalNumberPicker numberPicker, int number);

    }

    public OnNumberChangeListener getOnNumberChangeListener() {
        return mOnNumberChangeListener;
    }

    public void setOnNumberChangeListener(OnNumberChangeListener onNumberChangeListener) {
        mOnNumberChangeListener = onNumberChangeListener;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值