最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android 利用三階貝塞爾曲線繪制運(yùn)動軌跡的示例

 更新時間:2018年03月08日 08:35:11   作者:涉水者  
本篇文章主要介紹了Android 利用三階貝塞爾曲線繪制運(yùn)動軌跡的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

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

實(shí)現(xiàn)點(diǎn)贊效果,自定義起始點(diǎn)以及運(yùn)動軌跡

效果圖:

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);

    // 初始化插補(bǔ)器
    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();
    //手動設(shè)置寬高
    dWidth = dip2px(getContext(), 40);
    dHeight = dip2px(getContext(), 40);
    lp = new LayoutParams(dWidth, dHeight);
    //設(shè)置view控件的起始位置
//    lp.addRule(CENTER_HORIZONTAL, TRUE);// 這里的TRUE 要注意 不是true
    lp.addRule(ALIGN_PARENT_RIGHT, TRUE);
    lp.addRule(ALIGN_PARENT_BOTTOM, TRUE);

  }

  /**
   * dp轉(zhuǎn)px值
   */
  private int dip2px(Context context, float dpValue) {
    float scale = context.getResources().getDisplayMetrics().density;
    return (int) (dpValue * scale + 0.5f);
  }

  /**
   * 進(jìn)場動畫,三種同時播放
   * 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) {
    // 初始化貝塞爾估值器
    //隨機(jī)產(chǎn)生兩個點(diǎn),以確定一條3階貝塞爾曲線
    BezierEvaluator evaluator = new BezierEvaluator(getPointF(2), getPointF(1));
    // 起點(diǎn)在底部中心位置,終點(diǎn)在底部隨機(jī)一個位置,改變new PointF()中值來改變起始位置
//    ValueAnimator animator = ValueAnimator.ofObject(evaluator, new PointF((mWidth - dWidth) /
//        2, mHeight - dHeight), new PointF(random.nextInt(getWidth()), 0));
    // 起點(diǎn)在右下角位置,終點(diǎn)在左上角位置
    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動畫,根據(jù)運(yùn)動距離改變透明度
//        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都是隨機(jī),因此可以產(chǎn)生n多種軌跡
    pointF.x = random.nextInt(mWidth);//0~loveLayout.Width

    //為了美觀,建議盡量保證P2在P1上面,那怎么做呢??
    //只需要將該布局的高度分為上下兩部分,讓p1只能在下面部分范圍內(nèi)變化(1/2height~height),讓p2只能在上面部分范圍內(nèi)變化(0~1/2height),因?yàn)樽鴺?biāo)系是倒著的;

    //0~loveLayout.Height/2
    if (i == 1) {
      pointF.y = random.nextInt(mHeight / 2) + mHeight / 2;//P1點(diǎn)Y軸坐標(biāo)變化
    } else if (i == 2) {//P2點(diǎn)Y軸坐標(biāo)變化
      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());
    // 隨機(jī)選一個愛心
    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;
  }
}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 淺談Android textview文字對齊換行的問題

    淺談Android textview文字對齊換行的問題

    下面小編就為大家分享一篇淺談Android textview文字對齊換行的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • Android的八種對話框的實(shí)現(xiàn)代碼示例

    Android的八種對話框的實(shí)現(xiàn)代碼示例

    本篇文章主要介紹了Android的八種對話框的實(shí)現(xiàn)代碼示例,這里整理了詳細(xì)的代碼,非常具有實(shí)用價值,有需要的小伙伴可以參考下。
    2017-09-09
  • Android M(6.x)使用OkHttp包解析和發(fā)送JSON請求的教程

    Android M(6.x)使用OkHttp包解析和發(fā)送JSON請求的教程

    Android 6.0采用的SPDY支持HTTP上GZIP壓縮的傳輸,這使得OkHttp包的功能能夠進(jìn)一步被利用,本文我們來總結(jié)一下Android M(6.0)使用OkHttp包解析和發(fā)送JSON請求的教程
    2016-07-07
  • ViewModel中StateFlow和SharedFlow單元測試使用詳解

    ViewModel中StateFlow和SharedFlow單元測試使用詳解

    這篇文章主要為大家介紹了ViewModel中StateFlow和SharedFlow單元測試使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • 淺談Android開發(fā)Webview的Loading使用效果

    淺談Android開發(fā)Webview的Loading使用效果

    這篇文章主要為大家介紹了淺談Android開發(fā)Webview的Loading使用效果詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • Eclipse NDK遷移到Android Studio的方法示例

    Eclipse NDK遷移到Android Studio的方法示例

    本篇文章主要介紹了Eclipse NDK遷移到Android Studio的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • Android編程之TextView的字符過濾功能分析

    Android編程之TextView的字符過濾功能分析

    這篇文章主要介紹了Android編程之TextView的字符過濾功能,結(jié)合實(shí)例形式分析了TextView控件實(shí)現(xiàn)字符過濾的相關(guān)技巧與使用方法,需要的朋友可以參考下
    2016-01-01
  • 詳解如何在Android studio中更新sdk版本和build-tools版本

    詳解如何在Android studio中更新sdk版本和build-tools版本

    這篇文章主要介紹了如何在Android studio中更新sdk版本和build-tools版本,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Android編程之四種Activity加載模式分析

    Android編程之四種Activity加載模式分析

    這篇文章主要介紹了Android編程之四種Activity加載模式,簡要分析了Android編程中涉及的Activity的四種加載模式,具有一定參考借鑒價值,需要的朋友可以參考下
    2016-01-01
  • 簡單實(shí)用的Android UI微博動態(tài)點(diǎn)贊效果

    簡單實(shí)用的Android UI微博動態(tài)點(diǎn)贊效果

    這篇文章主要為大家詳細(xì)介紹了簡單實(shí)用的Android UI微博動態(tài)點(diǎn)贊效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10

最新評論

略阳县| 邹城市| 长垣县| 华亭县| 内黄县| 芮城县| 祁门县| 民和| 合川市| 桂阳县| 济源市| 淮安市| 海淀区| 泰来县| 胶南市| 广安市| 云阳县| 秦皇岛市| 叶城县| 专栏| 屯门区| 台湾省| 兰坪| 深水埗区| 益阳市| 连州市| 仙游县| 榆林市| 汉川市| 泗洪县| 正镶白旗| 明星| 得荣县| 巴林右旗| 锦屏县| 遵义县| 正镶白旗| 德保县| 萨迦县| 昆明市| 长阳|