美文网首页Android知识Android开发Android开发经验谈
笔记20171127-Android仿滴滴呼叫车时转圈圈的Vie

笔记20171127-Android仿滴滴呼叫车时转圈圈的Vie

作者: hello我的world | 来源:发表于2017-11-27 20:29 被阅读0次

    需求:

    类似滴滴打车,呼叫车,但是司机还未接单,等待计时的自定义View

    要达到的效果:

    转圈圈.jpeg
    hongyang大神的自定义View教程中的思路实现的

    相关代码:

    1.attrs.xml(这个文件里放的是自定义view的属性)
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <attr name="firstColor" format="color"/>
        <attr name="secondColor" format="color"/>
        <attr name="circleWidth" format="dimension"/>
        <attr name="speed" format="integer"/>
        <attr name="textSize" format="dimension"/>
        <attr name="textColorFirst" format="color"/>
        <attr name="textColorSecond" format="color"/>
    
        <declare-styleable name="circle">
            <attr name="firstColor"/>
            <attr name="secondColor"/>
            <attr name="circleWidth"/>
            <attr name="speed"/>
            <attr name="textSize"/>
            <attr name="textColorFirst"/>
            <attr name="textColorSecond"/>
        </declare-styleable>
    </resources>
    
    2.自定义的View 我给它起名叫CircleView(反正就是个圆)
    package weekimwee.cn.circleviewdemo;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.RectF;
    import android.support.annotation.Nullable;
    import android.util.AttributeSet;
    import android.util.TypedValue;
    import android.view.View;
    
    import java.math.BigDecimal;
    import java.text.SimpleDateFormat;
    
    /**
     * Created by Wee Kim Wee on 2017/10/23.
     */
    
    public class CircleView extends View {
        private int firstColor;
        private int secondColor;
        private int circleWidth;
        private int speed;
        private int textSize;
        private float progress;
        private boolean isNext;
        private String bigCircleText;
        private int bigCircleTextColor;
        private int time;
        private DrawThread drawThread;
        private SimpleDateFormat formatter = new SimpleDateFormat("mm分ss秒");
        private final String LOADING ="已等待";
        private Paint paint;
        public CircleView(Context context) {
            this(context,null);
        }
    
        public CircleView(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs,0);
        }
    
        public CircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.circle, defStyleAttr, 0);
            int n = a.getIndexCount();
            for(int i = 0; i < n; i++){
                int attr = a.getIndex(i);
                switch (attr){
                    case R.styleable.circle_firstColor:
                        firstColor = a.getColor(attr, Color.GRAY);
                        break;
                    case R.styleable.circle_secondColor:
                        secondColor = a.getColor(attr,Color.GRAY);
                        break;
                    case R.styleable.circle_circleWidth:
                        circleWidth = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
                                TypedValue.COMPLEX_UNIT_PX, 20, getResources().getDisplayMetrics()));
                        break;
                    case R.styleable.circle_speed:
                        speed=a.getInt(attr, 20);
                        break;
                    case R.styleable.circle_textSize:
                        textSize =a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
                                TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
                        break;
                    case R.styleable.circle_textColorFirst:
                        bigCircleTextColor = a.getColor(attr,Color.BLACK);
                        break;
                }
            }
            a.recycle();
            bigCircleText = "00分00秒";
    
            paint = new Paint();
            drawThread = new DrawThread();
            drawThread.start();
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            //大圆
            int centre = getWidth() / 2; // 获取圆心的x坐标
            int radius = (centre - circleWidth / 2)-25;// 半径
            paint.setStrokeWidth(circleWidth); // 设置圆环的宽度
            paint.setAntiAlias(true); // 消除锯齿
            paint.setStyle(Paint.Style.STROKE); // 设置空心
            RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius); // 用于定义的圆弧的形状和大小的界限
    
            //跟着跑的小圆
            float h = (float) (2*( Math.PI / 360) * progress);
            float x = (float) ( radius+25+Math.sin(h) * radius);
            float y = (float) (radius+25-Math.cos(h) * radius);
            //在180度位置上的圆
            //float hc = (float) (2*( Math.PI / 360) * 180);
            //float xc = (float) ( radius+25+Math.sin(hc) * radius);
            //float yc = (float) (radius+25-Math.cos(hc) * radius);
    
            //大圆边框绘制颜色
            if (!isNext) {// 第一颜色的圈完整,第二颜色跑
                paint.setColor(firstColor); // 设置圆环的颜色
                canvas.drawCircle(centre, centre, radius, paint); // 画出圆环
                paint.setColor(secondColor); // 设置圆环的颜色
                canvas.drawArc(oval, -90, progress, false, paint); // 根据进度画圆弧
    
                paint.setColor(secondColor);
                paint.setStyle(Paint.Style.FILL);
                canvas.drawCircle(x,y,10,paint);
                //paint.setColor(firstColor);
                //paint.setStyle(Paint.Style.FILL);
                //canvas.drawCircle(xc,yc,10,paint);
            } else {
                paint.setColor(secondColor); // 设置圆环的颜色
                canvas.drawCircle(centre, centre, radius, paint); // 画出圆环
                paint.setColor(firstColor); // 设置圆环的颜色
                canvas.drawArc(oval, -90, progress, false, paint); // 根据进度画圆弧
    
                paint.setColor(firstColor);
                paint.setStyle(Paint.Style.FILL);
                canvas.drawCircle(x,y,8,paint);
                //paint.setColor(secondColor);
                //paint.setStyle(Paint.Style.FILL);
                //canvas.drawCircle(xc,yc,10,paint);
            }
    
    
            paint.setTextSize(textSize);
            //已等待
            float loadingTextWidth = paint.measureText(LOADING);
            paint.setColor(Color.GRAY);
            paint.setStrokeWidth(1);
            canvas.drawText(LOADING,centre-loadingTextWidth/2,centre-textSize,paint);
            //几分几秒
            float bigCircleTextWidth = paint.measureText(bigCircleText);
            paint.setColor(bigCircleTextColor);
            canvas.drawText(bigCircleText, centre - bigCircleTextWidth / 2, centre + textSize , paint);
        }
    
        public void stop(){
            drawThread.close();
        }
    
        class DrawThread extends Thread {
    
            private boolean isRun = true;
    
            @Override
            public void run() {
                while (isRun) {
                    BigDecimal b1 = new BigDecimal(Float.toString(progress));
                    BigDecimal b2 = new BigDecimal(Float.toString(0.3f));
                    progress = b1.add(b2).floatValue();
                    if (progress == 360) {
                        progress = 0;
                        if (!isNext)
                            isNext = true;
                        else
                            isNext = false;
                    }
                    time = time+speed;
                    postInvalidate();
                    bigCircleText = formatter.format(time);
                    try {
                        Thread.sleep(speed);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
    
            public void close() {
                isRun = false;
            }
        }
    }
    
    3.activity_main.xml布局中使用上述View
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="weekimwee.cn.circleviewdemo.MainActivity">
    
        <TextView
            android:layout_alignParentTop="true"
            android:padding="20dp"
            android:id="@+id/helloworld"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!" />
    
        <weekimwee.cn.circleviewdemo.CircleView
            android:id="@+id/view"
            android:layout_centerInParent="true"
            android:layout_width="200dp"
            android:layout_height="200dp"
            app:firstColor="#ff4500"
            app:secondColor="#d3d3d3"
            app:circleWidth="2dp"
            app:speed="25"
            app:textSize="20sp"
            app:textColorFirst ="#ff4500"
            app:textColorSecond="#d3d3d3"
            />
    </RelativeLayout>
    
    4.MainActivity.java中使用View开始计时
    package weekimwee.cn.circleviewdemo
    
    import android.support.v7.app.AppCompatActivity
    import android.os.Bundle
    import kotlinx.android.synthetic.main.activity_main.*
    
    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            helloworld.setOnClickListener {
                view.stop()
            }
        }
    }
    

    实现思路:

    必要条件:
    • 空心大圆,两种颜色
    • 实心的小圆,也是两种颜色
    • 计时线程,30秒小圆要绕着大圆走一圈并更换颜色,大圆中间的text显示计时
    具体代码中的实现:
    • 在构造方法中把属性获取下来
    • 计时的线程开始启动,线程中的逻辑:
      360度的大圆,每25毫秒转0.3f度,转1200次刚好转完,刚好30秒(因为我没有用动画,直接是在View中重绘的,如果是3度这样的,会显的一卡一卡的不平滑)
    • onDraw方法:
      (1)先画大圆(大圆位置是固定的)
      (2)计算小圆的位置(每次重绘角度已经变了,所以要重新计算小圆的位置)
      (3)大圆边框绘制颜色,以及绘制小圆(小圆颜色与大圆边框一致)
      (4)绘制大圆中间的字
    • stop方法
      这个方法供外部调用停止计时线程,例如呼叫到车了,这个页面finish了之类的

    以上是这个呼叫车计时等待View的笔记,demo在这里在这里

    相关文章

      网友评论

        本文标题:笔记20171127-Android仿滴滴呼叫车时转圈圈的Vie

        本文链接:https://www.haomeiwen.com/subject/rkzdbxtx.html