先看一下效果:
1,自定义一个ViewGroup继承自LinearLayout:
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.LinearLayout;
public class LoadingViewGroup extends LinearLayout {
private CustomAnimation mShapeView;
private View mShadowView;
private int mTranslationDistance=0;
private final int ANIMATION_DURMATION=800;
private boolean isCloseAnimation=false;
public LoadingViewGroup(Context context) {
this(context,null);
}
public LoadingViewGroup(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public LoadingViewGroup(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mTranslationDistance=dip2px(100);
initLayout();
//实例化View,添加进来
}
private void initLayout(){
View view=inflate(getContext(),R.layout.ui_loading_view,this);
mShapeView= (CustomAnimation) findViewById(R.id.loading_shape);
mShadowView=findViewById(R.id.loading_shadow);
post(new Runnable() {
@Override
public void run() {
startFallAnimation();
}
});
//startFallAnimation();当然也可以这样写,但是这样写是在onCreate()中执行的
}
private void startFallAnimation(){
if (isCloseAnimation){
return;
}
ObjectAnimator translationAnimation=ObjectAnimator.ofFloat(mShapeView,"translationY",0,mTranslationDistance);
ObjectAnimator scaleAnimation=ObjectAnimator.ofFloat(mShadowView,"scaleX",1f,0.2f);
AnimatorSet animatorSet=new AnimatorSet();
animatorSet.playTogether(translationAnimation,scaleAnimation);
animatorSet.setDuration(ANIMATION_DURMATION);
animatorSet.setInterpolator(new AccelerateInterpolator());
animatorSet.start();
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
//下降结束开始转换形状
mShapeView.exchange();
startUpAnimation();
}
});
}
private void startUpAnimation(){
ObjectAnimator translationAnimation=ObjectAnimator.ofFloat(mShapeView,"translationY",mTranslationDistance,0);
ObjectAnimator scaleAnimation=ObjectAnimator.ofFloat(mShadowView,"scaleX",0.2f,1f);
AnimatorSet animatorSet=new AnimatorSet();
animatorSet.playTogether(translationAnimation,scaleAnimation);
animatorSet.setDuration(ANIMATION_DURMATION);
animatorSet.setInterpolator(new DecelerateInterpolator());
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
startFallAnimation();
}
@Override
public void onAnimationStart(Animator animation) {
//上升已开始就开始开始旋转
startRotation();
}
});
animatorSet.start();
}
private void startRotation(){
ObjectAnimator rotationAnimator = null;
switch (mShapeView.getCurrentShape()){
case round:
case triangle:
rotationAnimator=ObjectAnimator.ofFloat(mShapeView,"rotation",0,120);
break;
case rectangle:
rotationAnimator=ObjectAnimator.ofFloat(mShapeView,"rotation",0,180);
break;
}
rotationAnimator.setDuration(ANIMATION_DURMATION);
rotationAnimator.setInterpolator(new DecelerateInterpolator());
rotationAnimator.start();
}
@Override
public void setVisibility(int visibility) {
super.setVisibility(INVISIBLE);//不要进行摆放和计算
mShapeView.clearAnimation();
mShadowView.clearAnimation();
ViewGroup parent= (ViewGroup) getParent();
if (parent!=null){
parent.removeView(this);//把自己从父布局移除
removeAllViews();//移除自己所有的View
}
isCloseAnimation=true;
}
private int dip2px(int dip){
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dip,getResources().getDisplayMetrics());
}
}
2,定义一个View,继承自V借我,实现各种形状切换
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
public class CustomAnimation extends View {
private Paint paint;
private Shape currentShape=Shape.round;
public CustomAnimation(Context context) {
this(context,null);
}
public CustomAnimation(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public CustomAnimation(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint=new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width=MeasureSpec.getSize(widthMeasureSpec);
int height=MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width>height?height:width,width>height?height:width);
}
@Override
protected void onDraw(Canvas canvas) {
switch (currentShape){
case round:
paint.setColor(getResources().getColor(R.color.circle));
canvas.drawCircle(getWidth()/2,getHeight()/2,getWidth()/2,paint);
break;
case triangle:
Path path=new Path();
paint.setColor(getResources().getColor(R.color.triangle));
path.moveTo(getWidth()/2,0);
path.lineTo(0,getHeight());
path.lineTo(getWidth(),getHeight());
path.close();
canvas.drawPath(path,paint);
break;
case rectangle:
paint.setColor(ContextCompat.getColor(getContext(),R.color.rectangle));
canvas.drawRect(0,0,getWidth(),getHeight(),paint);
break;
}
}
public void exchange(){
switch (currentShape){
case rectangle:
currentShape=Shape.triangle;
break;
case triangle:
currentShape=Shape.round;
break;
case round:
currentShape=Shape.rectangle;
break;
}
invalidate();
}
public Shape getCurrentShape(){
return this.currentShape;
}
enum Shape{
triangle,
rectangle,
round
}
}
3,activity_main中的布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="测试按钮"
android:onClick="test"/>
<com.darren.view_day12.LoadingViewGroup
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:onClick="visibility"
android:layout_centerInParent="true"/>
</RelativeLayout>
4,自定义的布局所要加载的文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
>
<com.darren.view_day12.CustomAnimation
android:id="@+id/loading_shape"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginBottom="100dp"
/>
<View
android:id="@+id/loading_shadow"
android:layout_width="30dp"
android:layout_height="6dp"
android:background="@drawable/shadow_loading"/>
<TextView
android:id="@+id/loading_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="玩命加载中..."/>
</LinearLayout>