Android自定义View之仿金山词霸加载效果

今天,闲来无事,看到金山词霸的加载时的LoadingView甚是不错,于是就小模仿了一下。先看效果:这里写图片描述
下面切入正题,先说下思路:
1.确定中心点的座标
2.根据正余弦函数,确定8个小圆的圆心座标
3.定义有8个颜色的数组,画圆的时候依次用不用颜色的画笔

注意:画圆之前要把之前画的圆的颜色置为灰色
下面自定义View的代码:
CircleLoading.java

public class CircleLoading extends View{

    private Paint mPaint;   //画笔
    private Context mContext;   
    private float mRadius;  //小圆半径
    private int radius; //大圆半径

    private float centerX;
    private float centerY;
    private int currentPosition = 6;    //动画起始位置(即动画从最靠上的那个圆开始)
    private boolean isStart = false;
    //定义8种颜色
    private int colors[] = {Color.YELLOW,Color.GREEN,Color.CYAN,
            Color.BLUE,Color.parseColor("#9809F7"),
            Color.parseColor("#03F0F7"),Color.RED,
            Color.parseColor("#F85004")};

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

    public CircleLoading(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public CircleLoading(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        mContext = context;
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Style.FILL);
        mPaint.setColor(Color.GRAY);
        radius = dip2px(30);
        mRadius = dip2px(5);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);

        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);

        //处理 wrap_content问题
        int defaultDimension = dip2px(100);
        if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(defaultDimension, defaultDimension);
        } else if (widthSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(defaultDimension, heightSpecSize);
        } else if (heightSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(widthSpecSize, defaultDimension);
        }

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        centerX = w/2;
        centerY = h/2;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setColor(Color.GRAY);
        for(int i = 0;i<8;i++){
            float circleX = (float) (centerX + radius * Math.cos(Math.PI * i / 4));
            float circleY = (float) (centerY + radius * Math.sin(Math.PI *i/4));
            canvas.drawCircle(circleX, circleY, mRadius, mPaint);
        }
        if(isStart){
            mPaint.setColor(colors[currentPosition]);
            float cx = (float) (centerX + radius * Math.cos(Math.PI * currentPosition / 4));
            float cy = (float) (centerY + radius * Math.sin(Math.PI * currentPosition/4));
            canvas.drawCircle(cx, cy, mRadius, mPaint);
        }
    }

    //开始动画
    public void startAnimator() {
        isStart = true;
        new Thread(new Runnable() {

            @Override
            public void run() {
                while(true){
                    Log.i("Main", "currentPosition:"+currentPosition);
                    postInvalidate();
                    currentPosition++;
                    if(currentPosition == 8){
                        currentPosition = 0;
                    }
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }
        }).start();
    }

    //停止动画
    public void stopAnimator() {
        isStart = false;
        postInvalidate();
    }

    /**
     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
     */
    public int dip2px(float dpValue) {
        final float scale = mContext.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

}

接下来是xml文件:
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <com.sky.view.CircleLoading 
        android:id="@+id/circle_load"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"/>


</RelativeLayout>

最后是我们的MainActivity:
MainActivity.java

public class MainActivity extends Activity{

    private CircleLoading circleLoading;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        circleLoading = (CircleLoading) findViewById(R.id.circle_load);
        circleLoading.startAnimator();
    }

}

有关自定义View的知识还是非常多的,这些还都是一些皮毛,有机会深入研究,继续更新。。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章