Android 自定义动画 LoadingView

 

项目地址:https://github.com/CuteWiseCode/LoadingView

先上效果图

 

实现思路: 代码实现主要结合自定义view 以及动画属性的方式,根据需求调整动画的展示方式、加速度等。

一、动画的布局文件

      将白色背景图以及需要转动的图片资源引用到布局文件中。布局文件以FrameLayout 作为父view,默认展示背景图以及第一个转动的图片。

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

    <ImageView
        android:layout_gravity="center"
        android:layout_width="86.0dip"
        android:layout_height="86.0dip"
        android:background="@mipmap/bg_animation" />

    <ImageView
        android:layout_gravity="center"
        android:id="@+id/loading_view_01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/loading_01" />

    <ImageView
        android:layout_gravity="center"
        android:id="@+id/loading_view_02"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/loading_02"
        android:visibility="invisible" />

    <ImageView
        android:layout_gravity="center"
        android:id="@+id/loading_view_03"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/loading_03"
        android:visibility="invisible" />

    <ImageView
        android:layout_gravity="center"
        android:id="@+id/loading_view_04"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/loading_04"
        android:visibility="invisible" />

    <ImageView
        android:layout_gravity="center"
        android:id="@+id/loading_view_05"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/loading_05"
        android:visibility="invisible" />

</FrameLayout>

二、创建一个 AnimationView 类

2.1、继承 FrameLayout ,重写两个构造函数   AnimationView(Context paramContext) 和 AnimationView(@NonNull Context context, @Nullable AttributeSet attrs) ,了解自定义View的童鞋 应该知道,第一个构造函数用于在代码中新建时调用,第二个构造函数用户在布局文件中定义时调用。

	//构造函数
	  public AnimationView(Context paramContext)
	  {
	    super(paramContext);
	    
	    inflate(getContext(), R.layout.loading_view, this);//layout_loading_view
	    initializeView();
	  }

	public AnimationView(@NonNull Context context, @Nullable AttributeSet attrs) {
		super(context, attrs);
		
		inflate(getContext(), R.layout.loading_view, this);//layout_loading_view
		initializeView();
	}

2.2、在构造函数中解析布局文件,并进行初始化

/**
	 * 初始化控件
	 */
	  private void initializeView()
	  {
		   
	    this.viewf = ((ImageView)findViewById(R.id.loading_view_01));
	    this.viewg = ((ImageView)findViewById(R.id.loading_view_02));
	    this.viewh = ((ImageView)findViewById(R.id.loading_view_03));
	    this.viewi = ((ImageView)findViewById(R.id.loading_view_04));
	    this.viewj = ((ImageView)findViewById(R.id.loading_view_05));
	    this.viewe = this.viewf;
	    //测量控件的大小 UNSPECIFIED = 0 EXACTLY = 1 AT_MOST= 2
	    int m = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
	    int n = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
	    this.viewf.measure(m, n);
	    this.floata = (this.viewf.getMeasuredWidth() / 2);//获取宽的值,除2
	    this.floatb = (this.viewf.getMeasuredHeight() / 2);//获取高的值除2

	    initView();//开始动画
	  }

2.3、设置并开始动画,注意这里使用到动画监听   animationListener

 public void initView()
	  {
	    tostartAnimation(this.viewe, 0.0F, 90.0F);
	  }
/**
	 * 
	 * @param paramView 具体某个view
	 * @param paramFloat1 0.0f
	 * @param paramFloat2 90.0f
	 * 
	 * 
	 */
	  private void tostartAnimation(View paramView, float paramFloat1, float paramFloat2)
	  {
		 
	    AnimationLoad animation = new AnimationLoad(paramFloat1, paramFloat2, this.floata, this.floatb, this.floatc, true);
	    animation.setDuration(this.intk);
	    animation.setFillAfter(true);//true if the animation should apply its transformation after it ends
	    animation.setInterpolator(new AccelerateInterpolator());//Sets the acceleration curve for this animation. Defaults to a linear interpolation.Parameters:i The interpolator which defines the acceleration curve
	    animation.setAnimationListener(new animationListener());//the animation listener to be notified
	    paramView.startAnimation(animation);
	  }

监听类:animationListener。在动画结束的时候,启动runnable,启动另一个动画

 private final class animationListener
	    implements Animation.AnimationListener
	  {
	    private animationListener()
	    {
	    }

	    public void onAnimationEnd(Animation paramAnimation)
	    {
	       //The Runnable that will be executed.
	      AnimationView.this.post(new runnable());
	    }

	    public void onAnimationRepeat(Animation paramAnimation)
	    {
	    }

	    public void onAnimationStart(Animation paramAnimation)
	    {
	    }
	  }

runnable 线程:

 private final class runnable
	      implements Runnable
	    {
	      private runnable()
	      {
	      }

	      public void run()
	      {
	      	viewf.setVisibility(View.GONE);//1
	      	viewg.setVisibility(View.GONE);//2
	      	viewh.setVisibility(View.GONE);//3
	      	viewi.setVisibility(View.GONE);//4
	      	viewj.setVisibility(View.GONE);//5
	      	viewe.setVisibility(View.GONE);
	      	intd++;
	      	if (intd % 5 == 0)//intd
	      		setData(viewf);//第一张
	        while (true)
	        {
	      	  if (1 == intd % 5)
	            {
	            	setData( viewg);
//	            	continue;
	            }
	            if (2 == intd % 5)
	            {
	            	setData( viewh);
//	            	continue;
	            }
	            if (3 == intd % 5)
	            {
	            	setData( viewi);
//	            	continue;
	            }
	            if (4 == intd % 5)
	            	setData( viewj);
	          viewe.setVisibility(View.VISIBLE);
	          viewe.requestFocus();
	          AnimationLoad animation = new AnimationLoad(-90.0F, 0.0F, floata, floatb, floatc, false);
	          animation.setDuration(intk);
	          animation.setFillAfter(true);
	          animation.setInterpolator(new DecelerateInterpolator());//减速
	          animation.setAnimationListener(new Animation.AnimationListener()
	          {
	            public void onAnimationEnd(Animation paramAnimation)
	            {
	              AnimationView.this.initView();
	            }

	            public void onAnimationRepeat(Animation paramAnimation)
	            {
	            }

	            public void onAnimationStart(Animation paramAnimation)
	            {
	            }
	          });
	         
	          viewe.startAnimation(animation);
	          return;
	        }
	      }
	    }

上述代码中 AnimationLoad 类如下:继承了Animation,使用Camera 以及Matrix  定义了旋转的方式。

  private final float floata;
	  private final float floatb;
	  private final float floatc;
	  private final float floatd;
	  private final float floate;
	  private final boolean boolf;
	  private Camera camerag;

	  public AnimationLoad(float paramFloat1, float paramFloat2, float paramFloat3, float paramFloat4, float paramFloat5, boolean paramBoolean)
	  {
	    this.floata = paramFloat1;//0
	    this.floatb = paramFloat2;//90.0f
	    this.floatc = paramFloat3;//172
	    this.floatd = paramFloat4;//172
	    this.floate = paramFloat5;//0
	    this.boolf = paramBoolean;
	  }
	 
	  protected void applyTransformation(float paramFloat, Transformation paramTransformation)
	  {
	    float f1 = this.floata;//0.0f
	    float f2 = f1 + paramFloat * (this.floatb - f1);//90
	    float f3 = this.floatc;//172
	    float f4 = this.floatd;//172
	    Camera localCamera = this.camerag;
	    Matrix localMatrix = paramTransformation.getMatrix();
	    localCamera.save();//Saves the camera state. Each save should be balanced with a call to restore().
	   //如果时加速
	    if (this.boolf)
	      localCamera.translate(0.0F, 0.0F, paramFloat * this.floate);//Applies a translation transform on all three axis
	      localCamera.translate(0.0F, 0.0F, this.floate * (1.0F - paramFloat));
	    while (true)
	    {
	      localCamera.rotateY(f2);//Applies a rotation transform around the Y axis.
	      localCamera.getMatrix(localMatrix);//Computes the matrix corresponding to the current transformation and copies it to the supplied matrix object.
	      localCamera.restore();//Restores the saved state, if any
//	    localMatrix.postScale(0.5f, 0.5f);//使原来的图像缩放成原来的1/2
	      localMatrix.preTranslate(-f3, -f4);
	      localMatrix.postTranslate(f3, f4);
	      return;
	    }
	  }
	  /**
	   * Initialize this animation with the dimensions of the object being animated 
	   */
	  public void initialize(int paramInt1, int paramInt2, int paramInt3, int paramInt4)
	  {
	    super.initialize(paramInt1, paramInt2, paramInt3, paramInt4);
	    this.camerag = new Camera();
	  }
	

分享到此结束,demo 请前往github,  记得给个star哦

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