国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android 利用三階貝塞爾曲線繪制運動軌跡的示例

2019-10-22 18:14:31
字體:
來源:轉載
供稿:網友

本篇文章主要介紹了Android 利用三階貝塞爾曲線繪制運動軌跡的示例,分享給大家,具體如下:

實現點贊效果,自定義起始點以及運動軌跡

效果圖:

Android,貝塞爾曲線運動軌跡,三階貝塞爾曲線

xml布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  xmlns:tools="http://schemas.android.com/tools"  android:id="@+id/rl_root"  android:layout_width="match_parent"  android:layout_height="match_parent"  tools:context="stone.wshh.com.touch.MainActivity">  <stone.wshh.com.touch.MyLoveLayout    android:layout_marginBottom="100dp"    android:layout_marginRight="15dp"    android:id="@+id/love_layout"    android:layout_width="match_parent"    android:layout_height="match_parent">  </stone.wshh.com.touch.MyLoveLayout>  <Button    android:id="@+id/bt_bottom"    android:text="begin"    android:layout_alignParentBottom="true"    android:layout_centerHorizontal="true"    android:layout_marginBottom="20dp"    android:layout_width="100dp"    android:layout_height="50dp" /></RelativeLayout>

MainActivity類:

public class MainActivity extends Activity implements View.OnClickListener{  private Button btBottom;//  private WaitNoticeDialog dialog;//  public Handler handler;  private MyLoveLayout love;  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    btBottom = (Button) findViewById(R.id.bt_bottom);    love = (MyLoveLayout) findViewById(R.id.love_layout);    btBottom.setOnClickListener(this);//    handler=new IHandler(this);//    dialog = new WaitNoticeDialog(this);  }  static class IHandler extends Handler {    private WeakReference<MainActivity> ui;    IHandler(MainActivity ui) {      this.ui = new WeakReference<MainActivity>(ui);    }    @Override    public void handleMessage(Message msg) {      if(ui!=null&&ui.get()!=null){        ui.get().handleMsg(msg);      }    }  }  /**   * 線程消息處理   * @param msg   */  public void handleMsg(Message msg){    switch (msg.what) {    }  }  @Override  public void onClick(View v) {    switch (v.getId()){      case R.id.bt_bottom:        love.addHeart();        break;    }  }  @Override  protected void onDestroy() {    super.onDestroy();//    handler.removeCallbacksAndMessages(null);  }}

自定義view:MyLoveLayout

public class MyLoveLayout extends RelativeLayout {  private Drawable[] drawables;  private Interpolator[] mInterpolators;  private int dWidth, mWidth;  private int dHeight, mHeight;  private LayoutParams lp;  private Random random = new Random();  public MyLoveLayout(Context context, AttributeSet attrs) {    super(context, attrs);    //imageView位置是相對于MyLoveLayout    init();  }  @Override  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    super.onMeasure(widthMeasureSpec, heightMeasureSpec);    //得到本布局的寬高    mWidth = getMeasuredWidth();    mHeight = getMeasuredHeight();  }  private void init() {    // 初始化顯示的圖片    drawables = new Drawable[7];    drawables[0] = getResources().getDrawable(R.drawable.heart_1);    drawables[1] = getResources().getDrawable(R.drawable.heart_2);    drawables[2] = getResources().getDrawable(R.drawable.heart_3);    drawables[3] = getResources().getDrawable(R.drawable.heart_4);    drawables[4] = getResources().getDrawable(R.drawable.heart_5);    drawables[5] = getResources().getDrawable(R.drawable.heart_6);    drawables[6] = getResources().getDrawable(R.drawable.heart_7);    // 初始化插補器    mInterpolators = new Interpolator[4];    mInterpolators[0] = new LinearInterpolator();// 線性    mInterpolators[1] = new AccelerateInterpolator();// 加速    mInterpolators[2] = new DecelerateInterpolator();// 減速    mInterpolators[3] = new AccelerateDecelerateInterpolator();// 先加速后減速    // 獲取圖片寬高//    dWidth = drawables[0].getIntrinsicWidth();//    dHeight = drawables[0].getIntrinsicHeight();    //手動設置寬高    dWidth = dip2px(getContext(), 40);    dHeight = dip2px(getContext(), 40);    lp = new LayoutParams(dWidth, dHeight);    //設置view控件的起始位置//    lp.addRule(CENTER_HORIZONTAL, TRUE);// 這里的TRUE 要注意 不是true    lp.addRule(ALIGN_PARENT_RIGHT, TRUE);    lp.addRule(ALIGN_PARENT_BOTTOM, TRUE);  }  /**   * dp轉px值   */  private int dip2px(Context context, float dpValue) {    float scale = context.getResources().getDisplayMetrics().density;    return (int) (dpValue * scale + 0.5f);  }  /**   * 進場動畫,三種同時播放   * alpha透明度 (80%-0%)   * scaleX 寬度 target(20%-100%)   * scaleY 高度   * @param target   * @return   */  private AnimatorSet getEnterAnimator(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.setTarget(target);    enter.setInterpolator(new LinearInterpolator());    enter.setDuration(500).playTogether(alpha, scaleX, scaleY);    return enter;  }  private ValueAnimator getBezierValueAnimator(final View target) {    // 初始化貝塞爾估值器    //隨機產生兩個點,以確定一條3階貝塞爾曲線    BezierEvaluator evaluator = new BezierEvaluator(getPointF(2), getPointF(1));    // 起點在底部中心位置,終點在底部隨機一個位置,改變new PointF()中值來改變起始位置//    ValueAnimator animator = ValueAnimator.ofObject(evaluator, new PointF((mWidth - dWidth) ///        2, mHeight - dHeight), new PointF(random.nextInt(getWidth()), 0));    // 起點在右下角位置,終點在左上角位置    ValueAnimator animator = ValueAnimator.ofObject(evaluator, new PointF(mWidth - dWidth, mHeight - dHeight), new PointF(0, 0));    animator.setTarget(target);    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {      @Override      public void onAnimationUpdate(ValueAnimator valueAnimator) {        // 這里獲取到貝塞爾曲線計算出來的的x y值 賦值給view 這樣就能讓愛心隨著曲線走啦        PointF pointF = (PointF) valueAnimator.getAnimatedValue();        target.setX(pointF.x);        target.setY(pointF.y);        // alpha動畫,根據運動距離改變透明度//        target.setAlpha(1 - valueAnimator.getAnimatedFraction());        target.setAlpha(1 - valueAnimator.getAnimatedFraction() + 0.3f);      }    });    animator.setDuration(3000);    return animator;  }  private PointF getPointF(int i) {    PointF pointF = new PointF();    //pointF.x,pointF.y都是隨機,因此可以產生n多種軌跡    pointF.x = random.nextInt(mWidth);//0~loveLayout.Width    //為了美觀,建議盡量保證P2在P1上面,那怎么做呢??    //只需要將該布局的高度分為上下兩部分,讓p1只能在下面部分范圍內變化(1/2height~height),讓p2只能在上面部分范圍內變化(0~1/2height),因為坐標系是倒著的;    //0~loveLayout.Height/2    if (i == 1) {      pointF.y = random.nextInt(mHeight / 2) + mHeight / 2;//P1點Y軸坐標變化    } else if (i == 2) {//P2點Y軸坐標變化      pointF.y = random.nextInt(mHeight / 2);    }//    寫死的一條軌跡//    if (i == 1) {//      pointF.x=mWidth-dWidth*2;//      pointF.y = 3*dHeight;//    } else if (i == 2) {//      pointF.x=dWidth*2;//      pointF.y = mHeight -dHeight;//    }    return pointF;  }  public void addHeart() {    final ImageView imageView = new ImageView(getContext());    // 隨機選一個愛心    imageView.setImageDrawable(drawables[random.nextInt(6)]);    imageView.setLayoutParams(lp);    addView(imageView);    AnimatorSet finalSet = new AnimatorSet();    AnimatorSet enterAnimatorSet = getEnterAnimator(imageView);//入場動畫    ValueAnimator bezierValueAnimator = getBezierValueAnimator(imageView);//貝塞爾曲線路徑動畫    finalSet.playSequentially(enterAnimatorSet, bezierValueAnimator);//    finalSet.playSequentially(bezierValueAnimator);    finalSet.setInterpolator(mInterpolators[random.nextInt(4)]);    finalSet.setTarget(imageView);    finalSet.addListener(new AnimatorListenerAdapter() {      @Override      public void onAnimationEnd(Animator animation) {        super.onAnimationEnd(animation);        removeView((imageView));//刪除愛心      }    });    finalSet.start();  }}

貝塞爾估值器:BezierEvaluator

public class BezierEvaluator implements TypeEvaluator<PointF> {  private PointF mControlP1;  private PointF mControlP2;  public BezierEvaluator(PointF controlP1, PointF controlP2) {    this.mControlP1 = controlP1;    this.mControlP2 = controlP2;  }  @Override  public PointF evaluate(float time, PointF start, PointF end) {    float timeLeft = 1.0f - time;    PointF point = new PointF();    point.x = timeLeft * timeLeft * timeLeft * (start.x) + 3 * timeLeft * timeLeft * time *        (mControlP1.x) + 3 * timeLeft * time *        time * (mControlP2.x) + time * time * time * (end.x);    point.y = timeLeft * timeLeft * timeLeft * (start.y) + 3 * timeLeft * timeLeft * time *        (mControlP1.y) + 3 * timeLeft * time *        time * (mControlP2.y) + time * time * time * (end.y);    return point;  }}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 都安| 璧山县| 罗山县| 新河县| 大邑县| 宕昌县| 漳州市| 沾益县| 云龙县| 仲巴县| 深泽县| 延川县| 乐昌市| 内丘县| 瑞昌市| 长白| 昆山市| 孝感市| 米易县| 二连浩特市| 长乐市| 平和县| 铜山县| 泗阳县| 阿尔山市| 通海县| 云梦县| 宜兴市| 白朗县| 桐乡市| 潜江市| 浦东新区| 霍城县| 沾化县| 包头市| 南部县| 乃东县| 南漳县| 蚌埠市| 互助| 靖边县|