1. 程式人生 > >android畫多種顏色的圓環帶動畫效果

android畫多種顏色的圓環帶動畫效果

首先在values中的attrs中建立自定義控制元件的屬性

<declare-styleable name="MyView">
        <attr name="my_view_color" format="color"></attr>
        <attr name="my_view_cirle" format="dimension"></attr>
    </declare-styleable>

自定義控制元件繼承view
package com.bruce.testgitdemo.test;

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.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;

import com.ajie.bootstartdemo.R;

import java.util.ArrayList;


/**
 * 自定義圓環
 */
public class MyView extends View {
    private int color = Color.parseColor("#e8e8e8");   //畫圓的顏色  預設紅色
    private float cirle = 200;   //半徑範圍大小 預設200
    private Paint mPaint;
    private int widthSize,heightSize;    //螢幕寬高
    private int[] colors;   //顏色陣列
    private ArrayList<Float> percents;   //百分比陣列
    private float percent ;   //總共百分比
    private Boolean flag = true;    // 只執行一次
    private float[] step;   //儲存每個圓弧的弧度
    private float[] percentnum ;   //儲存每個圓弧的起始弧度
    private boolean isAnim = false;    //是否使用動畫 預設不使用


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

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

    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyView, defStyleAttr, 0);
        int n = a.getIndexCount();
        for (int i = 0;i<n;i++){
            int attr = a.getIndex(i);
            switch (attr){
                case R.styleable.MyView_my_view_color:
                    color = a.getColor(R.styleable.MyView_my_view_color,0);
                    break;
                case R.styleable.MyView_my_view_cirle:
                    cirle= a.getDimension(R.styleable.MyView_my_view_cirle,0f);
                    break;
                default:
                    break;
            }
        }
        a.recycle();
        mPaint = new Paint();
        mPaint.setAntiAlias(true);  //消除鋸齒
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        widthSize = MeasureSpec.getSize(widthMeasureSpec);
        heightSize = MeasureSpec.getSize(heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //外圈圓
        mPaint.setColor(color);   //預設顏色(底部最初圓環顏色)
        canvas.drawCircle(widthSize/2,heightSize/2,cirle,mPaint);
        RectF oval = new RectF(widthSize/2-cirle, heightSize/2-cirle, widthSize/2+cirle, heightSize/2+cirle);
        if (isAnim){
            addCircleAnim(canvas,oval);
        }else {
            circleNoAnim(canvas,oval);
        }

        //內圈圓
        mPaint.setColor(Color.BLACK);
        canvas.drawCircle(widthSize/2,heightSize/2,cirle-cirle/4,mPaint);



    }

    public int[] getColors() {
        return colors;
    }

    public void setColors(int[] colors) {
        this.colors = colors;
    }

    public ArrayList<Float> getPercents() {
        return percents;
    }

    public void setPercents(ArrayList<Float> percents) {
        this.percents = percents;
    }

    /**
     * 是否使用動畫
     * @param isHaveAnim
     */
    public void setIsHaveAnim(Boolean isHaveAnim){
        if (isHaveAnim){
            this.getViewTreeObserver().addOnPreDrawListener(
                    new ViewTreeObserver.OnPreDrawListener() {
                        public boolean onPreDraw() {
                            new Thread(new CircleThread()).start();
                            getViewTreeObserver().removeOnPreDrawListener(this);
                            return false;
                        }
                    });
        }
        this.isAnim = isHaveAnim;
    }

    /**
     * 檢查百分比是否超過100%
     */
    private float checkPercent(ArrayList<Float> percents){
        if (percents == null){
            Log.d("tag","總百分比為空");
            return 0;
        }
        for (int i = 0;i<percents.size();i++){
            percent += percents.get(i);
        }
        Log.d("tag","percent-----"+percent);
       return percent;
    }

    private class CircleThread implements Runnable {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    Thread.sleep(20);
                    /**
                     * 在新的執行緒中,傳送訊息給View,更新介面資料
                     * 通過m++實現加速度方式的不斷加速繪製弧形
                     * i代表要繪製扇形的角度大小,0-360
                     */
                    flag = false;
                    m +=2;
                    Message msg = new Message();
                    msg.what = 1;
                    if (i < 360) {
                        i = m;
                    } else {
                        i = 360;
                        return;
                    }
                    msg.obj = i;
                    circleHandler.sendMessage(msg);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

    }

    private Handler circleHandler = new Handler() {

        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 1) {
                int temp = (Integer) msg.obj;
                setTemp(temp);
                invalidate();
            }
        }
    };

    private int temp ,i,m ;
    private void setTemp(int temp){
        this.temp = temp;
    }

    /**
     * 帶動畫的畫圓
     * @param canvas
     * @param oval
     */
    private void addCircleAnim(Canvas canvas,RectF oval){
        float nextPercent = 0;
        //初始化賦值,flag = true 只執行一次(有動畫效果)
        if (flag){
            try {
                if (checkPercent(percents)>1) {
                    throw new Exception("百分比不能大於1");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            step  = new float[percents.size()];
            percentnum = new float[percents.size()];
            for (int i = 0;i<percents.size();i++){
                step[i] = 360*percents.get(i);
                percentnum[i] = nextPercent;
                nextPercent += 360*percents.get(i);
            }
        }else {
            for (int i = 0;i<percents.size();i++){
                if (temp<=step[i]){
                    mPaint.setColor(colors[i]);
                    canvas.drawArc(oval,percentnum[i],temp,true,mPaint);
                }else {
                    mPaint.setColor(colors[i]);
                    canvas.drawArc(oval,percentnum[i],step[i],true,mPaint);
                }
            }
        }
    }

    /**
     * 不帶動畫的畫圓
     * @param canvas
     * @param oval
     */
    private void circleNoAnim(Canvas canvas,RectF oval){
        try {
            if (checkPercent(percents)>1) {
                throw new Exception("百分比不能大於1");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //迴圈畫圓環
        float nowPercent = 0;
        float nextPercent = 0;
        //繪製圓環  (無動畫效果)
        for (int i = 0;i<percents.size();i++){
            mPaint.setColor(colors[i]);
            nextPercent += 360*percents.get(i);
            canvas.drawArc(oval,nowPercent,360*percents.get(i),true,mPaint);     //   360*percents.get(i)此引數寫法對畫圓環很重要
            nowPercent = nextPercent;
        }
    }
}

控制元件的使用就很簡單了
 MyView myView = (MyView) findViewById(R.id.myview);
        myView.setIsHaveAnim(false);
        myView.setColors(colors);
        myView.setPercents(getPercentValue());
 public ArrayList<Float> getPercentValue() {
        ArrayList<Float> list = new ArrayList<>();
//        for (int i = 0;i<5;i++){
//            list.add(0.15f);
//        }
        list.add(0.1f);
        list.add(0.2f);
        list.add(0.3f);
        list.add(0.1f);
        list.add(0.1f);

        return list;
    }

demo下載地址

相關推薦

android多種顏色動畫效果

首先在values中的attrs中建立自定義控制元件的屬性 <declare-styleable name="MyView"> <attr name="my_view_color" format="color"></attr&

Android buttom textview 顏色平滑過渡的動畫效果

1. TransitionDrawable。例如,在資料夾中繪製一個xml檔案,你可以這樣寫: <?xml version="1.0" encoding="UTF-8"?> <transition xmlns:android=" CodeGo.net

css3閃爍動畫

col key pos scale near meta osi 閃爍 ans <!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <ti

Android高效率實現彈出動畫效果的對話方塊,仿照微信對話方塊效果

看到很多app頁面裡都有彈出對話方塊效果,今天使用PopupWindow實現帶動畫效果的對話方塊,先看效果圖: 效果圖: 分析實現思路: 彈出對話方塊帶有動畫效果 對話方塊從底部向上彈出 彈出對話方塊時,窗體背景呈現灰色(半透明) 對話方塊四周具

Android 自定義數字

最近專案中寫了一個數字圓環的樣式,只能通過自定義View完成,對於自定義View我還比較薄弱,查了一些資料,我們參考下: 看下效果圖: 自定義View:DoughnutView.java /** * on 15/12/16. * 自定義數字圓環 * 參考:

Android Dialog使用、自定義動畫的Dialog使用

效果圖 普通Dialog private void showNormalDialog() { final AlertDialog.Builder builder = ne

Android 自定義View (三) 交替 等待效果

轉載請標明出處:http://blog.csdn.net/lmj623565791/article/details/24500107一個朋友今天有這麼個需求(下圖),我覺得那自定義View來做還是很適合的,就做了下,順便和大家分享下,對於自定義View多練沒壞處麼。如果你看了

Android實現GridView的item長按拖動刪除完美實現(動畫效果

領導這幾天讓做一個專案,就是可以實現像支付寶首頁一樣的可以長按拖動,刪除的介面,以前沒做過,領導讓我做的時候覺得簡直是老虎吃天,無從下手啊,可是領導的任務還是要實現的,沒辦法,就自己網上找咯,但是網上的demo五花八門無法滿足我的需求,而且bug還很多,所以最後

CSS3——制作動畫效果的小圖片

技術分享 margin OS div IV hidden pan ali body 還挺有意思的,但是我沒有截取動畫的軟件,就沒辦法展示我的小動圖了,暫時放一個靜態的吧: main.html <!DOCTYPE html> <html lang="en

收藏一個動畫效果的ScrollViewer以及ScrollBar的模板

tps tro change bin nta idc aries htm 引用 原文:收藏一個帶動畫效果的ScrollViewer以及ScrollBar的模板 這裏介紹一個帶動畫效果的ScrollViewer和ScrollBar,總共分為兩個資源字典,直接拿來引用即

android仿支付寶螞蟻森林載入動畫效果

一圖勝千言 偷過別人能量的小夥伴都熟悉這個載入效果,下面就講解一下實現過程。 1,自定義view 2,這裡要用到螞蟻森林的圖示,如圖 通過canvas.drawBitmap()畫出圖片。 3,通過PorterDuff.Mode.SRC_IN,給圖片填充想要的

滑鼠滑過圖片使圖片尺寸大小改變(動畫效果

下面實現了滑鼠放到圖片上去,圖片慢慢變大,滑鼠移走,圖片慢慢恢復。 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>滑鼠

D3.js實現動畫效果的柱狀圖

<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <meta name="viewport" content

jQuery 多種高階頁面屬性和動畫效果

完成目標:利用jQuery語法完成多種頁面屬性和動畫效果 1.文字淡入淡出,顯示及隱藏。 程式碼: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"

Android ViewPager多頁面滑動切換以及動畫效果

一、首先,我們來看一下效果圖,這是新浪微博的Tab滑動效果。我們可以手勢滑動,也可以點選上面的頭標進行切換。與此同方式, 白色橫條會移動到相應的頁卡頭標下。這是一個動畫效果,白條是緩慢滑動過去的。好了,接下來我們就來實現它。 二、在開始前,我們先要認識一個控制元件,ViewPager。它是google

Android中實現雙擊點贊動畫效果

iv_easy_like.getBackground().setAlpha(0); rlLike.setOnTouchListener(new OnDoubleClickListener(new OnDoubleClickListener.DoubleClickCallb

Android中使用SVG實現炫酷動畫效果

前言 SVG,即Scalable Vector Graphics 可伸縮向量圖形。這種影象格式在前端中已經使用的非常廣泛,而在移動端的開發中,遇到一些複雜的自定義控制元件或者動畫效果,我們就可以考慮使用SVG。 一.Vector Drawable

android 使用Path實現搜尋動態載入動畫效果

今天實現一個搜尋動態載入資料的動畫效果,還是先看效果吧,用文字描述乾巴巴的,看圖說話什麼都明白了, 實現這個就是使用Path中的getSegment()不斷的去改變它擷取片段的start和stop,再結合動畫,今天就分步驟實現它,看完以後你也會覺的不是很難,只是沒想到這麼

動畫效果的圓形進度條顯示定時器倒計時

在實際專案開發中我們經常要使用進度條監聽下載進度,使用的大多是在UIView中的- (void)drawRect:(CGRect)rect方法中描繪圓形路徑,然後通過傳過來的進度值計算圓形路徑百分比達到監聽效果,這種監聽進度方法適合檔案下載,但是我們開發中有時會

startActivity去除系統自動畫效果

方法一:在startActivity()或者finish()後緊跟呼叫:((Activity) mContext).overridePendingTransition(0, 0); 方法二:在一些特殊情況下方法一是不能實現的.比如給Intent設定了屬性:intent.a