今天首先来看一个效果:
首先我们需要自定义一个ShapeView:
package com.example.anim_01;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by Michael on 2019/11/6.
*/
public class ShapeView extends View {
private Shape mCurrentShape = Shape.Square;
private Paint p;
private Path path;
public ShapeView(Context context) {
this(context,null);
}
public ShapeView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public ShapeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
p = new Paint();
p.setAntiAlias(true);
path = new Path();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(Math.min(width,height),Math.min(width,height));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
switch (mCurrentShape){
case Circle:
//画圆形
int width = getWidth()/2;
p.setColor(ContextCompat.getColor(getContext(),R.color.circle));
canvas.drawCircle(width,width,width,p);
break;
case Square:
//画正方形
int w = getWidth();
p.setColor(ContextCompat.getColor(getContext(),R.color.rect));
Rect r = new Rect(0,0,w,w);
canvas.drawRect(r,p);
break;
case Triangle:
//画等腰三角形
path.moveTo(getWidth()/2,0);
path.lineTo(0,(float) (Math.sqrt(3)/2)*getHeight());
path.lineTo(getWidth(),(float) (Math.sqrt(3)/2)*getHeight());
path.close();
p.setColor(ContextCompat.getColor(getContext(), R.color.triangle));
canvas.drawPath(path,p);
break;
}
}
enum Shape{
Circle,Square,Triangle
}
public void exChange(){
switch (mCurrentShape) {
case Circle:
mCurrentShape = Shape.Square;
break;
case Triangle:
mCurrentShape = Shape.Circle;
break;
case Square:
mCurrentShape = Shape.Triangle;
break;
}
invalidate();
}
public Shape getCurrentShape(){
return mCurrentShape;
}
}
然后我们组合ShapeVew+line+底部文字:
<?xml version="1.0" encoding="utf-8"?>
<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.example.anim_01.ShapeView
android:id="@+id/shape_view"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginBottom="90dp"
/>
<View
android:id="@+id/v_line"
android:layout_width="25dp"
android:layout_height="3dp"
android:background="@drawable/shape_line"
/>
<TextView
android:layout_marginTop="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="正在加载中......"
/>
</LinearLayout>
shape_line代码:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval"
>
<solid android:color="#000000"/>
</shape>
最后把布局加载到LoadingView中去,然后加上动画:
package com.example.anim_01;
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.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.LinearLayout;
/**
* Created by Michael on 2019/11/6.
*/
public class LoadingView extends LinearLayout {
private ShapeView shapeView;
private int distance = 88;
private View vLine;
public static final int Time = 450;
public LoadingView(Context context) {
this(context,null);
}
public LoadingView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public LoadingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initLayout();
shapeView = findViewById(R.id.shape_view);
vLine = findViewById(R.id.v_line);
post(new Runnable() {
@Override
public void run() {
startToFall();
}
});
}
private int dp2x(int dpValue) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, getResources().getDisplayMetrics());
}
private void startToFall() {
ObjectAnimator anim1 = ObjectAnimator.ofFloat(shapeView,
"translationY",0,dp2x(distance));
ObjectAnimator anim2 = ObjectAnimator.ofFloat(vLine,
"scaleX",1.0f,0.3f);
AnimatorSet set = new AnimatorSet();
set.playTogether(anim1,anim2);
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
startToUp();
}
});
set.setDuration(Time);
set.setInterpolator(new AccelerateInterpolator());
set.start();
}
private void startToUp() {
ObjectAnimator anim1 = ObjectAnimator.ofFloat(shapeView,
"translationY",dp2x(distance),0);
ObjectAnimator anim2 = ObjectAnimator.ofFloat(vLine,
"scaleX",0.3f,1.0f);
AnimatorSet set2 = new AnimatorSet();
set2.playTogether(anim1,anim2);
set2.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
startToFall();
}
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
startToRotate();
startToExchange();
}
});
set2.setDuration(Time);
set2.setInterpolator(new AccelerateInterpolator());
set2.start();
}
private void startToExchange() {
shapeView.exChange();
}
private void startToRotate() {
ObjectAnimator anim = null;
switch (shapeView.getCurrentShape()){
case Square:
anim = ObjectAnimator.ofFloat(shapeView,"rotation",0,180);
break;
case Triangle:
anim = ObjectAnimator.ofFloat(shapeView,"rotation",0,-120);
break;
case Circle:
anim = ObjectAnimator.ofFloat(shapeView,"rotation",0,180);
break;
}
anim.setDuration(Time);
anim.setInterpolator(new DecelerateInterpolator());
anim.start();
}
private void initLayout() {
inflate(getContext(),R.layout.ui_loading_view,this);
}
}