自定义控件开关,绘制图片。

资源来源黑马培训机构教学视频

前段时间,学习了自定义控件,后来绝的用处很大,所以来和大家分享一下,自定义布局控件的使用,自定义控件,自己绘制控件。

步骤和另外一个一样,就不写步骤顺序那些麻烦的东西了。

主要的操作就是:
要自己写 onMeasure(…)方法。该方法 测量尺寸时的回调方法。
onDraw() 方法,该方法绘制
invalidate();该方法用于刷新,调用该方法后系统会自动调用onDraw();方法。

public class MyToggleButton extends View implements View.OnClickListener {

    //滑动图片的资源id
    private int slideBtnId;
    //背景图的资源id
    private int backgroundId;
    private Paint paint;
    private Bitmap backgroudBitmap;
    private Bitmap slideBtn;
    /** * 滑动按钮的左边接 */
    private float slideBtn_left = 0;

    //在代码里面创建对象的时候创建,使用该够着方法
    public MyToggleButton(Context context) {
        super(context);
    }

    /** * 在布局文件中声明 的 view 创建时系统自动调用 */
    public MyToggleButton(Context context, AttributeSet attrs) {
        super(context, attrs);

        //获得自定义的属性
        TypedArray ta = context.obtainStyledAttributes(
                attrs, R.styleable.MyToggleBtn);
        int n = ta.getIndexCount();
        for (int i = 0; i < n; i++) {
            /*获取某个属性的id值*/
            int itemId = ta.getIndex(i);
            switch (itemId) {
                case R.styleable.MyToggleBtn_curr_state:
                    currState = ta.getBoolean(itemId, false);

                    break;
                case R.styleable.MyToggleBtn_my_background:
                    backgroundId = ta.getResourceId(itemId, -1);
                    if (backgroundId == -1) {
                        throw new RuntimeException("请设置背景图片");
                    }
                    backgroudBitmap = BitmapFactory.decodeResource(
                            getResources(), backgroundId);
                    break;
                case R.styleable.MyToggleBtn_my_slide_btn:
                    slideBtnId = ta.getResourceId(itemId, -1);
                    if (slideBtnId == -1) {
                        throw new RuntimeException("请设置资源图片");
                    }
                    slideBtn = BitmapFactory.decodeResource(
                            getResources(), slideBtnId
                    );
                    break;
            }
        }
        initView();
    }

    private void initView() {
// backgroudBitmap = BitmapFactory.
// decodeResource(getResources(), R.drawable.switch_background);
// slideBtn = BitmapFactory.decodeResource(getResources(),
// R.drawable.slide_button);
        //初始化画逼
        paint = new Paint();

        paint.setAntiAlias(true);//打开抗锯齿

        //添加onclick的监听
        setOnClickListener(this);
        flushState();
    }

    /**' * view 对象显示的屏幕上,有几个步骤 * 1.构造方法的创建 * 2,测量view的大小 * 3,确定view的位置,view自身的一些建议权,决定权在父view手中的 * 4,绘制view的内容, * */

    /** * 测量尺寸时的回调方法。 * * @param widthMeasureSpec * @param heightMeasureSpec */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        /** * 设置当前view的 * 宽度,高度, --> 单位像素值。 */
        setMeasuredDimension(backgroudBitmap.getWidth(), backgroudBitmap.getHeight());
    }

    /* 确定位置的时候调用该方法 对自定义view的时候自定义不大。 */
// @Override
// protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
// super.onLayout(changed, left, top, right, bottom);
// }

    /** * 当前开关的状态,默认 开 */
    private boolean currState = false;

    @Override
    protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
        //绘制背景,paint绘制图片要使用的画笔
        canvas.drawBitmap(backgroudBitmap, 0, 0, paint);
        //绘制课滑动的按钮
        canvas.drawBitmap(slideBtn, slideBtn_left, 0, paint);
    }

    /** * 判断是否发送拖动了,就不相应onclick时间 */
    private boolean isDrag = false;


    /** * onclick事件在View.onTouchEvent 中被解析, * 系统对事件的解析,过于简陋,只有有down事件和up事件, * 系统便认为发生了onclick * * @param v */
    @Override
    public void onClick(View v) {
        if (!isDrag) {  //如果没有拖动,
            currState = !currState;
            flushState();
        }

    }


    /** * down 事件的x值 */
    private int firstX;
    /** * touch事件的上一个X值 */
    private int lastX;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                firstX = lastX = (int) event.getX();
                isDrag = false;
                break;
            case MotionEvent.ACTION_MOVE:
                //判断是否发生拖动,
                if (Math.abs(event.getX() - firstX) > 5) {
                    isDrag = true;
                }
                int dis = (int) (event.getX() - lastX);
                //将本次的位置,设置给lastX
                lastX = (int) event.getX();
                //根据手指移动的距离,改变slideBtn_left的值
                slideBtn_left = slideBtn_left + dis;
                break;
            case MotionEvent.ACTION_UP:
                //在发生拖动的情况下,根据最后的位置判断当前开关的额状态
                if (isDrag) {
                    int maxLeft = backgroudBitmap.getWidth() -
                            slideBtn.getWidth();
                    //根据slideBtn——left判段,当前应该是上面状态
                    if (slideBtn_left > maxLeft / 2) {
                        currState = true;
                    } else {
                        currState = false;
                    }
                    flushState();
                }
                break;
        }
        flushView();

        return true;//返回false将不处理函数
    }

    /** * 刷新当前视图 */
    private void flushView() {
        //要对 slideBtn_left的值进行判断,保证合理的位置
        int maxLeft = backgroudBitmap.getWidth() -
                slideBtn.getWidth();
        slideBtn_left = (slideBtn_left > 0) ? slideBtn_left : 0;
        slideBtn_left = (slideBtn_left < maxLeft) ? slideBtn_left : maxLeft;

        invalidate();//刷新当前视图,调用onDraw();


    }

    /** * 刷新当前状态 */
    private void flushState() {
        if (currState) {
            slideBtn_left = backgroudBitmap.getWidth()
                    - slideBtn.getWidth();
        } else {
            slideBtn_left = 0;
        }
        flushView();
    }
}

“`

注意,如果测试,一定要导入图片,这是绘制图片的自定义方法

你可能感兴趣的:(android)