始终相信一句话:书读百遍,其义自见。代码敲多了,自然而然就明白了。加油!
效果图如下:
1、加载动画效果分析:
1.1自定义一个图形变换的控件(WaitingAnim)用于由圆形、正方形、三角形相互变换。
1.2写改动画禁止状态的布局,用户加载到自定义ViewGroup中去。
1.3自定义ViewGroup实现动画
2、废话少说,上代码:
2.1自定义WaitingAnim代码如下:
public class WaitingAnim extends View {
private int mCircleColor= Color.BLUE;
private int mSquareColor = Color.GREEN;
private int mTriangleColor = Color.RED;
private Shape mCurrentShape=Shape.Circle;
private Paint mPaint;
private Path mPath;
public WaitingAnim(Context context) {
this(context,null);
}
public WaitingAnim(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.WaitingAnim);
mCircleColor=array.getColor(R.styleable.WaitingAnim_CircleColor,mCircleColor);
mSquareColor=array.getColor(R.styleable.WaitingAnim_SquareColor,mSquareColor);
mTriangleColor=array.getColor(R.styleable.WaitingAnim_TriangleColor,mTriangleColor);
array.recycle();
init();
}
public WaitingAnim(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(mCircleColor);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
/*测量模式*/
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
/*测量尺寸*/
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
//widthMode==MeasureSpec.AT_MOST 说明width height在布局中设置得是wrap_content
if (widthMode==MeasureSpec.AT_MOST||heightMode==MeasureSpec.AT_MOST){
widthSize=20;
heightSize=20;
}
/*如果用户设置宽高不一致时*/
if (widthSize!=heightSize){
widthSize=widthSize>heightSize?heightSize:widthSize;
heightSize=widthSize>heightSize?heightSize:widthSize;
}
setMeasuredDimension(widthSize,heightSize);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
switch (mCurrentShape){
/*画圆*/
case Circle:
mPaint.setColor(mCircleColor);
canvas.drawCircle(getWidth()/2,getHeight()/2,getWidth()/2,mPaint);
break;
/*画矩形*/
case Square:
mPaint.setColor(mSquareColor);
Rect rect = new Rect(0,0,getWidth(),getHeight());
canvas.drawRect(rect,mPaint);
break;
/*画三角形*/
case Triangle:
// 画三角 Path 画路线
mPaint.setColor(Color.RED);
if (mPath == null) {
// 画路径
mPath = new Path();
mPath.moveTo(getWidth() / 2, 0);
mPath.lineTo(0, (float) ((getWidth()/2)*Math.sqrt(3)));
mPath.lineTo(getWidth(), (float) ((getWidth()/2)*Math.sqrt(3)));
// path.lineTo(getWidth()/2,0);
mPath.close();// 把路径闭合
}
canvas.drawPath(mPath, mPaint);
break;
}
}
public void exchange(){
switch (mCurrentShape){
case Circle:
mCurrentShape=Shape.Square;
break;
case Square:
mCurrentShape=Shape.Triangle;
break;
case Triangle:
mCurrentShape=Shape.Circle;
break;
}
invalidate();
}
public enum Shape{
Circle,Square,Triangle;
}
public Shape getmCurrentShape() {
return mCurrentShape;
}
}
2.2自定义ViewGroup(LoadingView)代码如下:
public class LoadingView extends LinearLayout {
private WaitingAnim waitingAnim;
private View shade;
private int mTranslationDistance;
private int AnimaDuration=350;
private boolean isStopAnimator=false;
public LoadingView(Context context) {
this(context,null);
}
public LoadingView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public LoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initLayout(context);
}
/**
* 初始化加载
*/
private void initLayout(Context context) {
//1、写好的布局,加载进来
//1.1实例化View
// View loadView = inflate(getContext(),R.layout.ui_loadingview,null);
//this代表把这个布局加载到LoadingView中
View loadView = inflate(getContext(),R.layout.ui_loadingview,this);
waitingAnim = (WaitingAnim) findViewById(R.id.waitingAnim);
shade = (View) findViewById(R.id.shade);
mTranslationDistance=Densityuitl.dip2px(context,80);
/*写在里表示在onResume里面执行*/
post(new Runnable() {
@Override
public void run() {
startFallAninmator();
}
});
/*写在这里表示在onCreatView里面执行*/
// startFallAninmator();
}
/**
* 下落的动画
*/
public void startFallAninmator() {
Log.e("TAG","startFallAninmator");
if (isStopAnimator) {
return;
}
//下落的位移动画
ObjectAnimator translationAninamator=ObjectAnimator.ofFloat(waitingAnim,"translationY",0,mTranslationDistance);
// translationAninamator.setDuration(AnimaDuration);
// translationAninamator.start();
//中间阴影缩小
ObjectAnimator scaleAnimator = ObjectAnimator.ofFloat(shade,"scaleX",1f,0.3f);
// scaleAnimator.setDuration(AnimaDuration);
// scaleAnimator.start();
//动画的集合
AnimatorSet set = new AnimatorSet();
set.setDuration(AnimaDuration);
set.playTogether(translationAninamator,scaleAnimator);
/*匀加速*/
set.setInterpolator(new AccelerateInterpolator());
//下落完成之后就开始上抛了
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
/*切换图片*/
waitingAnim.exchange();
startUpAnimator();
}
});
set.start();
}
private void startUpAnimator() {
if (isStopAnimator) {
return;
}
//上抛的位移动画
ObjectAnimator translationAninamator=ObjectAnimator.ofFloat(waitingAnim,"translationY",mTranslationDistance,0);
// translationAninamator.setDuration(AnimaDuration);
// translationAninamator.start();
//中间阴影缩小
ObjectAnimator scaleAnimator = ObjectAnimator.ofFloat(shade,"scaleX",0.3f,1f);
// scaleAnimator.setDuration(AnimaDuration);
// scaleAnimator.start();
/*动画的集合*/
AnimatorSet set = new AnimatorSet();
set.setDuration(AnimaDuration);
set.playTogether(translationAninamator,scaleAnimator);
/*匀减速*/
set.setInterpolator(new DecelerateInterpolator());
//下落完成之后就开始上抛了
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
startFallAninmator();
}
@Override
public void onAnimationStart(Animator animation) {
startRotationAnimator();
}
});
set.start();
}
/**
* 旋转的动画
*/
private void startRotationAnimator() {
if (isStopAnimator) {
return;
}
ObjectAnimator rotationAnimator = null;
switch (waitingAnim.getmCurrentShape()){
case Circle:
case Square:
rotationAnimator=ObjectAnimator.ofFloat(waitingAnim,"rotation",0,180);
break;
case Triangle:
rotationAnimator=ObjectAnimator.ofFloat(waitingAnim,"rotation",0,-180);
break;
}
rotationAnimator.setDuration(AnimaDuration);
rotationAnimator.setInterpolator(new DecelerateInterpolator());
rotationAnimator.start();
}
@Override
public void setVisibility(int visibility) {
super.setVisibility(View.INVISIBLE);//不再去摆放和计算,少走系统的源码
/*清除动画*/
waitingAnim.clearAnimation();
shade.clearAnimation();
/*从父布局已移除*/
ViewGroup parent = (ViewGroup) getParent();
if (parent!=null){
parent.removeView(this);
parent.removeAllViews();
}
isStopAnimator=true;
}
}
最后,在Activity使用该自定义控件就好了,要是想让该自定义控件消失不显示,直接设置该控件为GONE。该自定义控件重写了setVisibility()方法。在方法中实现清除动画等操作。