日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

直播送花特效

發布時間:2024/1/1 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 直播送花特效 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

點擊上方“程序員大咖”,選擇“置頂公眾號”

關鍵時刻,第一時間送達!


引言


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



主播接到花朵的效果?



觀眾送花效果


思路


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


主要的思路如下:

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

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


代碼


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


固定起點->固定終點特效實現


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

? ? }


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


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


/**

? ? /**

? ? ?* 開啟動畫

? ? ?*

? ? ?* @param view ? 執行動畫的view

? ? ?* @param startP 起點 如果傳null 默認從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();

? ? ? ? //開啟透明度動畫然后執行位移動畫

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

? ? ? ? //加入植入器

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

? ? ? ? //添加動畫監聽事件 為了移除view 防止造成oom

? ? ? ? set.addListener(new AnimatorListenerAdapter() {

? ? ? ? ? ? @Override

? ? ? ? ? ? public void onAnimationEnd(Animator animation) {

? ? ? ? ? ? ? ? super.onAnimationEnd(animation);

? ? ? ? ? ? ? ? rootView.removeView(view);

? ? ? ? ? ? }

? ? ? ? });

? ? ? ? set.start();

? ? }


? ? /**

? ? ?* 開啟動畫

? ? ?*

? ? ?* @param view ?執行動畫的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+)。下面開始寫個界面來看看效果啦。界面代碼我直接上代碼 不講解了!對了有關于view位置的問題大家直接去看別的文章吧,很多的哈,我這里貼個我認為不錯的:


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


public class MainActivity extends AppCompatActivity implements View.OnClickListener {

? ? //終點坐標imageView

? ? private ImageView endFlowerIv;

? ? //開啟動畫按鈕 也是起點坐標

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

? ? }


<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

? ? android:id="@+id/activity_main"

? ? android:layout_width="match_parent"

? ? android:layout_height="match_parent">


? ? <ImageView

? ? ? ? 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" />



? ? <Button

? ? ? ? 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" />

</FrameLayout>


下面是效果圖



隨即起點->固定終點特效實現


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


? ? ?/**

? ? ?* 添加花朵 隨即生成起點(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);

? ? }


界面的點擊事件換成對應的方法


@Override

? ? public void onClick(View v) {

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

? ? }




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


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


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

比如我我想讓一個數值從0-10 時間是10s,我們來寫寫看我們新建一個ValueAnimActivity.java來實現觀眾的界面,順便在里面測試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();

? ? }


}


<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

? ? android:layout_width="match_parent"

? ? android:layout_height="match_parent"

? ? android:orientation="vertical">


? ? <TextView

? ? ? ? android:id="@+id/value_count_tv"

? ? ? ? android:layout_width="wrap_content"

? ? ? ? android:layout_height="wrap_content"

? ? ? ? android:layout_gravity="center"

? ? ? ? android:textSize="30dp" ?/>


? ? <Button

? ? ? ? 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" />

</FrameLayout>


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




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


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


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

? ?

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


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

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


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

? ? }




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




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


?/**

? ? ?* 自定義的估值器

? ? ?*/

? ? public static class MyTypeEvaluator implements TypeEvaluator<PointF> {

? ? ? ? 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();//結果

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

? ? ? ? }

? ? }


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


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



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







下面是最終效果啦



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




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


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



  • 來自:CSDN-CF凌晨

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

  • 程序員大咖整理發布,轉載請聯系作者獲得授權

【點擊成為Python大神】

總結

以上是生活随笔為你收集整理的直播送花特效的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。