zoukankan      html  css  js  c++  java
  • 豆瓣加载动画实现

    最终效果如下

    ValueAnimator类API 简介

    • ofFloat(float… values) 构建ValueAnimator,设置动画的浮点值,需要设置2个以上的值

    • setDuration(long duration) 设置动画时长,默认的持续时间为300毫秒。

    • setInterpolator(TimeInterpolator value) 设置动画的线性非线性运动,默认AccelerateDecelerateInterpolator

    • addUpdateListener(ValueAnimator.AnimatorUpdateListener listener) 监听动画属性每一帧的变化

    分解步骤,计算一下总共需要的角度:
    1、一个笑脸,x轴下方的圆弧旋转135°,覆盖2个点,此过程中圆弧增加45°
    2、画布旋转135°,此过程中圆弧增加45°
    3、画布旋转360°,此过程中圆弧减少360/5度
    4、画布旋转90°,此过程中圆弧减少90/5度
    5、画布旋转135°,释放覆盖的2个点

    实现

    package com.zj.test;
    
    import android.animation.TimeInterpolator;
    import android.animation.ValueAnimator;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.RectF;
    import android.util.AttributeSet;
    import android.view.View;
    import android.view.animation.DecelerateInterpolator;
    
    /**
     * Created by jjx on 2016/5/28.
     */
    public class customView extends View{
    
    
    
    //    public customView(Context context, AttributeSet attrs, int defStyleAttr) {
    //        super(context, attrs, defStyleAttr);
    //
    //        initAnimator(animatorDuration);
    //        mPaint=new Paint();
    //        mPaint.setStyle(Paint.Style.STROKE);//设置画笔样式为描边,如果已经设置,可以忽略
    //        mPaint.setColor(Color.GREEN);
    //        mPaint.setStrokeWidth(10);
    //    }
    
        float Width;
        float Height;
    
        public customView(Context context, AttributeSet attrs) {
            super(context, attrs);
    
            initAnimator(animatorDuration);
            mPaint=new Paint();
            mPaint.setStyle(Paint.Style.STROKE);//设置画笔样式为描边,如果已经设置,可以忽略
            mPaint.setColor(Color.GREEN);
            mPaint.setStrokeWidth(10);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
            Width=MeasureSpec.getSize(widthMeasureSpec);
            mViewWidth=Width;
    
            Height=MeasureSpec.getSize(heightMeasureSpec);
        }
    
        Paint mPaint;
        float mViewWidth;
    
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.translate(Width/2,Height/2);
            doubanAnimator(canvas, mPaint);
        }
    
        private ValueAnimator animator;
        private float animatedValue;
        private long animatorDuration = 5000;
        private TimeInterpolator timeInterpolator = new DecelerateInterpolator();
    
        private void initAnimator(long duration){
            if (animator !=null &&animator.isRunning()){
                animator.cancel();
                animator.start();
            }else {
                animator=ValueAnimator.ofFloat(0,855).setDuration(duration);
                animator.setInterpolator(timeInterpolator);
                animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        animatedValue = (float) animation.getAnimatedValue();
                        invalidate();
                    }
                });
                animator.start();
            }
        }
    
    
        private void doubanAnimator(Canvas canvas, Paint mPaint){
            mPaint.setStyle(Paint.Style.STROKE);//描边
            mPaint.setStrokeCap(Paint.Cap.ROUND);//圆角笔触
            mPaint.setColor(Color.rgb(97, 195, 109));
            mPaint.setStrokeWidth(15);
            float point = Math.min(mViewWidth,mViewWidth)*0.06f/2;
            float r = point*(float) Math.sqrt(2);
            RectF rectF = new RectF(-r,-r,r,r);
            canvas.save();
    
            // rotate
            if (animatedValue>=135){
                canvas.rotate(animatedValue-135);
            }
    
            // draw mouth
            float startAngle=0, sweepAngle=0;
            if (animatedValue<135){
                startAngle = animatedValue +5;
                sweepAngle = 170+animatedValue/3;
            }else if (animatedValue<270){
                startAngle = 135+5;
                sweepAngle = 170+animatedValue/3;
            }else if (animatedValue<630){
                startAngle = 135+5;
                sweepAngle = 260-(animatedValue-270)/5;
            }else if (animatedValue<720){
                startAngle = 135-(animatedValue-630)/2+5;
                sweepAngle = 260-(animatedValue-270)/5;
            }else{
                startAngle = 135-(animatedValue-630)/2-(animatedValue-720)/6+5;
                sweepAngle = 170;
            }
            canvas.drawArc(rectF,startAngle,sweepAngle,false,mPaint);
    
            // draw eye
            canvas.drawPoints(new float[]{
                    -point,-point
                    ,point,-point
            },mPaint);
    
            canvas.restore();
        }
    
    }

    布局文件

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

    参考链接

    自定义View——Canvas与ValueAnimator – Idtk

  • 相关阅读:
    docker-compose运行nginx
    docker后台持续运行
    docker-compose运行tomcat
    集群session解决方案
    docker运行mysql
    docker运行svn
    mongodb数据的导出和导入
    mongodb副本集的docker化安装
    grafana使用json数据源监控数据
    docker化安装grafana
  • 原文地址:https://www.cnblogs.com/jjx2013/p/6223635.html
Copyright © 2011-2022 走看看