android 通过贝塞尔曲线 实现爱心点赞功能:
  ValueAnimatior:
核心功能:
    已知起点p0, 终p3,中间点 p1、p2  通过贝塞尔曲线 计算路径中各个点
案例1:  重力抛物线  
案例2:  爱心点赞功能

核心代码:LoveLayout 

package mk.denganzhi.com.zhiwenku;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.animation.ValueAnimator.AnimatorUpdateListener;import android.content.Context;import android.graphics.PointF;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.util.Log;import android.widget.ImageView;import android.widget.RelativeLayout;import mk.denganzhi.com.zhiwenku.BezierEvaluator;import mk.denganzhi.com.zhiwenku.R;public class LoveLayout extends RelativeLayout {    Drawable[] drawables = new Drawable[3];    private Random random = new Random();    private int dHeight;    private int dWidth;    private LayoutParams params;    private int mWidth;    private int mHeight;    public LoveLayout(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }    public LoveLayout(Context context) {        super(context);        init();    }    public LoveLayout(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        // 必须在测量完毕以后才知道控件高度、和宽度        mWidth = getMeasuredWidth();        mHeight = getMeasuredHeight();    }    private void init() {        //准备图片集合        drawables[0] = getResources().getDrawable(R.drawable.red);        drawables[1] = getResources().getDrawable(R.drawable.yellow);        drawables[2] = getResources().getDrawable(R.drawable.blue);        //得到图片的原始高度        dWidth = drawables[0].getIntrinsicWidth();        dHeight = drawables[0].getIntrinsicHeight();        params = new LayoutParams(dWidth, dHeight);        //将iv添加到父容器底部、水平居中位置        params.addRule(CENTER_HORIZONTAL);        params.addRule(ALIGN_PARENT_BOTTOM);    }    // 1. 第一步:  绘制ImageView 心形    public void addLoveIcon(){        //添加心形,并开始执行动画        final ImageView iv = new ImageView(getContext());        iv.setImageDrawable(drawables[random.nextInt(3)]);        //将iv添加到父容器底部、水平居中位置        iv.setLayoutParams(params);        addView(iv);        //开始属性动画:平移、透明度渐变、缩放动画        AnimatorSet set = getAnimator(iv);        //监听动画执行完毕,将iv移除或者复用        set.addListener(new AnimatorListenerAdapter() {            @Override            public void onAnimationEnd(Animator animation) {                super.onAnimationEnd(animation);                removeView(iv);            }        });        set.start();    }    // 得到一个iv的动画集合    private AnimatorSet getAnimator(ImageView iv) {        //平移、透明度渐变、缩放动画        //1.alpha动画        ObjectAnimator alpha = ObjectAnimator.ofFloat(iv, "alpha", 0.3f,1f);        //2.缩放动画        ObjectAnimator scaleX = ObjectAnimator.ofFloat(iv, "scaleX", 0.3f,1f);        ObjectAnimator scaleY = ObjectAnimator.ofFloat(iv, "scaleY", 0.3f,1f);        //三个动画同时执行        AnimatorSet enter = new AnimatorSet();        enter.setDuration(600);        enter.playTogether(alpha,scaleX,scaleY);//enter.setTarget(iv);        //设置平移的曲线动画---贝塞尔曲线        // 2. 第二步启动估值器        ValueAnimator bezierAnimator = getBezierValueAnimator(iv);        AnimatorSet set = new AnimatorSet();        //同时依次执行 实现属性动画        set.playSequentially(enter,bezierAnimator);        set.setTarget(iv);        return set;    }    //得到一个贝塞尔曲线动画    private ValueAnimator getBezierValueAnimator(final ImageView iv) {        //根据贝塞尔公式确定四个点(起始点p0,拐点1p1,拐点2p2,终点p3)        PointF pointF0 = new PointF((mWidth-dWidth)/2, mHeight-dHeight);        PointF pointF3 = new PointF(random.nextInt(mWidth), 0);        PointF pointF1 = getPointF(1);        PointF pointF2 = getPointF(2);        BezierEvaluator evaluator = new BezierEvaluator(pointF1,pointF2);        ValueAnimator animator = ValueAnimator.ofObject(evaluator, pointF0,pointF3);        animator.addUpdateListener(new AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                PointF pointF = (PointF) animation.getAnimatedValue();//                iv.setX(pointF.x);//                iv.setY(pointF.y);                iv.setX(pointF.x);                iv.setY(pointF.y);                Log.e("denganzhi1","坐标是:x"+ pointF.x +"  y:" + pointF.y);                iv.setAlpha(1-animation.getAnimatedFraction());//1~0 百分比            }        });        animator.setDuration(10000);        return animator;    }    private PointF getPointF(int i) {        PointF pointF = new PointF();        pointF.x = random.nextInt(mWidth);        if(i==1){            pointF.y = random.nextInt(mHeight/2)+mHeight/2;        }else{            pointF.y = random.nextInt(mHeight/2);        }        return pointF;    }}

 估值器:BezierEvaluator

package mk.denganzhi.com.zhiwenku;import android.animation.TypeEvaluator;import android.graphics.PointF;public class BezierEvaluator implements TypeEvaluator {private PointF pointF1;private PointF pointF2;public BezierEvaluator(PointF pointF1, PointF pointF2) {// TODO Auto-generated constructor stubthis.pointF1 = pointF1;this.pointF2 = pointF2;}@Overridepublic PointF evaluate(float t, PointF point0, PointF point3) {// b(t)=p0*(1-t)*(1-t)*(1-t)+3*p1*t*(1-t)*(1-t)+3*p2*t*t*(1-t)+p3*t*t*tPointF point = new PointF();point.x = point0.x*(1-t)*(1-t)*(1-t)+3*pointF1.x*t*(1-t)*(1-t)+3*pointF2.x*t*t*(1-t)+point3.x*t*t*t;point.y = point0.y*(1-t)*(1-t)*(1-t)+3*pointF1.y*t*(1-t)*(1-t)+3*pointF2.y*t*t*(1-t)+point3.y*t*t*t;return point;}}

 

MainActivity代码,使用控件:

package mk.denganzhi.com.zhiwenku;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;public class MainActivity extends AppCompatActivity {    private LoveLayout loveLayout;    MyBazierLayout  myBazierLayout;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        loveLayout = (LoveLayout)findViewById(R.id.loveLayout);        myBazierLayout = findViewById(R.id.loveLayout2);    }    public void  start(View view){        loveLayout.addLoveIcon();      //  myBazierLayout.addLoveIcon();    }    public void translate(View view) {     //   myBazierLayout.translateFun();    }}

 MainActivity 的xml布局

                

效果图功能: 

  源码地址:https://download.csdn.net/download/dreams_deng/12255079 

归纳:使用贝塞尔公式绘制曲线路径

package mk.denganzhi.com.zhiwenku;import android.animation.ValueAnimator;import android.content.Context;import android.graphics.PointF;import android.graphics.drawable.BitmapDrawable;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.view.WindowManager;import android.widget.ImageButton;import android.widget.ImageView;public class TestActivity extends AppCompatActivity {    ImageButton mybtn;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_test);        mybtn = (ImageButton) findViewById(R.id.mybtn);    }  boolean isFlag=false;    public void startAnimation(View view) {        WindowManager wm = (WindowManager) this                .getSystemService(Context.WINDOW_SERVICE);        final int width = wm.getDefaultDisplay().getWidth();        int height = wm.getDefaultDisplay().getHeight();        float startX= mybtn.getLeft();        float startY =mybtn.getTop();        PointF pointF0 = new PointF(startX, startY);        PointF pointF2 = new PointF(startX-50,startY-10);        PointF pointF3 = new PointF(startX-300,startY-500);                // 贝塞尔公式        PointF pointF4 = new PointF(width/2-mybtn.getWidth()/2,height/2-mybtn.getHeight()/2);        BezierEvaluator evaluator = new BezierEvaluator(pointF2,pointF3);        Log.e("denganzhi","startx:"+startX+"  startY:"+startY);        ValueAnimator animator = ValueAnimator.ofObject(evaluator, pointF0,pointF4);        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                PointF pointF = (PointF) animation.getAnimatedValue();//                iv.setX(pointF.x);//                iv.setY(pointF.y);                int scaleBeiShu= (width)/mybtn.getWidth();                mybtn.setX(pointF.x);                mybtn.setY(pointF.y);                Log.e("denganzhi1","坐标是:x"+ pointF.x +"  y:" + pointF.y +" scaleBeiShu:"+scaleBeiShu);                if(pointF.x<350){                    if(!isFlag){                        mybtn.setImageDrawable(new BitmapDrawable());/** *  .scaleY(2) :  放大到2倍 *  scaleYBy(1):  在原来基础上放大1倍,累加过程 * *  scrollTo *  scrollBy */                        mybtn.animate()                                .scaleYBy(1)                                .scaleXBy(scaleBeiShu)                                .setDuration(3000);                        isFlag=true;                    }                }           //     mybtn.setAlpha(1-animation.getAnimatedFraction());//1~0 百分比            }        });        animator.setDuration(1000);        animator.start();    }}

activity_test 布局:

<?xml version="1.0" encoding="utf-8"?>        

效果:

 直接起点,终点, 中间2个点就可以使用贝塞尔曲线,绘制绘制轨迹

 问题就是:不知道它的点,知道点以后才知道轨迹 

更多相关文章

  1. android animation
  2. Android让帧动画在结束时消失
  3. Android分享界面制作(底部滑出动画)
  4. Android(安卓)ActionBar中的按钮添加旋转动画
  5. 一个不错的启动菜单显示屏动画效果
  6. android特效展示一:ListView
  7. android 动画之Scroller
  8. Android中Activity跳转和切换动画
  9. Android(安卓)中 PopupWindow的用法 汇总

随机推荐

  1. Android中自定义对话框小结
  2. Android: How to Capture Screen in Ging
  3. popwindow动画显示消失,activity切换动画
  4. Android(安卓)调用系统的分享[完美实现同
  5. Android基础知识总结(转载)
  6. 安卓4.X系统 增加蓝牙接收文件类型
  7. Android(安卓)代码设置Color的几种方式
  8. Android中自定义对话框小结
  9. android studio在编辑时出现如Failed to
  10. Android(安卓)Studio无法在线更新