Android自定义view(三),简易的数值输入器

前言:前几天看到了迅雷app上有个一元夺宝,那时无聊就参加了几次,到后来中奖结果出来了,哎,根本就没我的份啊(意料之中),还好投的钱不多,就一块两块,不过,我看到了那里有个数值输入的效果,我当时想了想这个实现挺简单了,应该有很多种方式,于是做了个决定,如果没中奖,我就把那个数值输入器做出来以惩罚自己(开玩笑~),现在,该是兑现自己承诺的时候了。

先看看我们即将要实现的效果图:

这里写图片描述

大家看到这个效果,要实现这么一个控件,我们可以怎么做?

一开始,我心想,这还不简单,自定义一个view,然后分别画出左边的减号按钮,中间的输入控件,和右边的加法按钮,包括最外边的边框,最后重新view的事件监听方法,在里面判断点击的坐标,如果是点击了左边按钮的坐标范围,那么让中间的输入控件数值递减,如果是点击了右边按钮的坐标范围,那么让中间的输入按钮数值递增。

嗯,这听起来不错,好吧,我动手试着按照这种思路开始做了,当我在画中间的输入按钮的时候,我懵了,怎么才能画出一个可以让用户输入的控件?于是,我放弃了这种思路,开始了另一种思路。

接着,我想,这用类似组合控件的形式不是很简单吗,干嘛搞得那么复杂啊,这样一来,不是不仅不用自己画一个输入控件了,而且还不用计算点击坐标了。所以,下面将用组合控件的形式实现这个控件。

1. 自定义属性

 为了提供控件的可定制性,我们需要自定义属性,观察上面的效果图,我们可以定义下面9个属性供用户使用(当然,你也可以定义其他的属性供用户定制)

  1. border_color:边框的颜色
  2. border_width:边框的宽度
  3. minus_color:减号的颜色
  4. minus_width:…
  5. plus_color:加号的颜色
  6. plus_width:…
  7. min_value:允许的最小值
  8. initial_value:初始值
  9. max_value:允许的最大值

2. 自定义加减按钮

 为了解决耦合问题,那个减号,加号按钮使用自定义view绘图来实现,不引用任何资源,这里以加号按钮为例,做个说明(在文章结尾将会贴上全部代码)。

class PlusView extends View{

    private Paint mPlusPaint;

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

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

    public PlusView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mPlusPaint = new Paint();
        mPlusPaint.setAntiAlias(true);
        mPlusPaint.setStrokeWidth(mPlusWidth);
        mPlusPaint.setStyle(Paint.Style.STROKE);
        mPlusPaint.setStrokeCap(Paint.Cap.ROUND);
        mPlusPaint.setColor(mPlusColor);
    }

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

        if(widthMode == MeasureSpec.AT_MOST){
            widthSize = Math.min(widthSize,100);
        }
        if(heightMode == MeasureSpec.AT_MOST){
            heightSize = Math.min(heightSize,100);
        }
        setMeasuredDimension(widthSize,heightSize);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();
        canvas.drawLine(mWidth - mWidth / 5, mHeight / 2, mWidth / 5, mHeight / 2, mPlusPaint);
        canvas.save();
        canvas.rotate(90, mWidth / 2, mHeight / 2);
        canvas.drawLine(mWidth / 5, mHeight / 2, mWidth - mWidth / 5, mHeight / 2, mPlusPaint);
        canvas.restore();
    }
}

这里自定义view,就是在测量的时候判断一些测量模式,如果是AT_MOST模式,那么给个最小值。测量完了以后,在onDraw()方法中画个加号就行了,对于自定义view不熟悉的可以参考这篇文章:android自定义view(一),打造绚丽的验证码

3. 继承LinearLayout实现控件组合

 观察上面的效果图,可以看出这个控件的三部分是等宽的,所以,使用LinearLayout实现非常简单(weight属性),下面,定义类继承LinearLayout:

public class NumberInput extends LinearLayout {
   
   

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

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

    public NumberInput(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // viewGroup必须设置背景,这样才会调用onDraw()方法
        setBackgroundColor(Color.TRANSPARENT);
        init(context,attrs);
        initView(context);
    }
}

这里,三个构造方法的调用情况就不多说了,不懂的可以问度娘~。我们在构造方法中做了一些初始化的工作,包括获取布局属性值,添加子view等等。这里,要注意的事,viewGroup默认是不会调用onDraw()方法的,我们可以给它设置背景强制viewGroup调用onDraw()方法。

获取属性值:

/**
 * 获取自定义属性值
 */
private void init(Context context,AttributeSet attrs) {
    TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.NumberInput);
    mBorderColor = typedArray.getColor(R.styleable.NumberInput_border_color, Color.GRAY);
    mBorderWidth = typedArray.getDimension(R.styleable.NumberInput_border_width, 6);
    mMinusColor = typedArray.getColor(R.styleable.NumberInput_minus_color, Color.GRAY);
    mMinusWidth = typedArray.getDimension(R.styleable.NumberInput_minus_width, 5);
    mPlusColor = typedArray.getColor(R.styleable.NumberInput_plus_color, Color.GRAY);
    mPlusWidth = typedArray.getDimension(R.styleable.NumberInput_plus_width, 5);
    mInitialValue = typedArray.getInteger(R.styleable.NumberInput_initial_value, 0);
    mMinValue = typedArray.getInteger(R.styleable.NumberInput_min_value, Integer.MIN_VALUE);
    mMaxValue = typedArray.getInteger(R.styleable.NumberInput_max_value, Integer.MAX_VALUE);
    <
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值