自定义控件实践-倒计时控件

2017-11-01  本文已影响0人  冰凌孤星

效果预览

目前项目中用到了一个倒计时控件, 觉的还不错. 所以分享出来. 有需要的同学可以直接拿去用. 废话不多说, 先看看效果:

jdfw.gif

分析需求

实现一个自定义控件, 先分析控件的初始状态和构成.

代码实现

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

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

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

    private void init() {

        mDisplayMetrics = getContext().getResources().getDisplayMetrics();
        t = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, t, mDisplayMetrics);
        //环的画笔
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        float strokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, mDisplayMetrics);
        mPaint.setStrokeWidth(strokeWidth);//圆圈的线条粗细
        //文本画笔
        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setColor(Color.WHITE);

        //默认总时间
        mM = String.valueOf(mTotalTime / 1000 / 60);
        mS = "00";

        setClickable(true);
    } 
 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mMWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();

        int mHigh = mMWidth;
        //范围
        mRectF = new RectF(t, t, mMWidth - t, mHigh - t);
    }

2.onDraw方法中就要绘制了. 控件在倒计时的时候外层有变化. 里面也有变化. 这些变化都应该是更具剩余时间百分比来的. 而背景 剩余时间 这些元素没有发生变化


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //整体背景
        mPaint.setStyle(Paint.Style.FILL); //绘制图形的描边
        mPaint.setColor(getResources().getColor(R.color.black_27));
        canvas.drawArc(mRectF, -90, 360, false, mPaint);
        //外环 背景绿色
        mPaint.setStyle(Paint.Style.STROKE); //绘制图形的描边
        mPaint.setColor(getResources().getColor(R.color.blue_86));
        canvas.drawArc(mRectF, -90, 360, false, mPaint);
        //剩余时间 文字
        String s = "剩余时间";
        float ts = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10, mDisplayMetrics);
        mTextPaint.setTextSize(ts);
        mTextPaint.setColor(getResources().getColor(R.color.text_color_99));
        float x = mTextPaint.measureText(s);
        canvas.drawText(s, mMWidth / 2 - x / 2, (float) mHeight * 0.4f, mTextPaint);

//        动态改变的部分
        //内环 背景灰色
        mPaint.setColor(getResources().getColor(R.color.gray_c1));
        mPaint.setStrokeCap(Paint.Cap.SQUARE);
        float swap = mPersent * 360;
        canvas.drawArc(mRectF, -90, swap, false, mPaint);

        // 绘制进度文案显示
        String text = mM + ":" + mS;
        float textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 21, mDisplayMetrics);
        float textWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 7, mDisplayMetrics);
        mTextPaint.setStrokeWidth(textWidth);
        mTextPaint.setTextSize(textSize);
        mTextPaint.setColor(getResources().getColor(R.color.text_color_ff));
        mTextPaint.setStyle(Paint.Style.FILL);
        float width = mTextPaint.measureText(text);
        canvas.drawText(text, mMWidth / 2 - width / 2, (float) mHeight * 0.65f, mTextPaint);
    }
  /**
     * 开始倒计时
     */
    public void starTimecount() {
        if (mCountDownTimer != null) {
            mCountDownTimer.cancel();
        }

        mRemineTime = mRemineTime == -1 ? mTotalTime : mRemineTime;

        mCountDownTimer = new CountDownTimer(mRemineTime, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
                mPersent = (mTotalTime - millisUntilFinished) / (float)mTotalTime;
                Log.i("zmin.............", ".persent..." + mPersent);
                changeForTimeText((int) millisUntilFinished / 1000);
                invalidate();
            }

            @Override
            public void onFinish() {
                mPersent = 1;
                changeForTimeText(0);
                invalidate();
                if (mOnTimeCountListener != null) {
                    mOnTimeCountListener.finish();
                }
            }
        };
        mCountDownTimer.start();
    }

 /**
     * 设置总时间时间
     *
     * @param second 秒
     */
    public void setTotalTime(int second) {
        mTotalTime = second * 1000;
        changeForTimeText(second);
    }

    /**
     * 设置倒计时时间
     *
     * @param second 剩余时间单位 秒
     */
    public void setRemineTime(int second) {
        if (mCountDownTimer != null) {
            mCountDownTimer.cancel();
            mCountDownTimer = null;
        }
        if (second > mTotalTime / 1000) {
            try {
                throw new Exception("the time your set is less than total time, please reset it ");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return;
        }
        mRemineTime = second * 1000;
        changeForTimeText(second);
        starTimecount();
    }

总结

实现这个自定义控件主要分析其中的逻辑. 找到总时间、剩余时间、控件外圈进度条和倒计时时间文本之间的关系 然后一步步写。 应该还是比较简单的~~
Demo地址: https://github.com/zmin666/LoopView
如果对你有帮助 欢迎star ~~

上一篇下一篇

猜你喜欢

热点阅读