1. 程式人生 > >Android 貝塞爾曲線,撒花了

Android 貝塞爾曲線,撒花了

這裡寫圖片描述
撒花了
這裡寫圖片描述
佈局

<?xml version="1.0" encoding="utf-8"?>
<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:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context="com.df.demo.demo.MainActivity">
<com.df.demo.demo.BezierLayout android:layout_width="match_parent"
android:layout_height="match_parent">
</com.df.demo.demo.BezierLayout> </RelativeLayout>

Activity

public class BezierLayout extends RelativeLayout {
    Drawable[] mDrawables=new Drawable[]{getResources().getDrawable(R.drawable.apple),
            getResources().getDrawable(R.drawable.banana),getResources().getDrawable(R.drawable.love),getResources().getDrawable(R.drawable.dimon)};
    private
LayoutParams mParams; private int mDrawWidth; private int mDrawHeight; private int mHeight; private int mWidth; private Random mRandom=new Random(); public BezierLayout(Context context) { this(context,null); } public BezierLayout(Context context, AttributeSet attrs) { this(context, attrs,0); } public BezierLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init(){ mDrawWidth=mDrawables[2].getIntrinsicWidth(); mDrawHeight=mDrawables[2].getIntrinsicHeight(); } @Override public boolean onTouchEvent(MotionEvent event) { //對按下事件監聽,獲取點選的位置 if(event.getAction()== MotionEvent.ACTION_DOWN){ PointF point=new PointF(); point.set(event.getX(),event.getY()); //每點選一次新增一個禮物 addPresent(point); return true; } return super.onTouchEvent(event); } private void addPresent(PointF point) { mParams=new LayoutParams(mDrawWidth,mDrawHeight); //設定左邊距為落下點-圖片寬度的一半(這是為了讓圖片的中心為落下手指位置) mParams.leftMargin=(int)(point.x-mDrawWidth/2); //設定上邊距為落下點-圖片高度的一半(這是為了讓圖片的中心為落下手指位置) mParams.topMargin=(int)(point.y-mDrawHeight/2); ImageView imageView=new ImageView(getContext()); //隨機設定圖片 imageView.setImageDrawable(mDrawables[mRandom.nextInt(4)]); //設定動畫 AnimatorSet animatorset=getObjectAnimator(imageView,point); animatorset.setTarget(imageView); addView(imageView,mParams); animatorset.start(); } public AnimatorSet getObjectAnimator(final ImageView imageview, PointF point) { //動畫:放大+透明度+貝塞爾曲線 //放大+透明度 ObjectAnimator scalexanimator=ObjectAnimator.ofFloat(imageview,"scaleX",0.2f,0.5f); ObjectAnimator scaleyanimator=ObjectAnimator.ofFloat(imageview,"scaleY",0.2f,0.5f); ObjectAnimator alphaanimator=ObjectAnimator.ofFloat(imageview,"aplpha",1.0f,0f); AnimatorSet set=new AnimatorSet(); set.playTogether(scalexanimator,scaleyanimator,alphaanimator); set.setDuration(1000); //貝塞爾曲線 ValueAnimator bezierAnimator=getBezierAnimator(imageview,point); //將放大+透明度+貝塞爾曲線三種動畫新增在一起 AnimatorSet sets=new AnimatorSet(); sets.playTogether(set,bezierAnimator); //設定動畫的物件與時間 sets.setTarget(imageview); sets.setDuration(3000); return sets; } public ValueAnimator getBezierAnimator(final ImageView imageview,PointF point) { //貝塞爾曲線需要四個點 //起點 PointF point0=new PointF(); point0.x=point.x-mDrawWidth/2; point0.y=point.y-mDrawHeight/2; //第一個中間點 final PointF point1=getTooglePoint(1,point); //d第二個中間點 PointF point2=getTooglePoint(2,point); //最後一個點 PointF point3=new PointF(mRandom.nextInt(mWidth),0); BerzierValutor valutor=new BerzierValutor(point1,point2); ValueAnimator valueAnimator=ValueAnimator.ofObject(valutor,point0,point3); valueAnimator.setDuration(2000); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { PointF point= (PointF) animation.getAnimatedValue(); imageview.setX(point.x); imageview.setY(point.y); imageview.setAlpha(1-animation.getAnimatedFraction()); } }); return valueAnimator; } private PointF getTooglePoint(int i,PointF point) { PointF point1=new PointF(); point1.x=mRandom.nextInt(mWidth); int reactHeight=(int)(point.y/2); if(i==1){ //第一個中間點,一半以下的隨機位置 point1.y=reactHeight+mRandom.nextInt(reactHeight); }else { //第二個中間點,一半以上的隨機位置 point1.y=mRandom.nextInt(reactHeight); } return point1; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mWidth=getMeasuredWidth(); mHeight=getMeasuredHeight(); } class BerzierValutor implements TypeEvaluator<PointF> { private PointF mPoint1; private PointF mpoint2; public BerzierValutor(PointF mPoint1, PointF mpoint2) { this.mPoint1 = mPoint1; this.mpoint2 = mpoint2; } @Override public PointF evaluate(float t, PointF startValue, PointF endValue) { PointF pointf=new PointF(); //根據貝塞爾公式設定三次方貝塞爾曲線 pointf.x=startValue.x*(1-t)*(1-t)*(1-t)+3*mPoint1.x*t*(1-t)*(1-t)+3*mpoint2.x*t*t*(1-t)+endValue.x*t*t*t; pointf.y=startValue.y*(1-t)*(1-t)*(1-t)+3*mPoint1.y*t*(1-t)*(1-t)+3*mpoint2.y*t*t*(1-t)+endValue.y*t*t*t; return pointf; } } }