前言
由于工作需要,有个需求要求做成58同城类似的进度条加载动画效果,这就需要自定义View ,然后用到 ObjectAnimator 属性动画
1.自定义View
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
public class ShapeView extends View {
//初始形状
public Shape mCurrentShape = Shape.CIRCLE;
private Paint mPaint;
private Path mPath;
public enum Shape {
CIRCLE,
RECTANGLE,
TRIANGLE,
}
public ShapeView(Context context) {
this(context, null);
}
public ShapeView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ShapeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPath = new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
}
public Shape getCurrentShape() {
return mCurrentShape;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//指定View的宽高
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) {
super.onDraw(canvas);
int center = getWidth() / 2;
switch (mCurrentShape) {
case CIRCLE:
//画圆
mPaint.setColor(ContextCompat.getColor(getContext(), android.R.color.holo_blue_dark));
canvas.drawCircle(center, center, center, mPaint);
break;
case RECTANGLE:
//画正方形
mPaint.setColor(ContextCompat.getColor(getContext(), android.R.color.holo_red_dark));
canvas.drawRect(0, 0, getRight(), getBottom(), mPaint);
break;
case TRIANGLE:
//用Path画三角形
mPaint.setColor(ContextCompat.getColor(getContext(), android.R.color.holo_green_dark));
//指定path的起点
mPath.moveTo(getWidth() / 2, 0);
mPath.lineTo(0, (float) (getWidth() / 2 * Math.sqrt(3)));
mPath.lineTo(getWidth(), (float) (getWidth() / 2 * Math.sqrt(3)));
canvas.drawPath(mPath, mPaint);
break;
}
}
/**
* 轮询改变当前View绘制的形状
*/
public void changeShape() {
switch (mCurrentShape) {
case CIRCLE:
mCurrentShape = Shape.RECTANGLE;
break;
case RECTANGLE:
mCurrentShape = Shape.TRIANGLE;
break;
case TRIANGLE:
mCurrentShape = Shape.CIRCLE;
break;
}
invalidate();
}
}
2.布局文件 layout_loading_view.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<com.xinrui.headsettest.view.ShapeView
android:id="@+id/shapeview"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginBottom="90dp" />
<View
android:id="@+id/shadowview"
android:layout_width="33dp"
android:layout_height="6dp"
android:background="@drawable/loading_shadow" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="正在加载中,请稍候..." />
</LinearLayout>
3.项目中运用
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import com.xinrui.headsettest.view.ShapeView;
public class LoadingViewActivity extends Activity {
private ShapeView mShapeView;
private View mShadowView;
boolean isStopAnimation = false;
float mTranslateDistance =80.0f;
long mAnimateTime = 500;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_loading_view);
initLayout();
}
/**
*加载布局,初始化控件
*/
private void initLayout() {
mShapeView = findViewById(R.id.shapeview);
mShadowView = findViewById(R.id.shadowview);
//开启动画
mShadowView.post(new Runnable() {
@Override
public void run() {
startDropAnimation();
}
});
}
/**
* 定义 下落动画 和 阴影缩小动画
*/
private void startDropAnimation() {
if (isStopAnimation) {
return;
}
//下落的动画
ObjectAnimator mTranslateAnimation = ObjectAnimator.ofFloat(mShapeView, "translationY", 0, mTranslateDistance);
mTranslateAnimation.setInterpolator(new AccelerateInterpolator());
//阴影缩小动画
ObjectAnimator mScaleAnimation = ObjectAnimator.ofFloat(mShadowView, "scaleX", 1f, 0.4f);
AnimatorSet mAnimatorSet = new AnimatorSet();
mAnimatorSet.playTogether(mTranslateAnimation, mScaleAnimation);
mAnimatorSet.setDuration(mAnimateTime);
mAnimatorSet.setInterpolator(new AccelerateInterpolator());
mAnimatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mShapeView.changeShape();
startUpAnimation();
}
});
mAnimatorSet.start();
}
/**
* 定义 弹起动画 和 阴影放大动画
*/
private void startUpAnimation() {
if (isStopAnimation) {
return;
}
//弹起的动画
ObjectAnimator mTranslateAnimation = ObjectAnimator.ofFloat(mShapeView, "translationY", mTranslateDistance, 0);
//阴影放大的动画
ObjectAnimator mScaleAnimation = ObjectAnimator.ofFloat(mShadowView, "scaleX", 0.4f, 1f);
AnimatorSet mAnimatorSet = new AnimatorSet();
mAnimatorSet.playTogether(mTranslateAnimation, mScaleAnimation);
mAnimatorSet.setDuration(mAnimateTime);
mAnimatorSet.setInterpolator(new DecelerateInterpolator());
mAnimatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
//弹起时旋转
startRotateAnimation();
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
startDropAnimation();
}
});
mAnimatorSet.start();
}
//旋转动画
private void startRotateAnimation() {
if (isStopAnimation) {
return;
}
ObjectAnimator mRotateAnimation = null;
switch (mShapeView.getCurrentShape()) {
case CIRCLE:
case RECTANGLE:
mRotateAnimation = ObjectAnimator.ofFloat(mShapeView, "rotation", 0, 180);
break;
case TRIANGLE:
mRotateAnimation = ObjectAnimator.ofFloat(mShapeView, "rotation", 0, -120);
break;
}
mRotateAnimation.setDuration(mAnimateTime);
mRotateAnimation.start();
}
}