ValueAnimator實現酷炫的動畫

bnxrrta85 7年前發布 | 11K 次閱讀 游戲開發 Android開發 移動開發

這篇文章主要實現用ValueAnimator實現自定義控件的一個動畫效果

先大概說一下ValueAnimator的使用ValueAnimator valueAnimator=ValueAnimator.ofFloat(0, 100f);這樣就生成了一個ValueAnimator類,ValueAnimator.ofFloat()也可以是ValueAnimator.ofInt();然后就是setDuration()設置動畫持續時間;setInterpolator(new AccelerateDecelerateInterpolator())設置攔截器(api給出了幾種效果,使用很方便的);再添加一個更新的監聽就可以開始搞事了addUpdateListener();接下來給大家看看我之前在項目中用過的一個比較復雜的動畫,代碼太長,就直接粘代碼吧,很簡單的,希望有大神能對代碼做一下改進!

public class RatingViw extends View {
    //旋轉動畫,百分比動畫,評估中的動畫,評分動畫,結果動畫
    private ValueAnimator rotateAnimation, perAnimation, detailAnimation, ratingAnimation, resultAnimation;
    private float rotateAngle;
    private List<RatingBar> RatingBars;
    private int x, y;    //圓心的坐標
    private static final int STROKE_OFFSET = 5;
   //扇形的間隙    private int currStarNum = -1;   //當前星的數量
    private int lastStatNum = -1;   //上一顆星的數量
    private int currPer;    //當前的百分數
    private int radius;     //半徑
    private int ditalAlpha, resultAlpha;  //
    private int maxRate = 18;
    private boolean isShow;       //顯示RatingView
    private boolean isShowDetail = true;  //顯示診斷過程
    //股票名稱,百分比,百分號,結果,評估中
    private Paint paint, perPaint, mPaint, resulPaint, sPaint;
    private Rect rect, rect1, textRect, ditalRect, resultRect;
    private String name = "", result = "80分";
    private float eventX;
    private float eventY;
    private boolean isEmpty = false;
    private String assess="評估中";        //評估中
    private boolean drawResult;
    private boolean isAnimationYEnd=false;
    public RatingViw(Context context) {
        this(context, null);
    }
    public RatingViw(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public RatingViw(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        RatingBars = new ArrayList<>();
        RatingBars.add(0, new RatingBar(0));
        RatingBars.add(0, new RatingBar(0));
        RatingBars.add(0, new RatingBar(0));
        initAnimation();
        initTextAnimation();
    }
   public void setName(String name) {
        this.name = name;
    }
    public String getName(){
        return name;
    }
    public void setResult(String result){
        this.result=result+"分";
    }
    private void initTextAnimation() {
        detailAnimation = ValueAnimator.ofInt(0, 255);
        detailAnimation.setDuration(500);
        detailAnimation.setInterpolator(new LinearInterpolator());
        detailAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                ditalAlpha = (int) valueAnimator.getAnimatedValue();
            }
        });
        resultAnimation = ValueAnimator.ofInt(0, 255);
        resultAnimation.setDuration(500);
        resultAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                resultAlpha = (int) valueAnimator.getAnimatedValue();
            }
        });
    }
    private void initAnimation() {
        rotateAnimation = ValueAnimator.ofFloat(0, 360 * 5);
        rotateAnimation.setDuration(3000);
        rotateAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
        rotateAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                rotateAngle = (float) valueAnimator.getAnimatedValue();
                long currentPlayTime = valueAnimator.getCurrentPlayTime();
                invalidate();
                if (currentPlayTime > 2500) {
                    if (isShow) {
                        ratingAnimation.start();
                    }
                }
            }
        });
        //中間的文字
        perAnimation = ValueAnimator.ofInt(0, 180);
        perAnimation.setDuration(3000);
        perAnimation.setInterpolator(new LinearInterpolator());
        perAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                currPer = (int) valueAnimator.getAnimatedValue();
                if (currPer == 50) {
                    detailAnimation.start();
                }
                if (currPer == 100) {
                    detailAnimation.start();
                }
            }
        });
        ratingAnimation = ValueAnimator.ofInt(0, maxRate);  //18顆星
        ratingAnimation.setDuration(1000);
        ratingAnimation.setInterpolator(new LinearInterpolator());
        ratingAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                currStarNum = (int) valueAnimator.getAnimatedValue();
                //關閉百分比和詳情
                isShowDetail = false;
                if (currStarNum == 1) {
                    resultAnimation.start();
                    drawResult = true;
                }
                if (currStarNum != lastStatNum) {
                    invalidate();
                }
                lastStatNum = currStarNum;
            }
        });
        ratingAnimation.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
            }
            @Override
            public void onAnimationEnd(Animator animation) {
                if (!drawResult) {
                    resultAnimation.start();
                }
                if (translation!=null)
                translation.start();
            }
            @Override
            public void onAnimationCancel(Animator animation) {
            }
            @Override
            public void onAnimationRepeat(Animator animation) {
            }
        });
    }
    private int translationX;//評分向左移動
    private int textX,textY;
    private int width,height;
    private int reSetX;
    private ValueAnimator translation,textAnimationX,textAnimatorY,reSetAnimation;   //評分左移,文字左移,
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(getMeasuredWidth(),getMeasuredWidth()*16/45);
    }
    @Override
    protected void onSizeChanged(final int w, final int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        x = w / 2;
        y = h / 2;
        radius = y*11/16;
        translation= ValueAnimator.ofInt(x,radius+h/4);
        translation.setDuration(500);
        translation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                translationX= (int) animation.getAnimatedValue();
                x=translationX;
                initRatingBar();
                invalidate();
                if (translationX<300){
                    textAnimationX.start();
                    textAnimatorY.start();
                }
            }
        });
        width = getMeasuredWidth();
        height = getMeasuredHeight();
        int d = width - 2 * radius - dip2px(getContext(), 15);
        textAnimationX= ValueAnimator.ofInt(0,w*7/90,w*7/90-30,w*7/90,w*7/90-20,w*7/90,w*7/90-10,w*7/90);
        textAnimationX.setDuration(500);
        textAnimationX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                textX= (int) animation.getAnimatedValue();
                if (textX*5>225){
                    textRectPaint.setAlpha(255);
                    textPaint.setAlpha(255);
                } else {
                    textRectPaint.setAlpha(textX*5);
                    textPaint.setAlpha(textX*5);
                }
                initPath();
                invalidate();
            }
        });
        textAnimatorY= ValueAnimator.ofInt(0,h*3/16,h*3/16-30,h*3/16,h*3/16-20,h*3/16,h*3/16-10,h*3/16);
        textAnimatorY.setDuration(500);
        textAnimatorY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                textY= (int) animation.getAnimatedValue();
                initPath();
                invalidate();
            }
        });
        textAnimatorY.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                isAnimationYEnd=true;
                if (onAnimatorListener!=null){
                    onAnimatorListener.onEnd();
                }
            }
        });
        reSetAnimation= ValueAnimator.ofInt(radius+h/4,width/2);
        reSetAnimation.setDuration(500);
        reSetAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                x= (int) animation.getAnimatedValue();
                int alpha = width / 2 - x;
                if (alpha>=255){
                    alpha=255;
                }
                textRectPaint.setAlpha(alpha);
                textPaint.setAlpha(alpha);
                initPath();
                initRatingBar();
                invalidate();
            }
        });
        reSetAnimation.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
            }
            @Override
            public void onAnimationEnd(Animator animation) {
                Toast.makeText(getContext(), "完成", Toast.LENGTH_SHORT).show();
                show();
            }
            @Override
            public void onAnimationCancel(Animator animation) {
            }
            @Override
            public void onAnimationRepeat(Animator animation) {
            }
        });
        initText();
        initRatingBar();
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (isEmpty) {
            canvas.save();
            canvas.rotate(rotateAngle, x, y);
            for (RatingBar RatingBar : RatingBars) {
                RatingBar.drawUnRate(canvas);
            }
            canvas.restore();
            canvas.save();
            canvas.rotate(-rotateAngle, x, y);
            for (RatingBar RatingBar : RatingBars) {
                RatingBar.drawLine(canvas);
            }
            canvas.restore();
            paint.setTextSize(radius / 5);
            canvas.drawText(name, x - textRect.width() / 2, y - radius / 2, paint);
        }
        drawResult(canvas);
        drawTranslationX(canvas);
        drawText(canvas);
    }
    private String suggest="";   //增持
    private String ranking=""; //打敗96%的股票
    private String totalAccuracy="";  //89%
    private String changeAccuracy="";  //較昨日提升2%
    public void setSuggest(int suggest) {
        String[] array = getContext().getResources().getStringArray(R.array.diagnoseRating);
        if (suggest>=array.length)return;
        this.suggest=array[suggest];
    }
    public void setRanking(String ranking) {
        this.ranking = "打敗"+DigitalUtil.getNumberToNumver_towInt(ranking)+"%的股票";
    }
    public void setTotalAccuracy(String totalAccuracy) {
        this.totalAccuracy = DigitalUtil.getNumberToNumver_towInt(totalAccuracy)+"%";
    }
    public void setChangeAccuracy(String changeAccuracy) {
        if (TextUtils.isEmpty(changeAccuracy))return;
        if (!changeAccuracy.contains("-")){
            this.changeAccuracy = "較昨日提升"+DigitalUtil.getNumberToNumver_towInt(changeAccuracy)+"%";
        }else {
            String replace = changeAccuracy.replace("-", "");
            this.changeAccuracy = "較昨日降低"+DigitalUtil.getNumberToNumver_towInt(replace)+"%";
        }
    }
    /**     * 畫最后的文字     */
    private void drawText(Canvas canvas) {
        textPaint.setTextSize(textY*2/5);
        textPaint.getTextBounds("今日評級",0,"今日評級".length(),textRectF);
        canvas.drawText("今日評級",width*235/450-textRectF.width()/2,y-height/8,textPaint);
        textPaint.setTextSize(textY*2/3);
        textPaint.getTextBounds(suggest,0,suggest.length(),textRectF);
        canvas.drawText(suggest,width*235/450-textRectF.width()/2,y+textRectF.height()/2,textPaint);
        textPaint.setTextSize(textY*2/5);
        textPaint.getTextBounds(ranking,0,ranking.length(),textRectF);
        canvas.drawText(ranking,width*235/450-textRectF.width()/2,y+height*3/16,textPaint);
        textPaint.setTextSize(textY*2/5);
        textPaint.getTextBounds("診股準確率",0,"診股準確率".length(),textRectF);
        canvas.drawText("診股準確率",width*365/450-textRectF.width()/2,y-height/8,textPaint);
        textPaint.setTextSize(textY*2/3);
        textPaint.getTextBounds(totalAccuracy,0,totalAccuracy.length(),textRectF);
        canvas.drawText(totalAccuracy,width*365/450-textRectF.width()/2,y+textRectF.height()/2,textPaint);
        textPaint.setTextSize(textY*2/5);
        textPaint.getTextBounds(changeAccuracy,0,changeAccuracy.length(),textRectF);
        canvas.drawText(changeAccuracy,width*365/450-textRectF.width()/2,y+height*3/16,textPaint);
        textPaint.getTextBounds("查看詳情>",0,"查看詳情>".length(),textRectF);
        canvas.drawText("查看詳情>",width*440/450-textRectF.width(),height*15/16,textPaint);    
}
    private Rect textRectF;
    private Paint textRectPaint,textPaint;
    private Path pathA,pathB,pathC,pathD,pathAr,pathBr,pathCr,pathDr;
    private void initText(){
        textRectPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        textRectPaint.setColor(Color.WHITE);
        textRectPaint.setAlpha(0);
        textRectPaint.setStyle(Paint.Style.STROKE);
        textRectPaint.setStrokeWidth(dip2px(getContext(),1));
        textPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setColor(Color.WHITE);
        textPaint.setTextSize(30);
        textRectF=new Rect();
        textPaint.getTextBounds("今日評級",0,"今日評級".length(),textRectF);
        pathA=new Path();
        pathB=new Path();
        pathC=new Path();
        pathD=new Path();
        pathAr=new Path();
        pathBr=new Path();
        pathCr=new Path();
        pathDr=new Path();
        initPath();
    }
    private void initPath() {
        int line=width/45;
        pathA.reset();
        pathA.moveTo(width*225/450-textX,y-textY);
        pathA.lineTo(width*225/450-textX,y-line-textY);
        pathA.lineTo(width*225/450-textX+line,y-line-textY);
        pathB.reset();
        pathB.moveTo(width*225/450+textX+2*width/45,y-textY);
        pathB.lineTo(width*225/450+textX+2*line,y-line-textY);
        pathB.lineTo(width*225/450+textX+line,y-line-textY);
        pathC.reset();
        pathC.moveTo(width*225/450+textX+2*line,y+textY);
        pathC.lineTo(width*225/450+textX+2*line,y+line+textY);
        pathC.lineTo(width*225/450+textX+line,y+line+textY);
        pathD.reset();
        pathD.moveTo(width*225/450-textX,y+textY);
        pathD.lineTo(width*225/450-textX,y+line+textY);
        pathD.lineTo(width*225/450-textX+line,y+line+textY);
        pathAr.reset();
        pathAr.moveTo(width*355/450-textX,y-textY);
        pathAr.lineTo(width*355/450-textX,y-line-textY);
        pathAr.lineTo(width*355/450+line-textX,y-line-textY);
        pathBr.reset();
        pathBr.moveTo(width*355/450+2*line+textX,y-textY);
        pathBr.lineTo(width*355/450+2*line+textX,y-line-textY);
        pathBr.lineTo(width*355/450+line+textX,y-line-textY);
        pathCr.reset();
        pathCr.moveTo(width*355/450+2*line+textX,y+textY);
        pathCr.lineTo(width*355/450+2*line+textX,y+line+textY);
        pathCr.lineTo(width*355/450+line+textX,y+line+textY);
        pathDr.reset();
        pathDr.moveTo(width*355/450-textX,y+textY);
        pathDr.lineTo(width*355/450-textX,y+line+textY);
        pathDr.lineTo(width*355/450+line-textX,y+line+textY);
    }
    /**
     * 畫平移動畫
     * @param canvas 畫布
     */
    private void drawTranslationX(Canvas canvas) {
        if (translationX>0){
            canvas.drawPath(pathA,textRectPaint);
            canvas.drawPath(pathB,textRectPaint);
            canvas.drawPath(pathC,textRectPaint);
            canvas.drawPath(pathD,textRectPaint);
            canvas.drawPath(pathAr,textRectPaint);
            canvas.drawPath(pathBr,textRectPaint);
            canvas.drawPath(pathCr,textRectPaint);
            canvas.drawPath(pathDr,textRectPaint);
        }
    }
    private static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
    public static int getScreenWidth(Context context) {
        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        windowManager.getDefaultDisplay().getMetrics(outMetrics);
        return outMetrics.widthPixels;
    }
    private void drawResult(Canvas canvas) {
        if (isShow) {
            //畫沒有評分的所有的item
            canvas.save();
            canvas.rotate(rotateAngle, x, y);
            for (RatingBar RatingBar : RatingBars) {
                RatingBar.drawUnRate(canvas);
            }
            canvas.restore();
            canvas.save();
            canvas.rotate(-rotateAngle, x, y);
            for (RatingBar RatingBar : RatingBars) {
                RatingBar.drawLine(canvas);
            }
            canvas.restore();
            canvas.drawText(name, x - textRect.width() / 2, y - radius / 5, paint);
            if (isShowDetail){
                drawPer(canvas);
            }
            //畫星
            if (currStarNum != -1) {
                for (RatingBar RatingBar : RatingBars) {
                    for (int i = 0; i < RatingBar.getCurrRate(); i++) {
                        if (i <= currStarNum) {
       //每次都要講之前的畫出來,不然之前的就沒有了
                            RatingBar.drawRating(canvas, i);
                        }
                    }
                }
            }
            //畫結果
            if (resultAlpha > 0) {
                resulPaint.setAlpha(resultAlpha);
                canvas.drawText(result, x - resultRect.width() / 2, y + radius / 5*2, resulPaint);
            }
        }
    }
    private void drawPer(Canvas canvas) {
        canvas.drawText("%", x + 2 * rect.width() / 3, y + radius / 3, mPaint);
        if (0<currPer&&currPer <= 30) {
            canvas.drawText("" + currPer, x - rect.width() / 2, y + radius / 3, perPaint);
            if (ditalAlpha > 0) {
                canvas.drawText(assess, x - ditalRect.width() / 2, y + radius / 3 + ditalRect.height()*3/2, sPaint);
            }
        }
        if (currPer > 30 && currPer < 50) {
            canvas.drawText("" + 30, x - rect.width() / 2, y + radius / 3, perPaint);
            if (ditalAlpha > 0) {
                canvas.drawText(assess, x - ditalRect.width() / 2, y + radius / 3 + ditalRect.height()*3/2, sPaint);
            }
        }
        if (currPer >= 50 && currPer <= 80) {
            canvas.drawText("" + (currPer - 20), x - rect.width() / 2, y + radius / 3, perPaint);
            if (ditalAlpha > 0) {
                canvas.drawText(assess, x - ditalRect.width() / 2, y + radius / 3 + ditalRect.height()*3/2, sPaint);
            }
        }
        if (currPer > 80 && currPer < 100) {
            canvas.drawText("" + 60, x - rect.width() / 2, y + radius / 3, perPaint);
            if (ditalAlpha > 0) {
                canvas.drawText(assess, x - ditalRect.width() / 2, y + radius / 3 + ditalRect.height()*3/2, sPaint);
            }
        }
        if (currPer >= 100 && currPer <= 130) {
            canvas.drawText("" + (currPer - 40), x - rect.width() / 2, y + radius / 3, perPaint);
            if (ditalAlpha > 0) {
                canvas.drawText(assess, x - ditalRect.width() / 2, y + radius / 3 + ditalRect.height()*3/2, sPaint);
            }
        }
        if (currPer > 130 && currPer < 150) {
            canvas.drawText("" + 90, x - rect.width() / 2, y + radius / 3, perPaint);
            if (ditalAlpha > 0) {
                canvas.drawText(assess, x - ditalRect.width() / 2, y + radius / 3 + ditalRect.height()*3/2, sPaint);
            }
        }
        if (currPer >= 150 && currPer < 160) {
            canvas.drawText("" + (currPer - 60), x - 2 * rect.width() / 3, y + radius / 3, perPaint);
        }
        if (currPer >= 160) {
            canvas.drawText("" + 100, x - 2 * rect1.width() / 3, y + radius / 3, perPaint);
        }
    }
    private void initRatingBar() {
        int dividePart = RatingBars.size();
        if (dividePart == 0) {
            return;
        }
        int sweepAngle = dividePart == 1 ? 360 : (360 - dividePart * STROKE_OFFSET) / dividePart;
        int rotateOffset = dividePart == 1 ? 90 : 90 + sweepAngle / 2 - 3;
        for (int i = 0; i < dividePart; i++) {
            float startAngle = i * (sweepAngle + STROKE_OFFSET) - rotateOffset;
            RatingBar RatingBar = RatingBars.get(i);
            if (dividePart == 1) {
                RatingBar.setSingle(true);
            }
            RatingBar.setX(x);
            RatingBar.setY(y);
            RatingBar.setStartAngle(startAngle);
            RatingBar.setSweepAngle(sweepAngle);
            RatingBar.init(maxRate);
            radius = RatingBar.getRadius();
        }
        initPaint();
    }
    private void initPaint() {
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setTextSize(radius / 4);
        paint.setColor(Color.WHITE);
        paint.setAlpha((int) (255 * 0.6));
        perPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        perPaint.setAlpha(255);
        perPaint.setTextSize(radius / 2);
        perPaint.setColor(Color.WHITE);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setTextSize(radius / 4);
        mPaint.setColor(Color.WHITE);
        mPaint.setAlpha(255);
        resulPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        resulPaint.setAlpha((int) (255 * 0.7));
        resulPaint.setColor(Color.WHITE);
        resulPaint.setTextSize(radius / 2);
        sPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        sPaint.setAlpha((int) (255 * 0.6));
        sPaint.setColor(Color.WHITE);
        sPaint.setTextSize(radius / 6);
        rect = new Rect();
        perPaint.getTextBounds("10", 0, "10".length(), rect);
        rect1 = new Rect();
        perPaint.getTextBounds("100", 0, "100".length(), rect1);
        textRect = new Rect();
        paint.getTextBounds(name, 0, name.length(), textRect);
        ditalRect = new Rect();
        sPaint.getTextBounds(assess,0,assess.length(),ditalRect);
        resultRect = new Rect();
        resulPaint.getTextBounds(result, 0, result.length(), resultRect);
    }
    public void addRatingBar(RatingBar RatingBar) {
        RatingBar.add(RatingBar);
    }
    public void show() {
        if (RatingBar.size() == 0) {
            return;
        }
        isShow = true;
        isEmpty = false;
        if (rotateAnimation != null) {
            rotateAnimation.cancel();
        }
        initRatingBar();
        rotateAnimation.setRepeatCount(0);        //旋轉動畫
        rotateAnimation.start();        //百分比動畫
        perAnimation.start();        //評估中動畫
        detailAnimation.start();
        if (onAnimatorListener!=null){
            onAnimatorListener.onStart();
        }
    }
    public void showEmpty() {
        isEmpty = true;
        initEmpty();
        invalidate();
        rotateAnimation.setRepeatMode(ValueAnimator.RESTART);
        rotateAnimation.setRepeatCount(ValueAnimator.INFINITE);
        rotateAnimation.start();
    }
    private void initEmpty() {
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setTextSize(radius / 5);  //
        paint.setColor(Color.WHITE);
        paint.setAlpha((int) (255 * 0.6));
        textRect = new Rect();
        paint.getTextBounds(name, 0, name.length(), textRect);
    }
    public void clear() {
        rotateAnimation.end();
        rotateAnimation.cancel();
        RatingBar.clear();
        isShow = false;
        ditalAlpha=0;
        resultAlpha=0;
        currStarNum=-1;
        isShowDetail=true;
        invalidate();
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                eventX = event.getX();
                eventY = event.getY();
                break;
            case MotionEvent.ACTION_UP:
                float resX = Math.abs(event.getX() - eventX);
                float resY = Math.abs(event.getY() - eventY);
                if (resX<10&&resY<10){
                    if (isAnimationYEnd){
                        Log.e("HHH", "onTouchEvent: " + event.getX() +"---"+ event.getY() +"---"+ width*365/450 +"---"+ height*15/16 );
                        if (event.getX()>=width-textRectF.width()*3/2 && event.getX()<width && event.getY()>=height-2*textRectF.height() && event.getY()<height) {
                            if (onClickRatingViewListener!=null){
                                onClickRatingViewListener.onClick();
                            }
                        }
                    }
                }
                break;
        }
        return true;
    }
    public void reSet(){
        name="";
        ditalAlpha=0;
        resultAlpha=0;
        currStarNum=-1;
        reSetAnimation.start();
    }
    private OnClickRatingViewListener onClickRatingViewListener;
    public void setOnClickRatingViewListener(OnClickRatingViewListener onClickRatingViewListener) {
        this.onClickRatingViewListener = onClickRatingViewListener;
    }
    public interface OnClickRatingViewListener{
        void onClick();
    }
    private OnAnimatorListener onAnimatorListener;
    public void setOnAnimatorListener(OnAnimatorListener onAnimatorListener) {
        this.onAnimatorListener = onAnimatorListener;
    }
    public interface OnAnimatorListener{
        void onStart();
        void onEnd();
    }
}

啊啊啊!!!一行一行的格式化代碼好麻煩啊,有沒有大神知道快速格式化代碼的嗎

下面是每個小格

public class RatingBar {
    private static final int ITEM_OFFSET = 1; //每個小item的間隙
    private static final int UN_RATING_ALPHA = (int) (255 * 0.3);  //沒被選中的item的透明度
    private static final int OUTLINE_ALPHA = (int) (255 * 0.4);  //外面的線的透明度
    private static final int RATING_ALPHA = (int) (255 * 0.8);  //評分的透明度
    private int ratingAlpha;
    private float startAngle;  //每扇形開始的角度
    private int sweepAngle;    //每個扇形的角度
    private int ratingBarWidth;  //評分的寬度
    private int outLineWidth;    //外面的線的寬度
    private int maxRate = 18;    //總分數
    private int currRate;        //當前的評分數
    private int radius;    //半徑
    private int x, y;      //位置
    private List<Rate> rates;
    private Paint paint, outLinrPaint, ratingPaint;
    private RectF rectF, outLineRectF;
    private boolean isSingle = false;
    public RatingBar(int currRate) {
        this.currRate = currRate;
        ratingAlpha=RATING_ALPHA;
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.WHITE);
        outLinrPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        outLinrPaint.setColor(Color.WHITE);
        ratingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        ratingPaint.setColor(Color.WHITE);
    }
    void init(int maxRate) {
        this.maxRate=maxRate;
        initRaingBar();
        initRectF();
        initPaint();
    }
    private void initPaint() {
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(ratingBarWidth);
        paint.setAlpha(UN_RATING_ALPHA);
        outLinrPaint.setStyle(Paint.Style.STROKE);
        outLinrPaint.setStrokeWidth(outLineWidth);
        outLinrPaint.setAlpha(OUTLINE_ALPHA);
        ratingPaint.setStyle(Paint.Style.STROKE);
        ratingPaint.setStrokeWidth(ratingBarWidth);
        ratingPaint.setAlpha(ratingAlpha);
    }
    private void initRectF() {
        radius = y / 4*3;
        ratingBarWidth = radius / 8;
        outLineWidth = ratingBarWidth / 4;
        int outLineRadius = radius -outLineWidth/2;
        int ratingBarRadius = radius - ratingBarWidth / 2-5*outLineWidth;
        rectF = new RectF();
        rectF.left = x - ratingBarRadius;
        rectF.top = y - ratingBarRadius;
        rectF.right = x + ratingBarRadius;
        rectF.bottom = y + ratingBarRadius;
        outLineRectF = new RectF();
        outLineRectF.left = x - outLineRadius;
        outLineRectF.top = y - outLineRadius;
        outLineRectF.right = x + outLineRadius;
        outLineRectF.bottom = y + outLineRadius;
    }
    private void initRaingBar() {
        rates = new ArrayList<>();
        float itemSweepAngle;
        if (isSingle) {
            itemSweepAngle = (sweepAngle - (ITEM_OFFSET * maxRate)) / maxRate;
        } else {
            //計算每個item的弧度
            itemSweepAngle = (sweepAngle - (ITEM_OFFSET * (maxRate - 1))) / maxRate;
       }
        for (int i = 0; i < maxRate; i++) {
            //計算每個item的開始角度
            float itemstartAngle = startAngle + i * (itemSweepAngle + ITEM_OFFSET);
            rates.add(new Rate(itemstartAngle, itemSweepAngle));
        }
    }
    void drawUnRate(Canvas canvas) {
        for (Rate rate : rates) {
            rate.drawArc(canvas, rectF, paint);
        }
    }
    void drawLine(Canvas canvas) {
        //周長
        canvas.drawArc(outLineRectF, startAngle-3, sweepAngle, false, outLinrPaint);
    }
    void drawRating(Canvas canvas, int index) {
        if (index > currRate) {
            return;
        }
        Rate rate = rates.get(index);
        rate.drawRate(canvas, rectF, ratingPaint);
    }
    void setStartAngle(float startAngle) {
        this.startAngle = startAngle;
    }
    void setSweepAngle(int sweepAngle) {
        this.sweepAngle = sweepAngle;
    }
    void setX(int x) {
        this.x = x;
    }
    void setY(int y) {
        this.y = y;
    } 
   void setSingle(boolean single) { 
      isSingle = single;  
  }   
 int getRadius() {    
    return radius; 
   }  
  int getCurrRate() {      
  return currRate;    
}
    private class Rate {
        private float startAngle, sweepAngle;   //每個小格的角度
        Rate(float startAngle, float sweepAngle) {
            this.startAngle = startAngle; 
           this.sweepAngle = sweepAngle;
        }
        void drawArc(Canvas canvas, RectF oval, Paint paint) {
            canvas.drawArc(oval, startAngle, sweepAngle, false, paint);
        }
        void drawRate(Canvas canvas, RectF rectF, Paint paint) {
            canvas.drawArc(rectF, startAngle, sweepAngle, false, paint);
        }
    }
}

代碼看著很多,但是原理很簡單,邏輯有點亂,可以說ValueAnimator的作用就是用來計時的,但是在以前有個項目中用ValueAnimator來做循環倒計時,大概代碼如下:

animator=ValueAnimator.ofInt(5,0);
animator.setDuration(5000);
animator.setInterpolator(new LinearInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        time=(int)valueAnimator.getAnimatedValue();
        text.setText(String.valueOf(time));
    }});
animator.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        animator.start();  //當動畫結束后又繼續該動畫,實現一個無限循環的效果
    }});

就用動畫實現一個無限循環的效果,想像的很美好,但是一運行這個動畫只執行了兩次,第二次結束后就沒有繼續了,苦思冥想,各種測試最后找到一個方法,就是在結束的時候用handler來發送一個消息,在接收消息那里再啟動動畫,這個動畫就可以實現無線循環了,具體原因為什么呢?有沒有大神知道的給我留個言吧。

在運行這個評分動畫的時候也發現了一個問題,在動畫更新的監聽中long currentPlayTime = valueAnimator.getCurrentPlayTime();這個方法在大部分手機沒有問題,但就在華為榮耀8的7.0的手機上出現了動畫不按套路出牌的效果,根據動畫的效果來看發現問題出在這里,由于這里有個啟動動畫,這個動畫就在這里亂套了,然而打印出currentPlayTime ,奇怪的是在第一次運行的時候沒有任何異常,在第二次的時候currentPlayTime 的初始值不是0,而是當前動畫從開始執行到現在的總共時間,用其他手機來測試,沒有發現異常,再看源碼里面也沒有關于版本的代碼,就暫時在currentPlayTime 這里判斷了一下,如果大于總時間就等于0,然后再來榮耀上運行,歐拉,暫時沒有問題了。

最后附上截圖-O(∩_∩)O哈哈~

GIF.gif

 

來自:http://www.jianshu.com/p/b8d3e833d3c9

 

 本文由用戶 bnxrrta85 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!