项目地址:https://github.com/CuteWiseCode/LoadingView
先上效果图
实现思路: 代码实现主要结合自定义view 以及动画属性的方式,根据需求调整动画的展示方式、加速度等。
一、动画的布局文件
将白色背景图以及需要转动的图片资源引用到布局文件中。布局文件以FrameLayout 作为父view,默认展示背景图以及第一个转动的图片。
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center" >
android:layout_gravity="center"
android:layout_width="86.0dip"
android:layout_height="86.0dip"
android:background="@mipmap/bg_animation" />
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" />
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" />
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" />
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" />
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" />
二、创建一个 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(@NonNullContext 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 = newAnimationLoad(paramFloat1, paramFloat2, this.floata, this.floatb, this.floatc, true);
animation.setDuration(this.intk);
animation.setFillAfter(true);//true if theanimation should apply its transformation after it ends
animation.setInterpolator(newAccelerateInterpolator());//Sets the acceleration curve for this animation.Defaults to a linear interpolation.Parameters:i The interpolator which definesthe acceleration curve
animation.setAnimationListener(new animationListener());//theanimation listener to be notified
paramView.startAnimation(animation);
}
监听类:animationListener。在动画结束的时候,启动runnable,启动另一个动画
private final classanimationListener
implements Animation.AnimationListener
{
private animationListener()
{
}
public void onAnimationEnd(AnimationparamAnimation)
{
//The Runnable that will be executed.
AnimationView.this.post(new runnable());
}
public void onAnimationRepeat(AnimationparamAnimation){ }
public void onAnimationStart(AnimationparamAnimation)
{ }
}
runnable 线程:
private final classrunnable
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 = newAnimationLoad(-90.0F, 0.0F, floata, floatb, floatc, false);
animation.setDuration(intk);
animation.setFillAfter(true);
animation.setInterpolator(newDecelerateInterpolator());//减速
animation.setAnimationListener(newAnimation.AnimationListener()
{
public void onAnimationEnd(AnimationparamAnimation)
{
AnimationView.this.initView();
}
public void onAnimationRepeat(AnimationparamAnimation)
{
}
public void onAnimationStart(AnimationparamAnimation)
{
}
});
viewe.startAnimation(animation);
return;
}
}
}
上述代码中 AnimationLoad 类如下:继承了Animation,使用Camera 以及Matrix 定义了旋转的方式。
private final floatfloata;
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, floatparamFloat2, float paramFloat3, float paramFloat4, float paramFloat5, booleanparamBoolean)
{
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(floatparamFloat, 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 camerastate. 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 arotation transform around the Y axis.
localCamera.getMatrix(localMatrix);//Computesthe matrix corresponding to the current transformation and copies it to thesupplied matrix object.
localCamera.restore();//Restores thesaved state, if any
// localMatrix.postScale(0.5f, 0.5f);//使原来的图像缩放成原来的1/2
localMatrix.preTranslate(-f3, -f4);
localMatrix.postTranslate(f3, f4);
return;
}
}
/**
* Initialize this animation with thedimensions of the object being animated
*/
public void initialize(int paramInt1, intparamInt2, int paramInt3, int paramInt4)
{
super.initialize(paramInt1, paramInt2,paramInt3, paramInt4);
this.camerag = new Camera();
}
分享到此结束,demo 请前往github, 记得给个star哦