博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
安卓运动圆环自定义View
阅读量:6910 次
发布时间:2019-06-27

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

运动圆环自定义View.gif

记得这个东西原来有个同事问过我,当时正在自学自定义View和属性动画这一块,对这个功能也没有写过,所以就google了一下,发了几个类似效果的github项目给朋友,今天礼拜天难得有心情写写代码,所以想想实现一下这个自定义View的效果。

首先,我们从这个gif的效果图中就可以得知这个自定义View我们需要哪些自定义属性,内部圆环的颜色、外部圆环的颜色、圆环的宽度、字体的大小、颜色,话不多说,直接撸码。

/** * Created by Administrator on 2018/5/13. * 运动圆环自定义View */public class MotionCrcle extends View {    /**     * 外部圆环颜色     */    private int mOuterColor = Color.BLUE;    /**     * 里面圆环颜色     */    private int mInnerColor = Color.RED;    /**     * 跑步数的文字大小     */    private int mTextSize = 30;    /**     * 跑步文字的颜色     */    private int mTextColor = Color.BLACK;    /**     * 圆环的宽度     */    private int mCrcleWidth = 45;    private Paint mOuterPaint, mInnerPaint, mTextPaint;    private float mMaxSteps = 0;    private int mCurrentSteps = 0;    public MotionCrcle(Context context) {        this(context, null);    }    public MotionCrcle(Context context, @Nullable AttributeSet attrs) {        this(context, attrs, 0);    }    public MotionCrcle(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MotionCrcle);        mOuterColor = array.getColor(R.styleable.MotionCrcle_outerCrcleColor, mOuterColor);        mInnerColor = array.getColor(R.styleable.MotionCrcle_innerCrcleColor, mInnerColor);        mCrcleWidth = array.getInt(R.styleable.MotionCrcle_crcleWidth, mCrcleWidth);        mTextColor = array.getColor(R.styleable.MotionCrcle_crcleTextColor, mTextColor);        mTextSize = array.getInt(R.styleable.MotionCrcle_crcleTextSize, mTextSize);        initPaint();        array.recycle();    }    public synchronized void setmMaxSteps(float mMaxSteps) {        this.mMaxSteps = mMaxSteps;    }    public synchronized void setmCurrentSteps(int mCurrentSteps) {        this.mCurrentSteps = mCurrentSteps;        invalidate();    }    private void initPaint() {        mOuterPaint = new Paint();        mOuterPaint.setAntiAlias(true);        mOuterPaint.setStrokeWidth(mCrcleWidth);        mOuterPaint.setStrokeCap(Paint.Cap.ROUND);        mOuterPaint.setStyle(Paint.Style.STROKE);        mOuterPaint.setColor(mOuterColor);        mInnerPaint = new Paint();        mInnerPaint.setAntiAlias(true);        mInnerPaint.setStrokeWidth(mCrcleWidth);        mInnerPaint.setStrokeCap(Paint.Cap.ROUND);        mInnerPaint.setStyle(Paint.Style.STROKE);        mInnerPaint.setColor(mInnerColor);        mTextPaint = new Paint();        mTextPaint.setAntiAlias(true);        mTextPaint.setTextSize(mTextSize);        mTextPaint.setColor(mTextColor);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int width = MeasureSpec.getSize(widthMeasureSpec);        int height = MeasureSpec.getSize(heightMeasureSpec);        if(width != height){            /**             * 因为运动圆环是一个正方形,所以我们要设置一个最小值作为View的长度             */            int min = Math.min(width, height);            widthMeasureSpec = MeasureSpec.makeMeasureSpec(min, MeasureSpec.EXACTLY);            heightMeasureSpec = MeasureSpec.makeMeasureSpec(min, MeasureSpec.EXACTLY);            setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);        }    }    @Override    protected void onDraw(Canvas canvas) {       //因为圆环本身是具有宽度的,所以我们这里左边的顶点要往右mCrcleWidth个距离,右边底部的点要往左,所以要减去mCrcleWidth        RectF recf = new RectF(mCrcleWidth, mCrcleWidth,                getWidth() - mCrcleWidth, getHeight() - mCrcleWidth);      //135是外部圆环的初始角度,270是所画的总角度数        canvas.drawArc(recf, 135, 270, false, mOuterPaint);        if(mCurrentSteps == 0){            return;        }      //算出当前步数是最大步数的比值        float angle = mCurrentSteps / mMaxSteps;        canvas.drawArc(recf, 135, 270 * angle, false, mInnerPaint);        String stepText = mCurrentSteps+"";        Rect bounds = new Rect();      //算出步数文字的baseLine,也就是基准线        mTextPaint.getTextBounds(stepText, 0, stepText.length(), bounds);        int x = getWidth() / 2 - bounds.width() / 2;        Paint.FontMetricsInt metrices = mTextPaint.getFontMetricsInt();        int diffY = (metrices.bottom - metrices.top) / 2 - metrices.bottom;        int baseLine = getHeight() / 2 + diffY;        canvas.drawText(stepText, x, baseLine, mTextPaint);    }}
文字基准线说明图.jpg

文字的绘制和画圆画弧不一样,其实仔细想想也明白,如果绘制按照左上角开始的话是不现实的,因为文字不可能是简单的顶部或底部对其,应该是重心对齐,简单说就是基准线,所以代码中基准线的算法是bottom-top再除以2减去bottom,以基准线开始绘制,top就是负数,bottom是正数。

public class MainActivity extends AppCompatActivity {    private Button mBtn;    private baohuo.rzj.com.myapplication.Views.MotionCrcle mCrcle;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mBtn = (Button) findViewById(R.id.btn);        mCrcle = (MotionCrcle) findViewById(R.id.motion_crcle);        mCrcle.setmMaxSteps(10000);        final ValueAnimator animator = ObjectAnimator.ofFloat(0,4500);        animator.setDuration(2000);        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator valueAnimator) {                float value = (float) valueAnimator.getAnimatedValue();                mCrcle.setmCurrentSteps((int) value);            }        });        mBtn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                animator.start();            }        });    }}

以上是Activity的代码,非常简单,不做解释,这个值得一提的是,我在写的时候内部圆环一直没有绘制,文字在不断变化,通过debug发现,我把步数最大值和当前步数设置为int,一个小的int除以大的int的到的只有0,所以我把最大步数改为float,这样得出的值就有小数位,最后附上xml代码。

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

你可能感兴趣的文章
maven部分插件配置demo
查看>>
Grin交易原理详解
查看>>
大数据体系【概念认知】系列-2:存储以及副本策略
查看>>
我的友情链接
查看>>
linux企业常用服务---haproxy+nginx搭建web高可用集群
查看>>
win7 断开 共享连接的操作方法
查看>>
CTSSD服务无法正常启动:Failure 4 in trying to open SV key PROCL-4/PROCL-5 clsctss_r_av2
查看>>
再议OPEN CURSOR与BULK COLLECT
查看>>
我的友情链接
查看>>
jquery attr与prop
查看>>
casatwy组件化方案
查看>>
Linux中ls对文件进行按大小排序和按时间排序
查看>>
Unix/Linux下安装NPM
查看>>
Apache与Tomcat区别联系
查看>>
洪水***源码
查看>>
用shell编写批量打包日志脚本
查看>>
nginx访问白屏
查看>>
Pentaho6.1中D3可视化库的集成及数据联动的实现
查看>>
部署LyncServer2013之七 启动服务和登陆LyncServer控制面板
查看>>
Android开发者:你真的会用AsyncTask吗?
查看>>