请问:简书怎么可以把代码格式调整?我贴出来换格式了。你们直接去Github下载工程!
效果分析:
可以基本分为两个部分,具体看实现
1.点击START ANIM按钮的时候,底部出现一个ImageView它的drawable是随机的,并伴着缩放和透明度的变化;
2.等第一步的动画执行完后开始向上移动,移动的轨迹是一个曲线,我们要用到贝塞尔曲线公式去不断的改变图片的位置。
效果实现:
1.自定义控件Releativielayout,绘制出爱心控件
2.移动是一个曲线:配合估值器+贝塞尔曲线
3.自定义估值器封装:贝塞尔估值器
4.贝塞尔曲线实现:三阶贝塞尔:4个点确定,有一个公式
p1和P2的确定点公式
p0 :起点可以确定
p1:比p0的y值大
p2 要比p1的y值大
p3:终点可以确定
整个曲线我们可以简单的理解为这个S路曲线,S也会有四个点:
1.P0最下面的这个起点,也就是我们刚刚添加进来最下方居中的这个点 ((mWidth - mDrawableWidth) / 2, mHeight- mDrawableHeight)
2.P1是下半部分抛物线的顶点,这里是随机;
3.P2是上半部分抛物线的顶点,这里也是随机;
4.P3是最上面位置的终点(mRandom.nextInt(mWidth), 0),也就是最上面的这个点;
5.t的范围是[0,1],我们确定这四个点之后就开始套公式了:
5.view通过改变x和y的值。x和y就是一个点,通过动画得到(估值器得到)。点通过贝塞尔曲线
图片设置x,y,alpha。
因为估值器里面的定义是一个点。
@Override
public PointFevaluate(float t, PointF p0, PointF p3) {
PointF pointF=new PointF();
pointF.x=p0.x*(1-t)*(1-t)*(1-t)
+3*p1.x*t*(1-t)*(1-t)
+3*p2.x*t*(t)*(1-t)
+p3.x*t*t*t;
pointF.y=p0.y*(1-t)*(1-t)*(1-t)
+3*p1.y*t*(1-t)*(1-t)
+3*p2.y*t*(t)*(1-t)
+p3.y*t*t*t;
return pointF;
PointF pointF=(PointF) valueAnimator.getAnimatedValue();//这个返回值就是估值器的值
ValueAnimator objectAnimator = ObjectAnimator.ofObject(new LoveTypeEvalutor(point1, point2), point0, point3);
objectAnimator.setDuration(2000);
objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
Log.d("dddd","onAnimationUpdate");
PointF pointF=(PointF) valueAnimator.getAnimatedValue();//这个返回值就是估值器的值
float r=valueAnimator.getAnimatedFraction();//这个值
imageView.setX(pointF.x);//setx:指的是谁
imageView.setY(pointF.y);
imageView.setAlpha(1-r+0.2f);
}
});
先说一下这种效果都用到了哪些东西:
1.自定义View的一些基础;
2.随机数的使用;
3.插补器的使用;
4.属性动画的一些高级用法
5.贝塞尔曲线应用到属性动画
public class DouyinPraiseextends RelativeLayout {
Randomrandom;
public DouyinPraise(Context context) {
this(context, null);
}
public DouyinPraise(Context context, AttributeSet attrs) {
this(context, attrs, 0);
random =new Random();
}
public DouyinPraise(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private int width;
private int height;
private int imageWidth, imageHeight;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);
}
public void addImageView() {
RelativeLayout.LayoutParams layoutParams =new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.addRule(ALIGN_PARENT_BOTTOM);
layoutParams.addRule(CENTER_HORIZONTAL);
ImageView imageView =new ImageView(getContext());//如何得到view,inlat。可以直接new
imageView.setImageResource(R.mipmap.ic_launcher);//如何获取图片的宽高
imageWidth = imageView.getWidth();
imageHeight = imageView.getHeight();
addView(imageView, layoutParams);
AnimatorSet animatorSet = getObjectAnimator(imageView);
animatorSet.start();
}
private AnimatorSetgetObjectAnimator(ImageView view) {
AnimatorSet animatorSetAll =new AnimatorSet();
AnimatorSet animatorSet =new AnimatorSet();
ObjectAnimator objectAnimatorAlpha = ObjectAnimator.ofFloat(view, "alpha", 0.3f, 1.0f);
ObjectAnimator objectAnimatorScalex = ObjectAnimator.ofFloat(view, "scaleX", 0.1f, 1.0f);
ObjectAnimator objectAnimatorScaleY = ObjectAnimator.ofFloat(view, "scaleY", 0.1f, 1.0f);
animatorSet.playTogether(objectAnimatorAlpha, objectAnimatorScalex, objectAnimatorScaleY);
animatorSet.setDuration(500);
animatorSetAll.playSequentially(animatorSet, getBziAnimation(view));//播放动画
animatorSetAll.start();
return animatorSet;
}
/***
* 三次方公式
* @return
*/
private AnimatorgetBziAnimation(ImageView imageView) {
PointF point0 =new PointF(width /2, height);
PointF point1 =new PointF(new Random().nextInt(width), random.nextInt(height/2));
PointF point2 =new PointF(new Random().nextInt(width), random.nextInt(height/2)+height/2);
PointF point3 =new PointF(new Random().nextInt(width), 0);
ValueAnimator objectAnimator = ObjectAnimator.ofObject(new LoveTypeEvalutor(point1, point2), point0, point3);
objectAnimator.setDuration(2000);
objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
Log.d("dddd","onAnimationUpdate");
PointF pointF=(PointF) valueAnimator.getAnimatedValue();//这个返回值就是估值器的值
float r=valueAnimator.getAnimatedFraction();//这个值
imageView.setX(pointF.x);//setx:指的是谁
imageView.setY(pointF.y);
imageView.setAlpha(1-r+0.2f);
}
});
objectAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationEnd(Animator animator) {
removeView(imageView);
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
return objectAnimator;
}
public class LoveTypeEvalutorimplements TypeEvaluator {
private PointFp1,p2;
public LoveTypeEvalutor(PointF p1, PointF p2) {
this.p1 = p1;
this.p2 = p2;
}
@Override
public PointFevaluate(float t, PointF p0, PointF p3) {
PointF pointF=new PointF();
pointF.x=p0.x*(1-t)*(1-t)*(1-t)
+3*p1.x*t*(1-t)*(1-t)
+3*p2.x*t*(t)*(1-t)
+p3.x*t*t*t;
pointF.y=p0.y*(1-t)*(1-t)*(1-t)
+3*p1.y*t*(1-t)*(1-t)
+3*p2.y*t*(t)*(1-t)
+p3.y*t*t*t;
return pointF;
}
}
https://blog.csdn.net/qq_16624353/article/details/93376688
网友评论