标签: androidapp图片动画
2016-01-29 20:41
4596人阅读
收藏
举报
分类:
Android(110)
版权声明:本文为博主原创文章,博客地址:http://blog.csdn.net/qq_26787115,未经博主允许不得转载。
目录(?)[+]
Android特效专辑(八)——实现心型起泡飞舞的特效,让你的APP瞬间暖心
马上也要放年假了,家里估计会没网,更完这篇的话,可能要到年后了,不过在此期间会把更新内容都保存在本地,这样有网就可以发表了,也是极好的,今天说的这个特效,原本是Only上的一个小彩蛋的,我们来看看图片
只要我点击了Only这个字,下面就开始上升起起泡了,这个实现起来其实就是一个欲盖弥彰的动画而已,准备好三张颜色不一样的心型图片咯,这样的话,我们就开始动手来写一写吧! 首先新建一个工程——HeartFaom 准备工作就是准备图片咯
BezierEvaluator
单位转换以及计算轨迹
package com.lgl.heartfaom;
import android.animation.TypeEvaluator;
import android.graphics.PointF;
public class BezierEvaluator implements TypeEvaluator<PointF> {
private PointF pointF1;
private PointF pointF2;
public BezierEvaluator(PointF pointF1, PointF pointF2) {
this.pointF1 = pointF1;
this.pointF2 = pointF2;
}
@Override
public PointF evaluate(float time, PointF startValue, PointF endValue) {
float timeLeft =
1.0f - time;
PointF point =
new PointF();
point.x = timeLeft * timeLeft * timeLeft * (startValue.x) +
3
* timeLeft * timeLeft * time * (pointF1.x) +
3 * timeLeft
* time * time * (pointF2.x) + time * time * time * (endValue.x);
point.y = timeLeft * timeLeft * timeLeft * (startValue.y) +
3
* timeLeft * timeLeft * time * (pointF1.y) +
3 * timeLeft
* time * time * (pointF2.y) + time * time * time * (endValue.y);
return point;
}
}
1234567891011121314151617181920212223242526272829303132
1234567891011121314151617181920212223242526272829303132
PeriscopeLayout
贝塞尔曲线的计算以及气泡的实现
package com.lgl.heartfaom;
import java.util.Random;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.RelativeLayout;
public class PeriscopeLayout extends RelativeLayout {
private Interpolator line =
new LinearInterpolator();
private Interpolator acc =
new AccelerateInterpolator();
private Interpolator dce =
new DecelerateInterpolator();
private Interpolator accdec =
new AccelerateDecelerateInterpolator();
private Interpolator[] interpolators;
private int mHeight;
private int mWidth;
private LayoutParams lp;
private Drawable[] drawables;
private Random random =
new Random();
private int dHeight;
private int dWidth;
public PeriscopeLayout(Context context) {
super(context);
init();
}
public PeriscopeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PeriscopeLayout(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public PeriscopeLayout(Context context, AttributeSet attrs,
int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
drawables =
new Drawable[
3];
Drawable red = getResources().getDrawable(R.drawable.pl_red);
Drawable yellow = getResources().getDrawable(R.drawable.pl_yellow);
Drawable blue = getResources().getDrawable(R.drawable.pl_blue);
drawables[
0] = red;
drawables[
1] = yellow;
drawables[
2] = blue;
dHeight = red.getIntrinsicHeight();
dWidth = red.getIntrinsicWidth();
lp =
new LayoutParams(dWidth, dHeight);
lp.addRule(CENTER_HORIZONTAL, TRUE);
lp.addRule(ALIGN_PARENT_BOTTOM, TRUE);
interpolators =
new Interpolator[
4];
interpolators[
0] = line;
interpolators[
1] = acc;
interpolators[
2] = dce;
interpolators[
3] = accdec;
}
@Override
protected void onMeasure(
int widthMeasureSpec,
int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = getMeasuredWidth();
mHeight = getMeasuredHeight();
}
public void addHeart() {
ImageView imageView =
new ImageView(getContext());
imageView.setImageDrawable(drawables[random.nextInt(
3)]);
imageView.setLayoutParams(lp);
addView(imageView);
Animator set = getAnimator(imageView);
set.addListener(
new AnimEndListener(imageView));
set.start();
}
private Animator
getAnimator(View target) {
AnimatorSet set = getEnterAnimtor(target);
ValueAnimator bezierValueAnimator = getBezierValueAnimator(target);
AnimatorSet finalSet =
new AnimatorSet();
finalSet.playSequentially(set);
finalSet.playSequentially(set, bezierValueAnimator);
finalSet.setInterpolator(interpolators[random.nextInt(
4)]);
finalSet.setTarget(target);
return finalSet;
}
private AnimatorSet
getEnterAnimtor(
final View target) {
ObjectAnimator alpha = ObjectAnimator.ofFloat(target, View.ALPHA,
0.2f,
1f);
ObjectAnimator scaleX = ObjectAnimator.ofFloat(target, View.SCALE_X,
0.2f,
1f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(target, View.SCALE_Y,
0.2f,
1f);
AnimatorSet enter =
new AnimatorSet();
enter.setDuration(
500);
enter.setInterpolator(
new LinearInterpolator());
enter.playTogether(alpha, scaleX, scaleY);
enter.setTarget(target);
return enter;
}
private ValueAnimator
getBezierValueAnimator(View target) {
BezierEvaluator evaluator =
new BezierEvaluator(getPointF(
2),
getPointF(
1));
ValueAnimator animator = ValueAnimator.ofObject(evaluator,
new PointF(
(mWidth - dWidth) /
2, mHeight - dHeight),
new PointF(random.nextInt(getWidth()),
0));
animator.addUpdateListener(
new BezierListenr(target));
animator.setTarget(target);
animator.setDuration(
3000);
return animator;
}
/**
* 获取中间的两个 点
*
* @param scale
*/
private PointF
getPointF(
int scale) {
PointF pointF =
new PointF();
pointF.x = random.nextInt((mWidth -
100));
pointF.y = random.nextInt((mHeight -
100)) / scale;
return pointF;
}
private class BezierListenr implements ValueAnimator.AnimatorUpdateListener {
private View target;
public BezierListenr(View target) {
this.target = target;
}
@Override
public void onAnimationUpdate(ValueAnimator animation) {
PointF pointF = (PointF) animation.getAnimatedValue();
target.setX(pointF.x);
target.setY(pointF.y);
target.setAlpha(
1 - animation.getAnimatedFraction());
}
}
private class AnimEndListener extends AnimatorListenerAdapter {
private View target;
public AnimEndListener(View target) {
this.target = target;
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
removeView((target));
}
}
}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
activity_main.xml
布局的实现
<RelativeLayout xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"#000" >
<Button
android:id=
"@+id/btn_start"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_centerInParent=
"true"
android:text=
"飞舞吧!" />
<
com.lgl.heartfaom.PeriscopeLayout
android:id=
"@+id/periscope"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent" >
</
com.lgl.heartfaom.PeriscopeLayout>
</RelativeLayout>
1234567891011121314151617181920
1234567891011121314151617181920
MainActivity
接着就是怎么去使用它了
package com.lgl.heartfaom;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
private Button btn_start;
private PeriscopeLayout periscopeLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
periscopeLayout = (PeriscopeLayout) findViewById(R.id.periscope);
btn_start = (Button) findViewById(R.id.btn_start);
btn_start.setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
periscopeLayout.addHeart();
}
});
}
}
123456789101112131415161718192021222324252627282930313233
123456789101112131415161718192021222324252627282930313233
好,我们接下来就可以运行一下试试实际上的效果了
觉得不错的点个赞哦!
Demo下载地址:http://download.csdn.net/detail/qq_26787115/9422603