博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
自定义控件实践-倒计时控件
阅读量:6760 次
发布时间:2019-06-26

本文共 5368 字,大约阅读时间需要 17 分钟。

效果预览

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

jdfw.gif

分析需求

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

  • 初始状态:
    image.png
    分析这个控件发现这个控件是一个整体 不是分散 控制的view... (⊙o⊙)…(什么是分散控制的view.常见的比如说滑动开关之类的) 既然如此 可知这个view应该是继承View的而不是ViewGroup.
  • 控制状态
    这个自定义view需要根据时间倒计时. 外层有个圈圈显示进度 内层有文本数字显示倒计时.倒计时就需要计时器 我用的是CountDownTimer来实现倒计时功能的.

代码实现

  • 第一步: 继承View,重写构造方法. 初始化一些参数.如下:

    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);  }复制代码
  • 第二步: 构造方法走完后就走 onMeasure onDraw方法了 这时候我们就要重写这些方法了.

    1.onMeasure 方法中要拿到控件的宽高信息 方便后面绘制的时候用到. 控件的范围采用矩形来约束

    @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);    }复制代码
  • 第三步: 控件的倒计时运行. 使用计时器 然后一秒钟回调一次onDraw方法 就能达到效果
/**     * 开始倒计时     */    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地址:
如果对你有帮助 欢迎star ~~

转载地址:http://babeo.baihongyu.com/

你可能感兴趣的文章
python基础-PyYaml操作yaml文件
查看>>
C# WPF 实现鼠标固定在指定范围内运动
查看>>
canvas绘图,html5 k线图,股票行情图
查看>>
Web前端设计模式——制作漂亮的弹出层
查看>>
Mozilla正计划修复Firefox遗留8年的漏洞
查看>>
Google C++单元测试框架(Gtest)系列教程之二——断言、函数测试
查看>>
Apex Design Patterns
查看>>
windows、linux创建子进程
查看>>
I.MX6 DNS 查看、修改方法
查看>>
供应链是什么意思
查看>>
HTML5的学习资料(开发设计原则)
查看>>
应用程序栏【WP7学习札记之九】
查看>>
utf-8引发的页面空白
查看>>
Controller的要求
查看>>
(转) Android中shape的使用
查看>>
制作WinPE
查看>>
mysql中文字段排序( 按拼音首字母排序)的查询语句
查看>>
[置顶] 某大型银行深化系统技术方案之九:核心层之流程数据管理
查看>>
MVC把随机产生的字符串转换为图片
查看>>
《OOC》笔记(0)——为何要看这本书
查看>>