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哦

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