项目地址:https://github.com/CuteWiseCode/LoadingView
先上效果图
实现思路: 代码实现主要结合自定义view 以及动画属性的方式,根据需求调整动画的展示方式、加速度等。
将白色背景图以及需要转动的图片资源引用到布局文件中。布局文件以FrameLayout 作为父view,默认展示背景图以及第一个转动的图片。
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哦