欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android實現(xiàn)簡單點贊動畫

 更新時間:2021年08月25日 10:53:06   作者:碧云天丶  
這篇文章主要為大家詳細介紹了Android實現(xiàn)簡單點贊動畫,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了Android實現(xiàn)簡單點贊動畫的具體代碼,供大家參考,具體內(nèi)容如下

思路

1、找到ActivityDecorViewRootView
2、確定點贊控件位于屏幕中的坐標(biāo)值
3、將點贊效果View加入到RootView中, 給效果View添加自己想要的動畫效果.
4、重復(fù)點擊時候, 需要將效果View先移除掉再重新加入到RootView中.

代碼

/**
 * 普通點贊效果, 點擊控件后出現(xiàn)一個View上浮
 */
public class ViewLikeUtils {
    public interface ViewLikeClickListener {
        /**
         * @param view          被點贊的按鈕
         * @param toggle        開關(guān)
         * @param viewLikeUtils 工具類本身
         */
        void onClick(View view, boolean toggle, ViewLikeUtils viewLikeUtils);
    }

    // 被點擊的按鈕
    private View mClickView;
    private View mAnimView;
    private ViewLikeClickListener mListener;
    private boolean toggle = false; // 點擊開關(guān)標(biāo)識
    private int mX; // 距離屏幕左側(cè)距離
    private int mY; // 距離屏幕頂端距離, 越往下數(shù)值越大

    /**
     * @param mClickView 被點擊的View
     * @param mAnimView  點贊后, 向上浮動的View
     * @param mListener  被點擊的View,點擊后的回調(diào)事件.
     */
    public ViewLikeUtils(View mClickView, View mAnimView, @NonNull ViewLikeClickListener mListener) {
        this.mClickView = mClickView;
        this.mAnimView = mAnimView;
        this.mListener = mListener;
        initListener();
    }

    /**
     * 設(shè)置View的監(jiān)聽
     */
    private void initListener() {
        mClickView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                if (motionEvent.getAction() == MotionEvent.ACTION_UP || motionEvent.getAction() == MotionEvent.ACTION_CANCEL) {
                    getLocation(); // 獲取被點擊View的坐標(biāo)
                    toggle = !toggle;
                    if (mListener != null) {
                        mListener.onClick(mClickView, toggle, ViewLikeUtils.this);
                    }
                    // mView.performClick();
                }
                // 正常的OnClickListener將無法調(diào)用
                return true;
            }
        });
    }

    /**
     * 獲取View在屏幕中的坐標(biāo)
     */
    private void getLocation() {
        int[] mLocation = new int[2];
        mClickView.getLocationOnScreen(mLocation);
        mX = mLocation[0];
        mY = mLocation[1];
    }

    /**
     * 開始動畫
     */
    private void startAnim(ValueAnimator valueAnimator) {
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                mAnimView.setAlpha(1 - (Float) valueAnimator.getAnimatedFraction());
                FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mAnimView.getLayoutParams();
                params.topMargin = (int) (mY - mAnimView.getMeasuredHeight() - 100 * valueAnimator.getAnimatedFraction());
                mAnimView.setLayoutParams(params);
            }
        });
        valueAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {

            }

            @Override
            public void onAnimationEnd(Animator animator) {
                removeChildView(mAnimView);
            }

            @Override
            public void onAnimationCancel(Animator animator) {

            }

            @Override
            public void onAnimationRepeat(Animator animator) {

            }
        });
        valueAnimator.start();
    }

    /**
     * 將上浮控件添加到屏幕中
     *
     * @param animview
     */
    private void addAnimView(View animview) {
        Activity activityFromView = getActivityFromView(mClickView);
        if (activityFromView != null) {
            FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
            FrameLayout mRootView = (FrameLayout) activityFromView.getWindow().getDecorView().getRootView();
            mRootView.addView(animview, params);
            // 測量浮動View的大小
            animview.measure(0, 0);
            params.topMargin = (int) (mY - animview.getMeasuredHeight());
            params.leftMargin = mX + mClickView.getMeasuredWidth() / 2 - animview.getMeasuredHeight() / 2;
            animview.setLayoutParams(params);
        }
    }

    /**
     * 開始動畫
     */
    public void startLikeAnim(ValueAnimator valueAnimator) {
        removeChildView(mAnimView);
        addAnimView(mAnimView);
        startAnim(valueAnimator);
    }

    /**
     * 獲取Activity
     *
     * @param view
     * @return
     */
    public Activity getActivityFromView(View view) {
        if (null != view) {
            Context context = view.getContext();
            while (context instanceof ContextWrapper) {
                if (context instanceof Activity) {
                    return (Activity) context;
                }
                context = ((ContextWrapper) context).getBaseContext();
            }
        }
        return null;
    }

    /**
     * 將子View從父容器中去除
     */
    private void removeChildView(View mChildView) {
        ViewGroup parentViewGroup = (ViewGroup) mChildView.getParent();
        if (parentViewGroup != null) {
            parentViewGroup.removeView(mChildView);
        }
    }
}

使用

// 效果View
val textView = TextView(this@MainActivity2)
textView.text = "+1"
textView.setTextColor(Color.RED)
textView.textSize = mBtn.textSize
// 效果View動畫
val animator = ValueAnimator.ofInt(10, 200)
animator.duration = 800
ViewLikeUtils(findViewById<Button>(R.id.btn_anim), textView) { clickView, toggle, mUtils ->
    // 開始動畫
    mUtils.startLikeAnim(animator)
}

效果

貝塞爾動畫點贊效果

思路其實差不多, 具體看代碼

public class ViewLikeBesselUtils {
    public interface ViewLikeClickListener {
        /**
         * @param view                被點贊的按鈕
         * @param toggle              開關(guān)
         * @param viewLikeBesselUtils 工具類本身
         */
        void onClick(View view, boolean toggle, ViewLikeBesselUtils viewLikeBesselUtils);
    }
    // 被點擊的按鈕
    private View mClickView;
    private View[] mAnimViews;
    private ViewLikeClickListener mListener;
    private boolean toggle = false; // 點擊開關(guān)標(biāo)識
    private int mX; // 距離屏幕左側(cè)距離
    private int mY; // 距離屏幕頂端距離, 越往下數(shù)值越大
    private Random mRandom = new Random(); // 隨機數(shù)
    /**
     * @param mClickView 被點擊的View
     * @param mAnimViews 點贊后, 向上浮動的View數(shù)組
     * @param mListener  被點擊的View,點擊后的回調(diào)事件.
     */
    public ViewLikeBesselUtils(View mClickView, View[] mAnimViews, @NonNull ViewLikeClickListener mListener) {
        this.mClickView = mClickView;
        this.mAnimViews = mAnimViews;
        this.mListener = mListener;
        initListener();
    }
    /**
     * 設(shè)置View的監(jiān)聽
     */
    private void initListener() {
        mClickView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                if (motionEvent.getAction() == MotionEvent.ACTION_UP || motionEvent.getAction() == MotionEvent.ACTION_CANCEL) {
                    getLocation(); // 獲取被點擊View的坐標(biāo)
                    toggle = !toggle;
                    if (mListener != null) {
                        mListener.onClick(mClickView, toggle, ViewLikeBesselUtils.this);
                    }
                    // mView.performClick();
                }
                // 正常的OnClickListener將無法調(diào)用
                return true;
            }
        });
    }
    /**
     * 獲取View在屏幕中的坐標(biāo)
     */
    private void getLocation() {
        int[] mLocation = new int[2];
        mClickView.getLocationInWindow(mLocation);
        mX = mLocation[0];
        mY = mLocation[1];
    }
    /**
     * 開始動畫
     *
     * @param mAnimView
     */
    private void startAnim(View mAnimView, int mTime) {
        AnimatorSet animatorSet = new AnimatorSet();
        ArrayList<BaseInterpolator> interpolators = new ArrayList<>();
        interpolators.add(new AccelerateInterpolator());
        interpolators.add(new DecelerateInterpolator());
        interpolators.add(new AccelerateDecelerateInterpolator());
        interpolators.add(new LinearInterpolator());
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
            animatorSet.setInterpolator(interpolators.get(mRandom.nextInt(4)));
        }
        // 合并動畫
        animatorSet.playTogether(getAnimationSet(mAnimView), getBezierAnimatorSet(mAnimView));
        animatorSet.setTarget(mAnimView);
        animatorSet.setDuration(mTime);
        animatorSet.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {
            }
            @Override
            public void onAnimationEnd(Animator animator) {
                removeChildView(mAnimView);
            }
            @Override
            public void onAnimationCancel(Animator animator) {
            }
            @Override
            public void onAnimationRepeat(Animator animator) {
            }
        });
        animatorSet.start();
    }
    /**
     * 將上浮控件添加到屏幕中
     *
     * @param animview
     */
    private void addAnimView(View animview) {
        Activity activityFromView = getActivityFromView(mClickView);
        if (activityFromView != null) {
            FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
            FrameLayout mRootView = (FrameLayout) activityFromView.getWindow().getDecorView().getRootView();
            mRootView.addView(animview, params);
        }
    }
    /**
     * 開始動畫
     */
    public void startLikeAnim() {
        for (View mAnimView : mAnimViews) {
            removeChildView(mAnimView);
            addAnimView(mAnimView);
            startAnim(mAnimView, mRandom.nextInt(1500));
        }
    }
    /**
     * 獲取屬性動畫
     */
    private AnimatorSet getAnimationSet(View mView) {
        ObjectAnimator scaleX = ObjectAnimator.ofFloat(mView, "scaleX", 0.4f, 1f);
        ObjectAnimator scaleY = ObjectAnimator.ofFloat(mView, "scaleY", 0.4f, 1f);
        ObjectAnimator alpha = ObjectAnimator.ofFloat(mView, "alpha", 1f, 0.2f);
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.playTogether(scaleX, scaleY, alpha);
        return animatorSet;
    }
    /**
     * 獲取貝塞爾動畫
     */
    private ValueAnimator getBezierAnimatorSet(View mView) {
        // 測量view
         mView.measure(0, 0);
        // 屏幕寬
        int width = getActivityFromView(mClickView).getWindowManager().getDefaultDisplay().getWidth();
        int mPointF0X = mX + mRandom.nextInt(mView.getMeasuredWidth());
         int mPointF0Y = mY - mView.getMeasuredHeight()/2;
        // 起點
        PointF pointF0 = new PointF(mPointF0X, mPointF0Y);
        // 終點
        PointF pointF3 = new PointF(mRandom.nextInt(width - 100), 0f);
        // 第二點
        PointF pointF1 = new PointF(mRandom.nextInt(width - 100), (float) (mY * 0.7));
        // 第三點
        PointF pointF2 = new PointF(mRandom.nextInt(width - 100), (float) (mY * 0.3));
        BezierEvaluator be = new BezierEvaluator(pointF1, pointF2);
        ValueAnimator bezierAnimator = ValueAnimator.ofObject(be, pointF0, pointF3);
        bezierAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                PointF pointF = (PointF) valueAnimator.getAnimatedValue();
                mView.setX(pointF.x);
                mView.setY(pointF.y);
            }
        });
        return bezierAnimator;
    }
    /**
     * 獲取Activity
     *
     * @param view
     * @return
     */
    public Activity getActivityFromView(View view) {
        if (null != view) {
            Context context = view.getContext();
            while (context instanceof ContextWrapper) {
                if (context instanceof Activity) {
                    return (Activity) context;
                }
                context = ((ContextWrapper) context).getBaseContext();
            }
        }
        return null;
    }
    /**
     * 將子View從父容器中去除
     */
    private void removeChildView(View mChildView) {
        ViewGroup parentViewGroup = (ViewGroup) mChildView.getParent();
        if (parentViewGroup != null) {
            parentViewGroup.removeView(mChildView);
        }
    }
}
public class BezierEvaluator implements TypeEvaluator<PointF> {
    /**
     * 這2個點是控制點
     */
    private PointF point1;
    private PointF point2;

    public BezierEvaluator(PointF point1, PointF point2) {
        this.point1 = point1;
        this.point2 = point2;
    }

    /**
     * @param t
     * @param point0 初始點
     * @param point3 終點
     * @return
     */
    @Override
    public PointF evaluate(float t, PointF point0, PointF point3) {
        PointF point = new PointF();
        point.x = point0.x * (1 - t) * (1 - t) * (1 - t)
                + 3 * point1.x * t * (1 - t) * (1 - t)
                + 3 * point2.x * t * t * (1 - t) * (1 - t)
                + point3.x * t * t * t;
        point.y = point0.y * (1 - t) * (1 - t) * (1 - t)
                + 3 * point1.y * t * (1 - t) * (1 - t)
                + 3 * point2.y * t * t * (1 - t) * (1 - t)
                + point3.y * t * t * t;
        return point;
    }
}

使用

mBtn = findViewById(R.id.btn_anim)
val mTVS = arrayOfNulls<TextView>(200)
for (i in 0..199) {
    val mTV = TextView(this@MainActivity2)
    mTV.text = "贊"
    mTV.setTextColor(Color.RED)
    mTV.textSize = mBtn.textSize
    mTVS[i] = mTV
}
ViewLikeBesselUtils(mBtn, mTVS) { view, toggle, viewLikeBesselUtils ->
    viewLikeBesselUtils.startLikeAnim()
}

效果

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

相關(guān)文章

  • Android實現(xiàn)圖片預(yù)覽與保存功能

    Android實現(xiàn)圖片預(yù)覽與保存功能

    在App開發(fā)中,通常為了省流提高加載速度提升用戶體驗我們通常在列表中或新聞中的插圖都是以縮略圖壓縮過的圖片來進行展示,當(dāng)用戶點擊圖片時我們再去加載真正像素的大圖讓用戶預(yù)覽。本文將利用Flutter實現(xiàn)這一功能,需要的可以參考一下
    2022-04-04
  • Angular5.0.0新特性

    Angular5.0.0新特性

    Angular5.0.0是一款非常優(yōu)秀的前端JS框架,已經(jīng)被用于google多款產(chǎn)品當(dāng)中,這篇文章主要介紹了Angular5.0.0新特性,需要的朋友可以參考下
    2017-11-11
  • Android實現(xiàn)簡潔的APP登錄界面

    Android實現(xiàn)簡潔的APP登錄界面

    這篇文章主要為大家詳細介紹了Android簡潔登錄界面的編寫代碼,實現(xiàn)簡單的登錄,用戶名密碼驗證功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • Android 帶有彈出收縮動畫的扇形菜單實例

    Android 帶有彈出收縮動畫的扇形菜單實例

    本篇文章主要介紹了Android 帶有彈出收縮動畫的扇形菜單實例,具有一定的參考價值,有興趣的可以了解一下
    2017-06-06
  • Android實現(xiàn)簡單計算器界面

    Android實現(xiàn)簡單計算器界面

    這篇文章主要為大家詳細介紹了Android實現(xiàn)簡單計算器界面,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-01-01
  • Android計步功能的實現(xiàn)代碼

    Android計步功能的實現(xiàn)代碼

    本篇文章主要介紹了Android計步功能的實現(xiàn)代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • Android RecyclerView添加FootView和HeadView

    Android RecyclerView添加FootView和HeadView

    這篇文章主要介紹了Android RecyclerView添加FootView和HeadView的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • Android 高德地圖之poi搜索功能的實現(xiàn)代碼

    Android 高德地圖之poi搜索功能的實現(xiàn)代碼

    這篇文章主要介紹了android 高德地圖之poi搜索功能的實現(xiàn)代碼,在實現(xiàn)此功能時遇到很多問題,在文章都給大家提到,需要的朋友可以參考下
    2017-08-08
  • 詳解Android中Activity的四大啟動模式實驗簡述

    詳解Android中Activity的四大啟動模式實驗簡述

    本篇文章主要介紹了Android中Activity的四大啟動模式實驗簡述,具有一定的參考價值,有興趣的可以了解一下。
    2016-12-12
  • Android簡單創(chuàng)建一個Activity的方法

    Android簡單創(chuàng)建一個Activity的方法

    這篇文章主要介紹了Android簡單創(chuàng)建一個Activity的方法,結(jié)合圖文形式分析了Android創(chuàng)建Activity的具體步驟與實現(xiàn)技巧,需要的朋友可以參考下
    2016-04-04

最新評論