Android 自定义View 滑动解锁

自定义view来绘制一个类似滑动解锁的button,注释都在,效果如下

 

 

代码在下面,替换一下资源,可以直接使用,如果需要画的是圆角的话,需要把下面两行注释的DrawLine的注释打开,然后把两行drawRoundRect注释掉。

 

package com.vendingontrack.vendcoin.customView;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

import com.vendingontrack.vendcoin.R;


public class SlideUnlockView extends View {

    private Paint mPaint;//绘制背景
    private Paint mTextPaint;//绘制文字
    private Paint mSlideTextPaint;//滑动文字
    private Paint mSwipeBgPaint;
    private Bitmap mIconBitmap;
    private int mWidth;
    private int mHeight;
    private int mPadding;
    private String content = "Slide to begin";
    private String mSlideContent = "VendCoin";
    private Rect mTextRect;
    private float mDrawX;
    private boolean mCanMove;
    private OnUnlockListener mListener;
    private int mBackgroudColor;
    private int mTextColor;
    private int mIconId;
    private boolean unSlide;
    private int mFillColor;
    private Context mContext;
    private boolean isSlide;

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

    public SlideUnlockView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public SlideUnlockView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        initAttr(attrs);
        init();
    }

    private void initAttr(AttributeSet attrs){
        TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.SlideUnlockView);
        mBackgroudColor = ta.getColor(R.styleable.SlideUnlockView_backgroundColor,getResources().getColor(R.color.color_E9DDC7));
        mTextColor = ta.getColor(R.styleable.SlideUnlockView_textColor,getResources().getColor(R.color.clolor_091431));
        mIconId = ta.getResourceId(R.styleable.SlideUnlockView_icon, R.drawable.icon_thumb);
//        unSlide = ta.getBoolean(R.styleable.SlideUnlockView_unSlide,false);
        ta.recycle();
    }

    //设置为不可滑动
    public void setUnSlide(boolean unable){
        this.unSlide = unable;
    }

    private void init() {

        mTextPaint = new Paint();
        mTextPaint.setColor(mTextColor);
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextSize(sp2px(getContext(),16));
        mTextRect = new Rect();
        mTextPaint.getTextBounds(content,0,content.length(),mTextRect);

        mSlideTextPaint = new Paint();
        mSlideTextPaint.setColor(mContext.getResources().getColor(R.color.color_E9DDC7));
        mSlideTextPaint.setAntiAlias(true);
        mSlideTextPaint.setTextSize(sp2px(getContext(),22));
//        mTextRect = new Rect();
        mSlideTextPaint.getTextBounds(mSlideContent,0,mSlideContent.length(),mTextRect);



        mIconBitmap = BitmapFactory.decodeResource(getResources(), mIconId);
        mPadding  = 0;


        mHeight = mIconBitmap.getHeight()+mPadding*2;
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setColor(mBackgroudColor);
        mPaint.setStrokeWidth(mHeight);

        mSwipeBgPaint = new Paint();
        mSwipeBgPaint = new Paint();
        mSwipeBgPaint.setAntiAlias(true);
        mSwipeBgPaint.setStyle(Paint.Style.FILL);
        mSwipeBgPaint.setStrokeCap(Paint.Cap.ROUND);
        mSwipeBgPaint.setColor(mContext.getResources().getColor(R.color.clolor_091431));
        mSwipeBgPaint.setStrokeWidth(mHeight);

        //默认滑动图标跟文字间的间隔
        int middle = dp2px(getContext(), 20);
        mWidth = mPadding + mHeight*2 + mTextRect.width() + middle *2;

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int wSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int wSpecSize = MeasureSpec.getSize(widthMeasureSpec);

        //如果设定的宽度比控件默认需求的大,则修改,否则就用默认宽度
       if (wSpecMode == MeasureSpec.EXACTLY){
            if (wSpecSize>mWidth){
                mWidth = wSpecSize;
            }
        }

        setMeasuredDimension(mWidth,mHeight);

    }

    public void setUnlockListener(OnUnlockListener listener){
        mListener = listener;
    }


    @Override
    protected void onDraw(Canvas canvas) {

        if (mDrawX < mPadding ){
            mDrawX = mPadding;
        }else if (mDrawX > mWidth - mIconBitmap.getWidth()-mPadding){
            mDrawX = mWidth - mIconBitmap.getWidth()-mPadding;
        }



        canvas.drawRoundRect(new RectF(0, 0, mWidth, mHeight), 18, 18, mPaint);

        //画背景颜色,需要给圆形笔锋预留半个高度的位置
//        canvas.drawLine(mHeight/2,mHeight/2,mWidth-mHeight/2,mHeight/2,mPaint);
        int textX = mWidth / 2 - mTextRect.width()/2;

//        canvas.drawLine(mHeight/2,mHeight/2,mDrawX+mIconBitmap.getWidth()/2,mHeight/2,mSwipeBgPaint);

        canvas.drawRoundRect(new RectF(0, 0, mDrawX+mIconBitmap.getWidth(), mHeight), 18, 18, mSwipeBgPaint);


        if(isSlide){
            canvas.drawText(mSlideContent, textX, mHeight / 2 + mTextRect.height() / 2, mSlideTextPaint);
        }else {
            //绘制文字到中间位置
            canvas.drawText(content, textX, mHeight / 2 + mTextRect.height() / 2, mTextPaint);
        }

        //根据滑动位置绘制图标
        canvas.drawBitmap(mIconBitmap,mDrawX,mPadding,mPaint);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                isSlide = false;
                //如果不可滑动,立即返回
                if (unSlide)return false;
                if (x <= mIconBitmap.getWidth()+mPadding){
                    mCanMove = true;
                }
                return true;
            case MotionEvent.ACTION_MOVE:
                //如果是可移动状态才继续绘制
                if (mCanMove){
                    isSlide = true;
                    mDrawX = x;
                    invalidate();
                }
                return true;
            case MotionEvent.ACTION_UP:
                isSlide = false;
                //如果是可移动状态才继续绘制
                if (mCanMove){
                    reset();
                    mCanMove = false;
                    //判断是否在指定位置抬起手指
                    if (mDrawX >= mWidth - mIconBitmap.getWidth()-mPadding){
                        if (mListener!=null)
                            mListener.onUnlock();
                    }
                }
                break;

        }
        return super.onTouchEvent(event);
    }

    public void setmCanMove(boolean canMove){
        mCanMove = canMove;
    }

    //用属性动画将图标位置重置
    private void reset(){
        ObjectAnimator animator = ObjectAnimator.ofFloat(this,"mDrawX",mDrawX,mPadding);
        animator.setDuration(200);
        animator.start();
    }

    private float getMDrawX() {
        return mDrawX;
    }

    private void setMDrawX(float mDrawX) {
        this.mDrawX = mDrawX;
        invalidate();
    }

    public interface OnUnlockListener{
        void onUnlock();
    }

    /**
     * dp转px
     *
     * @param context 上下文
     * @param dpValue dp值
     * @return px值
     */
    public static int dp2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }


    /**
     * sp转px
     *
     * @param context 上下文
     * @param spValue sp值
     * @return px值
     */
    public static int sp2px(Context context, float spValue) {
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }


}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值