ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Android 仿微信拍摄按钮

2020-12-24 12:29:41  阅读:188  来源: 互联网

标签:void float private CLICK callBack 按钮 Android 仿微信 public


自己写了一个另外版本,感觉不是很好,借鉴了一下老哥的代码,优化了一下,感谢老哥,尾部附链接。

 

简单粗暴,没有太多扩展,如果需要可以写一些扩展,我只是实现出来懒得扩展了,因为就是自己写着玩的,没有什么需求。

 

话不多说,直接上代码:

 

 

public class VideoTakeButton extends View {

    private static final String TAG = "VideoTakeButton";

    /**
     * 外边框半透明圆的画笔
     */
    private Paint mPaint0;

    /**
     * 内部圆的画笔
     */
    private Paint mPaint1;

    /**
     * 进度条的画笔
     */
    private Paint mPaint2;

    /**
     * 进度条动画
     */
    private ValueAnimator mProgressAni;

    /**
     * 最大拍摄时间,视频只能拍这么久
     */
    private int mMaxTime = 15;

    /**
     * 视频的最小拍摄时间,小于这个时间都按拍照处理
     */
    private float mMinTime = 0.6F;

    /**
     * 外边框的半透明圆的尺寸
     */
    private float bigCircleRadius = 0;
    /**
     * 外边框半透明圆的动画开始尺寸
     */
    private float bigCircleStartRadius = 0;
    /**
     * 外边框半透明圆的动画结束尺寸
     */
    private float bigCircleEndRadius = 0;

    /**
     * 内部圆的尺寸
     */
    private float smallCircleRadius = 0;
    /**
     * 内部圆的动画开始尺寸
     */
    private float smallCircleStartRadius = 0;
    /**
     * 内部圆的动画结束尺寸
     */
    private float smallCircleEndRadius = 40;

    /**
     * 拍摄视频的进度条
     */
    private float progress = 0;

    /**
     * 开始点击的消息码
     */
    private static final int START_CLICK = 0x001;
    /**
     * 长按事件的消息码
     */
    private static final int LONG_CLICK = 0x002;

    /**
     * 按钮按下时间
     */
    private long mStartTime = 0L;

    /**
     * 按钮抬起时间
     */
    private long mEndTime = 0L;
    /**
     * 长按最短时间  单位毫秒
     */
    public long LONG_CLICK_MIN_TIME = 800L;


    public VideoTakeButton(Context context) {
        super(context);
        init(context);
    }

    public VideoTakeButton(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public VideoTakeButton(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        mPaint0 = new Paint();
        mPaint0.setColor(Color.WHITE);
        mPaint0.setAlpha(150);

        mPaint1 = new Paint();
        mPaint1.setColor(Color.WHITE);
        mPaint1.setAlpha(255);

        mPaint2 = new Paint();
        mPaint2.setColor(Color.GREEN);
        mPaint2.setAlpha(255);

        //进度条的属性动画
        mProgressAni = ValueAnimator.ofFloat(0, 360f);
        mProgressAni.setDuration(mMaxTime * 1000);
    }

    private ViewHandler viewHandler = new ViewHandler(this);

    static class ViewHandler extends android.os.Handler {

        private WeakReference<VideoTakeButton> weakReference = null;

        public ViewHandler(VideoTakeButton videoTakeButton) {
            weakReference = new WeakReference<>(videoTakeButton);
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (weakReference == null || weakReference.get() == null) return;
            final VideoTakeButton videoTakeButton = weakReference.get();
            switch (msg.what) {
                case VideoTakeButton.START_CLICK:
                    videoTakeButton.startAnimationClick();
                    break;
                case VideoTakeButton.LONG_CLICK:
                    if (videoTakeButton.callBack != null) {
                        videoTakeButton.callBack.takeVideoStart();
                    }
                    break;
            }
        }
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);

        float x = getWidth();
        float y = getHeight();

        float pointX = x / 2;
        float pointY = y / 2;

        bigCircleStartRadius = x / 2 - x / 15;
        bigCircleEndRadius = x / 2;

        smallCircleStartRadius = x * 2 / 5 - x / 15;
        smallCircleEndRadius = (x * 2 / 5 - x / 15) / 2;
        if (isRecording) {
            canvas.drawCircle(pointX, pointY, bigCircleRadius, mPaint0);
            canvas.drawCircle(pointX, pointY, smallCircleRadius, mPaint1);
            //使用离屏绘制
            int layerID = canvas.saveLayer(0, 0, getWidth(), getHeight(), mPaint2, Canvas.ALL_SAVE_FLAG);
            canvas.drawArc(x / 15, x / 15, x - x / 15, x - x / 15, 270, progress, true, mPaint2);
            mPaint2.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
            canvas.drawArc(0, 0, x, x, 270, progress, true, mPaint2);
            mPaint2.setXfermode(null);
            canvas.restoreToCount(layerID);
        } else {
            bigCircleRadius = bigCircleStartRadius;
            canvas.drawCircle(pointX, pointY, bigCircleRadius, mPaint0);

            smallCircleRadius = smallCircleStartRadius;
            canvas.drawCircle(pointX, pointY, smallCircleRadius, mPaint1);
        }

    }

    private void startAnimationClick() {
        ValueAnimator smallCircle = ValueAnimator.ofFloat(smallCircleStartRadius, smallCircleEndRadius);
        smallCircle.setDuration(300);
        smallCircle.addUpdateListener(animation -> {
            smallCircleRadius = (float) animation.getAnimatedValue();
            invalidate();
        });
        ValueAnimator bigCircle = ValueAnimator.ofFloat(bigCircleStartRadius, bigCircleEndRadius);
        bigCircle.setDuration(300);
        bigCircle.addUpdateListener(animation -> {
            if (isRecording) {
                bigCircleRadius = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        smallCircle.start();
        bigCircle.start();
        smallCircle.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {

            }

            @Override
            public void onAnimationEnd(Animator animator) {
                //开始绘制圆形进度条
                if (isRecording) {
                    startAniProgress();
                }
            }

            @Override
            public void onAnimationCancel(Animator animator) {

            }

            @Override
            public void onAnimationRepeat(Animator animator) {

            }
        });
    }

    private void startAniProgress() {
        if (mProgressAni == null) return;
        mProgressAni.start();
        mProgressAni.addUpdateListener(valueAnimator -> {
            progress = (float) valueAnimator.getAnimatedValue();
            postInvalidate();
        });
        mProgressAni.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                isRecording = false;
                progress = 0;
                postInvalidate();
            }
        });
    }

    private boolean isRecording = false;

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                isRecording = true;
                mStartTime = System.currentTimeMillis();
                viewHandler.sendEmptyMessage(START_CLICK);
                viewHandler.sendEmptyMessageDelayed(LONG_CLICK, LONG_CLICK_MIN_TIME);
                break;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                isRecording = false;
                mEndTime = System.currentTimeMillis();
                if (mEndTime - mStartTime < LONG_CLICK_MIN_TIME) {
                    if (viewHandler.hasMessages(LONG_CLICK)) {
                        viewHandler.removeMessages(LONG_CLICK);
                    }
                    if (callBack != null) {
                        callBack.takePhoto();
                    }
                } else {
                    if (mProgressAni != null && progress / 10 < mMinTime) {
                        if (callBack != null) {
                            callBack.takePhoto();
                        }
                    } else {
                        if (callBack != null) {
                            callBack.takeVideoEnd();
                        }
                    }
                }
                if (mProgressAni != null) {
                    mProgressAni.cancel();
                }
                break;
        }
        return true;
    }

    interface CallBack {

        void takePhoto();

        void takeVideoStart();

        void takeVideoEnd();

    }

    private CallBack callBack;

    public void setCallBack(CallBack callBack) {
        this.callBack = callBack;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int screenWidth = getScreenWidth();
        int width = screenWidth * 23 / 100;
        setMeasuredDimension(width, width);
    }

    /**
     * 获取屏幕宽度
     *
     * @return
     */
    private int getScreenWidth() {
        WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics displayMetrics = new DisplayMetrics();
        windowManager.getDefaultDisplay().getMetrics(displayMetrics);
        return displayMetrics.widthPixels;
    }

}

 

 

感谢老哥:

标签:void,float,private,CLICK,callBack,按钮,Android,仿微信,public
来源: https://blog.csdn.net/try_zp_catch/article/details/111619497

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有