自定义View实战之开关按钮实现

图片预览
这里写图片描述

1. 分析

1. 开关按钮这个可以考虑用两个图片来实现 
2. 一个背景图片,一个开关图片
3. 通过手势移动切换开关状态 换图
4. 然后做动画处理
5. 当然可以完全自定义 画两个圆角矩形 切换的时候重绘控件

2. 实现原理

1. 需要实现onMeasure处理控件宽高为wrap_content时的宽高
2. 考虑用图片做开关背景还是完全自定义,加一个字段区分
3. 在onTouchEvent中处理开关事件
4. 动画处理

3. 初始化一些东西 初始化一般我放在onSizeChanged方法中

   @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);

    mViewX = w;
    mViewY = h;
    //计算开关按钮的偏移量
    mToggleOffsetX = -mViewX / 2 + dp2px(1);

    if(mToggleType == 1){

        Resources resources = getResources();

        Drawable closeDrawable = resources.getDrawable(mToggleCloseBackGroundImg);
        mCloseBgBitmap = drawableToBitmap(closeDrawable, w, h);

        Drawable openDrawable = resources.getDrawable(mToggleOpenBackGroundImg);
        mOpenBgBitmap = drawableToBitmap(openDrawable, w, h);

        Drawable leftDrawable = resources.getDrawable(mToggleSwitchImg);
        mToggleBitmap = drawableToBitmap(leftDrawable, (int) (w * 0.5f), h - dp2px(2));
    }
}

4. 绘制开关按钮

方式一:完全自定义 画圆角矩形

 private void drawSwitchToggle1(Canvas canvas) {

    //画背景圆角矩形
    if(mToggleOffsetX == -mViewX / 2 + dp2px(1)){
        mBackGroundPaint.setColor(mToggleCloseColor);
    }else{
        mBackGroundPaint.setColor(mToggleOpenColor);
    }
    mBgRectF.set(-mViewX / 2,-mViewY / 2,mViewX / 2,mViewY / 2);
    canvas.drawRoundRect(mBgRectF,mToggleRoundRadius,mToggleRoundRadius,mBackGroundPaint);

    //画开关按钮圆角矩形
    mToggleRectF.set(mToggleOffsetX, -mViewY / 2 + dp2px(1), mToggleOffsetX + mViewX / 2, mViewY / 2 - dp2px(1));
    canvas.drawRoundRect(mToggleRectF,mToggleRoundRadius,mToggleRoundRadius, mTogglePaint);
}

方式二:通过画背景图和开关图来回切换

 private void drawSwitchToggle2(Canvas canvas) {
    //画背景图
    if(mToggleOffsetX == -mViewX / 2 + dp2px(1)) {
        canvas.drawBitmap(mCloseBgBitmap, -mCloseBgBitmap.getWidth() / 2, -mCloseBgBitmap.getHeight() / 2, mTogglePaint);
    }else{
        canvas.drawBitmap(mOpenBgBitmap, -mCloseBgBitmap.getWidth() / 2, -mCloseBgBitmap.getHeight() / 2, mTogglePaint);
    }
    //画开关按钮图
    canvas.drawBitmap(mToggleBitmap, mToggleOffsetX,-mCloseBgBitmap.getHeight() / 2 + dp2px(1), mTogglePaint);
}

5. 触摸事件onTouchEvent方法处理

@Override
public boolean onTouchEvent(MotionEvent event) {
    float distanceY = 0f;
    float startY = 0f;
    switch (event.getAction()){
        case MotionEvent.ACTION_DOWN:
            mIsToggleMove = false;
            mStartX = event.getX();
            startY = event.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            float moveX = event.getX();
            float moveY = event.getY();
            mDistanceX = moveX - startY;
            distanceY = moveY - startY;
            if(Math.abs(mDistanceX) > Math.abs(distanceY) && Math.abs(mDistanceX) >= mViewX / 2){
                mIsToggleMove = true;
            }else{
                mIsToggleMove = false;
            }
            mStartX = moveX;
            break;
        case MotionEvent.ACTION_UP:
            if(mIsToggleMove){
                if(mDistanceX < 0){
                    mToggleOffsetX = -mViewX / 2 + dp2px(1);
                    mLastX = -dp2px(1);
                    mCurrentX = (int) mToggleOffsetX;
                }else{
                    mToggleOffsetX = 0 - dp2px(1);
                    mLastX = - mViewX / 2 + dp2px(1);
                    mCurrentX = (int) mToggleOffsetX;
                }
                setToggleAnimation();
                return true;
            }
            break;
    }
    return super.onTouchEvent(event);
}


//点击事件处理
 @Override
public void onClick(View view) {
   Log.e("startX",mStartX+"");
    //点击开关同一侧 不做处理
    if((mToggleOffsetX == 0 - dp2px(1) && mStartX >= mViewX / 2)
            || (mToggleOffsetX == -mViewX / 2 + dp2px(1) && mStartX < mViewX / 2)){
        return;
    }

    if(mStartX >= mViewX / 2){
        mToggleOffsetX = 0 - dp2px(1);
        mLastX = - mViewX / 2 + dp2px(1);
        mCurrentX = (int) mToggleOffsetX;
    }else {
        mToggleOffsetX = -mViewX / 2 + dp2px(1);
        mLastX = -dp2px(1);
        mCurrentX = (int) mToggleOffsetX;
    }
    setToggleAnimation();
   // invalidate();
}

6. 动画处理

//给按钮添加动画
public void setToggleAnimation(){
    ValueAnimator toggleAnimator = ValueAnimator.ofFloat(mLastX, mCurrentX);
    toggleAnimator.setDuration(DURATION);
    toggleAnimator.setInterpolator(new AccelerateInterpolator());
    toggleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            mToggleOffsetX = (float) animation.getAnimatedValue();
            invalidate();
        }
    });
    toggleAnimator.start();
}

7. 项目源代码下载

后面统一提供下载地址

8. 联系方式

QQ:1509815887

猜你喜欢

转载自blog.csdn.net/rjgcszlc/article/details/80977898
今日推荐