您的位置:首页 > 移动开发 > Android开发

Android动画之属性动画

2017-12-01 17:10 204 查看
总归是逮着机会,稍微慢一点。在过去的很长一段时间内,都是在业务逻辑的复杂变化中挣扎。没有技术上的成长,内心还是蛮恐慌的。一不小心,又带有了些许的情绪在里面。。。。。

一、属性动画单个动画

1,布局文件添加动画作用目标

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.future.animatordemo.MainActivity">

<ImageView
android:id="@+id/content_iv"
android:layout_width="150dp"
android:layout_height="150dp"
android:src="@mipmap/koala" />

</RelativeLayout>

2,获取控件并执行动画

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
/**
* 图片
*/
private ImageView contentIV;

/**
* 自定义控件
*/
private PointView createView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_bak);
initView();
initAnimation();
initListener();
}

/**
* 初始化控件
*/
private void initView() {
contentIV = findViewById(R.id.content_iv);
}

/**
* 初始化动画
*/
private void initAnimation() {
rotateAnimation();
//alpahAnimation();

}

private void initListener() {
contentIV.setOnClickListener(this);
}

/**
* 旋转动画
*/
private void rotateAnimation() {
ObjectAnimator anim = ObjectAnimator.ofFloat(contentIV, "rotation", 0f, 360f);
anim.setDuration(1000);
anim.start();
}

/**
* 透明渐变动画
*/
private void alpahAnimation() {
ObjectAnimator anim = ObjectAnimator.ofFloat(contentIV, "alpha", 1.0f, 0.8f, 0.6f, 0.4f, 0.2f, 0.0f);
anim.setRepeatCount(-1);
anim.setRepeatMode(ObjectAnimator.REVERSE);
anim.setDuration(2000);
anim.start();
}

@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.content_iv:
Toast.makeText(MainActivity.this, "戳中朕心了~_~", Toast.LENGTH_SHORT).show();
break;
}
}

}

执行效果:
旋转动画:



透明渐变动画:



二、属性动画的合集

添加以下方法,并在onCreate()中调用

private void setAnimation() {
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(contentIV, "alpha", 1.0f, 0.5f, 0.8f, 1.0f);
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(contentIV, "scaleX", 0.0f, 1.0f);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(contentIV, "scaleY", 0.0f, 2.0f, 1.0f);
ObjectAnimator rotateAnim = ObjectAnimator.ofFloat(contentIV, "rotation", 0, 360);
ObjectAnimator transXAnim = ObjectAnimator.ofFloat(contentIV, "translationX", 100, 400);
ObjectAnimator transYAnim = ObjectAnimator.ofFloat(contentIV, "translationY", 100, 750, 300, 600);
AnimatorSet set = new AnimatorSet();
set.playTogether(alphaAnim, scaleXAnim, scaleYAnim, rotateAnim, transXAnim, transYAnim);//叠加在一起运动
// set.playSequentially(alphaAnim, scaleXAnim, scaleYAnim, rotateAnim, transXAnim, transYAnim);
set.setDuration(3000);
set.start();
}

其中playTogether()将所有的动画组合在一起,同时开启动画。playSequentially()将动画顺序执行,当上一个动画没有结束时,下一个动画不会开始执行。
展示效果:



三、属性动画的监听

代码修改,添加动画运行更新监听,并在更新方法中刷新控件状态。使用了Layout()方法。

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
/**
* 图片
*/
private ImageView contentIV;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initListener();
}

/**
* 初始化控件
*/
private void initView() {
contentIV = findViewById(R.id.content_iv);
}

private void initListener() {
contentIV.setOnClickListener(this);
}

@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.content_iv:
Toast.makeText(MainActivity.this, "戳中朕心了~_~", Toast.LENGTH_SHORT).show();
break;
}
}

public void startAnimatorAnimation(View view) {
ValueAnimator animator = ValueAnimator.ofInt(0, 400);
animator.setDuration(1000);
animator.setInterpolator(new DecelerateInterpolator());

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (int) animation.getAnimatedValue();
contentIV.layout(curValue, curValue, curValue + contentIV.getWidth(), curValue + contentIV.getHeight());
}
});

animator.setStartDelay(1000);
animator.start();
}
}

备注:
相比于补间动画,属性动画直接修改了控件属性。直接反馈就是点击事件在补间动画时,只有在控件开始的位置执行才有效,其他地方无效。而属性动画在运行过程中,控件所在位置就是响应事件响应位置。

展示效果:



四、属性动画的应用

依据以上学习内容,制作自定义控件,展示属性动画的应用。

自定义控件实现如下:

public class PointView extends View {

public static final float RADIUS = 20f;

private Point currentPoint;

private Paint mPaint;
private Paint linePaint;

private AnimatorSet animSet;
private TimeInterpolator interpolatorType = new LinearInterpolator();

/**
* 实现关于color 的属性动画
*/
private int color;
private float radius = RADIUS;

public PointView(Context context) {
super(context);
init();
}

public PointView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}

public PointView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}

public int getColor() {
return color;
}

public void setColor(int color) {
this.color = color;
mPaint.setColor(this.color);
}

public float getRadius() {
return radius;
}

public void setRadius(float radius) {
this.radius = radius;
}

private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.TRANSPARENT);

linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
linePaint.setColor(Color.BLACK);
linePaint.setStrokeWidth(5);
}

@Override
protected void onDraw(Canvas canvas) {
if (currentPoint == null) {
currentPoint = new Point((int) RADIUS, (int) RADIUS);
drawCircle(canvas);
} else {
drawCircle(canvas);
}

drawLine(canvas);
}

private void drawLine(Canvas canvas) {
canvas.drawLine(10, getHeight() / 2, getWidth(), getHeight() / 2, linePaint);
canvas.drawLine(10, getHeight() / 2 - 150, 10, getHeight() / 2 + 150, linePaint);
canvas.drawPoint(currentPoint.x, currentPoint.y, linePaint);

}

public void startAnimation() {
Point startP = new Point((int) RADIUS, (int) RADIUS);
// Point endP = new Point(getWidth() - (int) RADIUS, getHeight() - (int) RADIUS);
Point endP = new Point(MainApplication.getApplication().getWidth() - (int) RADIUS, MainApplication.getApplication().getHeight() - (int) RADIUS);
final ValueAnimator valueAnimator = ValueAnimator.ofObject(new PointSinEvaluator(), startP, endP);
valueAnimator.setRepeatCount(-1);
valueAnimator.setRepeatMode(ValueAnimator.REVERSE);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
currentPoint = (Point) animation.getAnimatedValue();
postInvalidate();
}
});

//
ObjectAnimator animColor = ObjectAnimator.ofObject(this, "color", new ArgbEvaluator(), Color.GREEN,
Color.YELLOW, Color.BLUE, Color.WHITE, Color.RED);
animColor.setRepeatCount(-1);
animColor.setRepeatMode(ValueAnimator.REVERSE);

ValueAnimator animScale = ValueAnimator.ofFloat(20f, 80f, 60f, 10f, 35f, 55f, 10f);
animScale.setRepeatCount(-1);
animScale.setRepeatMode(ValueAnimator.REVERSE);
animScale.setDuration(5000);
animScale.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
radius = (float) animation.getAnimatedValue();
}
});

animSet = new AnimatorSet();
animSet.play(valueAnimator).with(animColor).with(animScale);
animSet.setDuration(5000);
animSet.setInterpolator(interpolatorType);
animSet.start();

}

private void drawCircle(Canvas canvas) {
float x = currentPoint.x;
float y = currentPoint.y;
canvas.drawCircle(x, y, radius, mPaint);
}

public void setInterpolatorType(int type) {
switch (type) {
case 1:
interpolatorType = new BounceInterpolator();
break;
case 2:
interpolatorType = new AccelerateDecelerateInterpolator();
break;
case 3:
interpolatorType = new DecelerateInterpolator();
break;
case 4:
interpolatorType = new AnticipateInterpolator();
break;
case 5:
interpolatorType = new LinearInterpolator();
break;
case 6:
interpolatorType = new LinearOutSlowInInterpolator();
break;
case 7:
interpolatorType = new OvershootInterpolator();
default:
interpolatorType = new LinearInterpolator();
break;
}
}

@TargetApi(Build.VERSION_CODES.KITKAT)
public void pauseAnimation() {
if (animSet != null) {
animSet.pause();
}
}

public void stopAnimation() {
if (animSet != null) {
animSet.cancel();
this.clearAnimation();
}
}
}


XML文件中使用:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.future.animatordemo.MainActivity">

<ImageView
android:id="@+id/content_iv"
android:layout_width="150dp"
android:layout_height="150dp"
android:src="@mipmap/koala" />

<com.future.animatordemo.view.PointView
android:id="@+id/create_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

</RelativeLayout>

初始化控件并使用控件:

public class MainActivityBak extends AppCompatActivity implements View.OnClickListener {
/**
* 图片
*/
private ImageView contentIV;

/**
* 自定义控件
*/
private PointView createView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_bak);
initView();
initAnimation();
initListener();
}

/**
* 初始化控件
*/
private void initView() {
contentIV = findViewById(R.id.content_iv);
createView = findViewById(R.id.create_view);
}

/**
* 初始化动画
*/
private void initAnimation() {
setAnimation();
createView.startAnimation();
}

private void initListener() {
contentIV.setOnClickListener(this);
}

private void setAnimation() {
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(contentIV, "alpha", 1.0f, 0.5f, 0.8f, 1.0f);
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(contentIV, "scaleX", 0.0f, 1.0f);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(contentIV, "scaleY", 0.0f, 2.0f, 1.0f);
ObjectAnimator rotateAnim = ObjectAnimator.ofFloat(contentIV, "rotation", 0, 360);
ObjectAnimator transXAnim = ObjectAnimator.ofFloat(contentIV, "translationX", 100, 400);
ObjectAnimator transYAnim = ObjectAnimator.ofFloat(contentIV, "translationY", 100, 750, 300, 600);
AnimatorSet set = new AnimatorSet();
set.playTogether(alphaAnim, scaleXAnim, scaleYAnim, rotateAnim, transXAnim, transYAnim);//叠加在一起运动
// set.playSequentially(alphaAnim, scaleXAnim, scaleYAnim, rotateAnim, transXAnim, transYAnim);
set.setDuration(3000);
set.start();
}

@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.content_iv:
Toast.makeText(MainActivity.this, "戳中朕心了~_~", Toast.LENGTH_SHORT).show();
break;
}
}
}

展示效果:



源码传送门

有人请教我哆啦A梦和大雄最后有没有在一起,我便问他,许仙最后有没有和白蛇在一起。生之有涯‘最后'如何,也不过是蜿蜒个几十年的一件小事,而大事是他们,和我们曾经在一起过。 

所有被千夫所指的困难,都是为了淘汰掉懦夫!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息