乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      直播送花特效

       萬皇之皇 2018-01-03



      引言


      這是作者第一個CSDN的文章,寫的不好的地方,請大家多多提提意見哈。今天寫的文章是關(guān)于動畫的,前幾天公司要求我寫一個觀看直播點擊送花與主播收到花朵的效果。



      主播接到花朵的效果 



      觀眾送花效果


      思路


      好了看見了效果之后想必大家都應(yīng)該知道肯定想到要用Animator(4.0增加的動畫類),想必很多人都接觸到了,但是剛接觸Android的兄弟可能就沒怎么使用這個。網(wǎng)上有很多文章對這個類的介紹,所以這里就不注重解釋了。


      主要的思路如下:

      1.確定起點(主播是隨機起點)與終點位置;

      2.為其添加動畫特效,從起點運動到終點,然后銷毀View。


      代碼


      我就不拿以前的代碼了,我一邊敲一邊說,首先創(chuàng)建個項目(不多說了哈),然后我們創(chuàng)建一個工具類FlowerAnimation.java。我們就對這個類瘋狂擼吧。


      固定起點->固定終點特效實現(xiàn)


          private static final String TAG = 'FlowerAnimation';

          //上下文

          private Context mContext;

          //生成的View添加在的ViewGroup

          private ViewGroup rootView;

          private ViewGroup.LayoutParams layoutParams;


          //資源文件

          private Drawable[] drawables;

          //插值器

          private Interpolator[] interpolators;


      上面代碼的注釋很清楚了,大家一看就明白了    ,TGA這是為了測試打印log使用的(AS快捷鍵-logt+enter)。


          public FlowerAnimation(Context mContext, ViewGroup rootView) {

               this.mContext = mContext;

               this.rootView = rootView;

               init();

          }   


          private void init() {

              drawables = new Drawable[8];

              drawables[0] = mContext.getResources().getDrawable(R.mipmap.flower_01);

              drawables[1] = mContext.getResources().getDrawable(R.mipmap.flower_02);

              drawables[2] = mContext.getResources().getDrawable(R.mipmap.flower_03);

              drawables[3] = mContext.getResources().getDrawable(R.mipmap.flower_04);

              drawables[4] = mContext.getResources().getDrawable(R.mipmap.flower_05);

              drawables[5] = mContext.getResources().getDrawable(R.mipmap.flower_06);

              drawables[6] = mContext.getResources().getDrawable(R.mipmap.flower_07);

              drawables[7] = mContext.getResources().getDrawable(R.mipmap.flower_08);


              interpolators = new Interpolator[4];

              interpolators[0] = new LinearInterpolator();//線性

              interpolators[1] = new AccelerateInterpolator();//加速

              interpolators[2] = new DecelerateInterpolator();//減速

              interpolators[3] = new AccelerateDecelerateInterpolator();//先加速后減速


              layoutParams = new ViewGroup.LayoutParams(DensityUtil.dip2px(mContext, 50), DensityUtil.dip2px(mContext, 50));

          }


      上面就是一些初始化的東西了,大家看看就好。


      準(zhǔn)備工作做好了,我們寫最主要的方法,那就是生成動畫了,上代碼


      /**

          /**

           * 開啟動畫

           *

           * @param view   執(zhí)行動畫的view

           * @param startP 起點 如果傳null 默認(rèn)從view位置開始

           * @param stopP  終點

           */

          public void startAnim(@NonNull final View view, @Nullable PointF startP, @NonNull PointF stopP) {

              if (startP == null) {

                  startP = new PointF(view.getX(), view.getY());

              }

              //透明度變化

              ObjectAnimator animatorAlpha = ObjectAnimator.ofFloat(view, 'alpha', 0, 1);

              animatorAlpha.setDuration(200);

              //位移動畫

              ObjectAnimator animatorX = ObjectAnimator.ofFloat(view, 'translationX', startP.x, stopP.x);

              animatorX.setDuration(1000);

              ObjectAnimator animatorY = ObjectAnimator.ofFloat(view, 'translationY', startP.y, stopP.y);

              animatorY.setDuration(1000);

              //生成動畫集合

              AnimatorSet set = new AnimatorSet();

              //開啟透明度動畫然后執(zhí)行位移動畫

              set.play(animatorAlpha).before(animatorX).with(animatorY);

              //加入植入器

              set.setInterpolator(interpolators[rand.nextInt(interpolators.length)]);

              //添加動畫監(jiān)聽事件 為了移除view 防止造成oom

              set.addListener(new AnimatorListenerAdapter() {

                  @Override

                  public void onAnimationEnd(Animator animation) {

                      super.onAnimationEnd(animation);

                      rootView.removeView(view);

                  }

              });

              set.start();

          }


          /**

           * 開啟動畫

           *

           * @param view  執(zhí)行動畫的view

           * @param stopP 終點

           */

          public void startAnim(@NonNull final View view, @NonNull PointF stopP) {

              startAnim(view, null, stopP);

          }


          /**

           * 添加花朵

           *

           * @param startPoint

           */

          public void addFlower(@NonNull PointF startPoint, @NonNull PointF stopP) {

              ImageView flower = new ImageView(mContext);

              flower.setX(startPoint.x);

              flower.setY(startPoint.y);

              Drawable drawable = drawables[rand.nextInt(drawables.length)];

              flower.setBackground(drawable);

              rootView.addView(flower, layoutParams);

              startAnim(flower, startPoint, stopP);

          }


      好了,我們看到,生成這個動畫需要View(這是必然的)終點也是必然,起點就無所謂了。每一步的注釋都寫的很清楚,ObjectAnimator這個類功能很強大(4.0+)。下面開始寫個界面來看看效果啦。界面代碼我直接上代碼 不講解了!對了有關(guān)于view位置的問題大家直接去看別的文章吧,很多的哈,我這里貼個我認(rèn)為不錯的:


      http://blog.csdn.net/jason0539/article/details/42743531


      public class MainActivity extends AppCompatActivity implements View.OnClickListener {

          //終點坐標(biāo)imageView

          private ImageView endFlowerIv;

          //開啟動畫按鈕 也是起點坐標(biāo)

          private Button startFlowerBt;

          private FlowerAnimation flowerAnimation;


          @Override

          protected void onCreate(Bundle savedInstanceState) {

              super.onCreate(savedInstanceState);

              setContentView(R.layout.activity_main);

              initView();

          }


          private void initView() {

              endFlowerIv = (ImageView) findViewById(R.id.main_end_flower_iv);

              startFlowerBt = (Button) findViewById(R.id.main_start_flower_bt);

              startFlowerBt.setOnClickListener(this);

              flowerAnimation = new FlowerAnimation(this, (ViewGroup) findViewById(R.id.activity_main));

          }



          @Override

          public void onClick(View v) {

              flowerAnimation.addFlower(new PointF(v.getX(), v.getY()), new PointF(endFlowerIv.getX(), endFlowerIv.getY()));

          }


          android:id='@+id/activity_main'

          android:layout_width='match_parent'

          android:layout_height='match_parent'>


          <>

              android:id='@+id/main_end_flower_iv'

              android:layout_width='50dp'

              android:layout_height='50dp'

              android:layout_gravity='center_horizontal'

              android:background='@mipmap/flower_01' />



          <>

              android:id='@+id/main_start_flower_bt'

              android:layout_width='50dp'

              android:layout_height='50dp'

              android:layout_gravity='center_horizontal|bottom'

              android:background='@mipmap/flower_01' />


      下面是效果圖



      隨即起點->固定終點特效實現(xiàn)


      這個問題想必大家在上面的基礎(chǔ)上就完全可以寫出來 直接把代碼貼上來與效果


           /**

           * 添加花朵 隨即生成起點(rootView范圍)

           *

           * @param stopP 終點

           */

          public void addFlowerByScope(@NonNull PointF stopP) {

              float x = rand.nextFloat() * rootView.getWidth();

              float y = rand.nextFloat() * rootView.getHeight();

              addFlower(new PointF(x, y), stopP);

          }


           /**

           * 添加花朵 隨即生成起點

           *

           * @param stopP  終點

           * @param scopeP 范圍  隨即生成的點將會按照此范圍隨即取值

           */

          public void addFlowerByScope(@NonNull PointF stopP, @NonNull PointF scopeP) {

              float x = rand.nextFloat() * scopeP.x;

              float y = rand.nextFloat() * scopeP.y;

              addFlower(new PointF(x, y), stopP);

          }


      界面的點擊事件換成對應(yīng)的方法


      @Override

          public void onClick(View v) {

              flowerAnimation.addFlowerByScope(new PointF(endFlowerIv.getX(), endFlowerIv.getY()));

          }




      到此,你會發(fā)現(xiàn)已經(jīng)完成主播接到花朵的效果(就是隨即從各個地方出現(xiàn)花朵飛到花朵出)以上就是主播界面顯示的效果了。代碼比較簡單,下面實現(xiàn)觀眾點擊送花的效果。


      思路呢?其實跟上面差不多,觀眾送花的效果類似固定點到固定點的效果(類似哈哈),為什么說類似呢?因為從圖上可以看到,路徑是不同的,很明顯發(fā)現(xiàn) 觀眾送花的效果的路徑是隨即的(亂飄)。這里就引出來了ValueAnimator 這個東西你會發(fā)現(xiàn)他是ObjectAnimator的父類。


      ValueAnimator 顧名思義哈 就是針對數(shù)值的動畫,他能幫我完成什么呢?

      比如我我想讓一個數(shù)值從0-10 時間是10s,我們來寫寫看我們新建一個ValueAnimActivity.java來實現(xiàn)觀眾的界面,順便在里面測試demo。


      public class ValueAnimActivity extends AppCompatActivity implements View.OnClickListener {

          private TextView countTv;

          private Button startBt;


          @Override

          protected void onCreate(@Nullable Bundle savedInstanceState) {

              super.onCreate(savedInstanceState);

              setContentView(R.layout.activity_value);

              initView();

          }


          private void initView() {

              countTv = (TextView) findViewById(R.id.value_count_tv);

              startBt = (Button) findViewById(R.id.value_start_bt);

              startBt.setOnClickListener(this);

          }


          @Override

          public void onClick(View v) {

              startValueAnim();

          }


          private void startValueAnim() {

              //從0-10 時間10s

              ValueAnimator countAnim = ValueAnimator.ofInt(0, 10)

                      .setDuration(10000);

              countAnim.setInterpolator(new LinearInterpolator());

              countAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

                  @Override

                  public void onAnimationUpdate(ValueAnimator animation) {

                      countTv.setText(animation.getAnimatedValue().toString());

                  }

              });

              countAnim.start();

          }


      }


          android:layout_width='match_parent'

          android:layout_height='match_parent'

          android:orientation='vertical'>


          <>

              android:id='@+id/value_count_tv'

              android:layout_width='wrap_content'

              android:layout_height='wrap_content'

              android:layout_gravity='center'

              android:textSize='30dp'  />


          <>

              android:id='@+id/value_start_bt'

              android:layout_width='wrap_content'

              android:layout_height='wrap_content'

              android:layout_gravity='center_horizontal|bottom'

              android:text='start' />


      代碼跟布局都很簡單 我們簡單寫了個ValueAnimator的例子 直接看效果




      那怎么實現(xiàn)我們的效果呢?這里就用到一個方法


      public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values)


      他能讓一個對象進(jìn)行改變,那怎么改變呢?其實隨便是什么?都要跟時間掛鉤(重要),為什么跟時間掛鉤,這還要解釋么?onAnimationUpdate回調(diào)的方法你打印log你會發(fā)現(xiàn)他會調(diào)用N多次,10S回調(diào)了496次,可想而知我們對象改變也會跟時間有關(guān)系,那么我們看看TypeEvaluator(類型評估者)這是一個接口,我們來看看它要我們實現(xiàn)的方法

         

      public T evaluate(float fraction, T startValue, T endValue);


       這個方法看到之后,后面2個我肯定知道是什么意思,動畫的起始值,那第一個是什么?(英文翻譯是分?jǐn)?shù))咱們說過肯定跟時間有關(guān)的,那么這個是不是就是時間呢?看了官方解釋之后,這個意思就是當(dāng)前完成動畫的百分比。

          還不懂?那好我們還看看官方有沒有默認(rèn)給我們實現(xiàn)的類,一看,有很多,我們直接拿來一個用看看效果,上代碼


      private void startValueAnim1() {

              //從0-10 時間10s

              ValueAnimator countAnim = ValueAnimator.ofObject(new IntEvaluator() {

                  @Override

                  public Integer evaluate(float fraction, Integer startValue, Integer endValue) {

                      Log.e(TAG, 'evaluate() called with: fraction = [' + fraction + '], startValue = [' + startValue + '], endValue = [' + endValue + ']');

                      return super.evaluate(fraction, startValue, endValue);

                  }

              }, 0, 10)

                      .setDuration(10000);

              countAnim.setInterpolator(new LinearInterpolator());

              countAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

                  @Override

                  public void onAnimationUpdate(ValueAnimator animation) {

                      countTv.setText(animation.getAnimatedValue().toString());

                  }

              });

              countAnim.start();

          }




      下面重點來了,如果要實現(xiàn)這種效果,那就要一個公式(貝塞爾曲線)這個當(dāng)初我也是一頭霧水啊,先不管直接套用公式就行了(先上一個圖片) 




      這個公式只要理解我們給出4個點,他就算出當(dāng)前的點。這里有4個點,但是我們只有2個點,另外2個點是為了控制曲線的走向,我隨即取就可以咯。好了,我們先不管點,先把TypeEvaluator寫好


       /**

           * 自定義的估值器

           */

          public static class MyTypeEvaluator implements TypeEvaluator {

              private PointF pointF1, pointF2;


              public MyTypeEvaluator(PointF pointF1, PointF pointF2) {

                  this.pointF1 = pointF1;

                  this.pointF2 = pointF2;

              }


              @Override

              public PointF evaluate(float fraction, PointF startValue, PointF endValue) {

                  float timeLeft = 1.0f - fraction;

                  PointF pointF = new PointF();//結(jié)果

                  pointF.x = timeLeft * timeLeft * timeLeft * (startValue.x)

                          + 3 * timeLeft * timeLeft * fraction * (pointF1.x)

                          + 3 * timeLeft * fraction * fraction * (pointF2.x)

                          + fraction * fraction * fraction * (endValue.x);


                  pointF.y = timeLeft * timeLeft * timeLeft * (startValue.y)

                          + 3 * timeLeft * timeLeft * fraction * (pointF1.y)

                          + 3 * timeLeft * fraction * fraction * (pointF2.y)

                          + fraction * fraction * fraction * (endValue.y);

                  return pointF;

              }

          }


      只是簡單的套用公式,就不用多講了直接復(fù)制就好,要不然能看的眼花。


      下面放上取中間控制點的代碼



      注釋也簡單,我覺得很好弄懂,下面上主要代碼







      下面是最終效果啦



      到這里差不多可以結(jié)束了。想必大家可能會問,如果動畫還沒執(zhí)行完就退出了,那就內(nèi)存泄漏了啊。所以我再來個方法。




      好了,跑起來沒有問題了。


      源碼地址:https://github.com/CFlingchen/CSDN1



      • 來自:CSDN-CF凌晨

      • http://blog.csdn.net/qq_27495349/article/details/53008975

      • 程序員大咖整理發(fā)布,轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)


        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多