項目地址: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哦