Android仿抖音點擊效果

**1.概述 **

點擊效果==》
短視頻抖音*App非常火 ,視頻點擊效果紅心效果也不錯。其實不難就是一些動畫效果的結合使用,這里將具體一步一步實現。使用簡單,歡迎前往github。

老規矩,先看女神效果圖

douyin.gif

2.效果分析

2.1:首先是構建一張紅心圖片 new ImageView(mContext);

2.2:設置紅心圖片X與Y坐標位置

2.2:添加屬性動畫效果集,包含縮放、透明度、旋轉、向上平移(按一定順序重復)

3.代碼實現

3.1、自定義布局,我這里重寫RelativeLayout

3.2、自定義屬性attrs.xml

<!--attrs文件 屬性-->
<declare-styleable name="HeartLayout">
   <attr name="heart_width" format="integer" />
   <attr name="heart_height" format="integer" />
   <attr name="heart_image_resId" format="reference" />
</declare-styleable>
image.gif
 //自定義屬性 寬、高、圖片
TypedArray typedArray=context.obtainStyledAttributes(attrs,R.styleable.HeartLayout);
        mWidth=typedArray.getInteger(R.styleable.HeartLayout_heart_width,mWidth);
        mHeight=typedArray.getInteger(R.styleable.HeartLayout_heart_height,mHeight);
    image_resId=typedArray.getResourceId(R.styleable.HeartLayout_heart_image_resId,image_resId);
image.gif

3.3、創建ImageView,并設置坐標

** 默認圖片或者自定義**

ImageView imageView=new ImageView(mContext);
    imageView.setImageResource(image_resId);
image.gif
  因為**圖片位置在手指正上方**,所以得到觸摸坐標后進行左移動自身寬度一半,向上移動自身高度。
  RelativeLayout.LayoutParams layoutParams=new RelativeLayout.LayoutParams(mWidth, mHeight);
        int xLeft=(int)event.getX()- mWidth/2;
        int yTop=(int)event.getY() - mHeight;
        layoutParams.setMargins(xLeft,yTop,0,0);
        imageView.setLayoutParams(layoutParams);
image.gif

3.4、動畫效果ObjectAnimator

通過屬性動畫ObjectAnimator進行縮放、旋轉、漸變透明度、平移等操作ImageView心圖片。

3.5、RedHeartLayout自定義布局的整體代碼

/**
 * 仿抖音紅心效果
 */
public class RedHeartLayout extends RelativeLayout {
    private Context mContext;
    private float[] mRandomAngle = {-25, -15, 0, 15, 25};//隨機心形圖片角度
    private int image_resId=R.drawable.ic_heart;//默認圖片
    private int mWidth=120; //默認圖片寬
    private int mHeight=120;//默認圖片高

    /**
     * new 使用
     * @param context
     */
    public RedHeartLayout(Context context) {
        super(context);
        initView(context);
    }
    /**
     *  當有style自定義樣式時候 使用
     * @param context
     * @param attrs
     * @param defStyleAttr
     */

    public RedHeartLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context);
    }
    /**
     *  布局使用
     * @param context
     * @param attrs
     */
    public RedHeartLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        //自定義屬性 寬、高、圖片
        TypedArray typedArray=context.obtainStyledAttributes(attrs,R.styleable.HeartLayout);
        mWidth=typedArray.getInteger(R.styleable.HeartLayout_heart_width,mWidth);
        mHeight=typedArray.getInteger(R.styleable.HeartLayout_heart_height,mHeight);
        image_resId=typedArray.getResourceId(R.styleable.HeartLayout_heart_image_resId,image_resId);
        initView(context);
    }

    /**
     *  將寬高dp轉化為px
     * @param context
     */
    private void initView(Context context) {
        this.mContext = context;
        this.mHeight=dip2px(mContext,mHeight);
        this.mWidth=dip2px(mContext,mWidth);
    }

    /**
     *  觸摸事件處理
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {

        //第一步,創建心形ImageView
        final ImageView imageView=new ImageView(mContext);
        imageView.setImageResource(image_resId);
        RelativeLayout.LayoutParams layoutParams=new RelativeLayout.LayoutParams(mWidth, mHeight);
        int xLeft=(int)event.getX()- mWidth/2;
        int yTop=(int)event.getY() - mHeight;
        layoutParams.setMargins(xLeft,yTop,0,0);
        imageView.setLayoutParams(layoutParams);
        addView(imageView);
        //第二步,添加動畫效果集
        AnimatorSet animatorSet = new AnimatorSet();
                    //縮放動畫,X軸2倍縮小至0.9倍
        animatorSet.play(scaleXY(imageView, "scaleX", 2f, 0.9f, 100, 0))
                   //縮放動畫 , Y軸2倍縮小至0.9倍
                   .with(scaleXY(imageView, "scaleY", 2f, 0.9f, 100, 0))
                   //旋轉動畫 , 隨機旋轉角度
                   .with(rotation(imageView, 0, 0))
                   //透明度動畫 , 透明度從0-1
                   .with(alpha(imageView, 0, 1, 100, 0))
                   //縮放動畫 , X軸0.9倍縮小至1倍
                   .with(scaleXY(imageView, "scaleX", 0.9f, 1, 50, 150))
                   //縮放動畫 , Y軸0.9倍縮小至1倍
                   .with(scaleXY(imageView, "scaleY", 0.9f, 1, 50, 150))
                   //平移動畫 , Y軸從0向上移動700單位
                   .with(translationY(imageView, "translationY", 0, -700, 800, 400))
                   //透明度動畫 , 透明度從1-0
                   .with(alpha(imageView, 1, 0, 400, 400))
                   //縮放動畫 , X軸1倍放大至3倍
                   .with(scaleXY(imageView, "scaleX", 1, 3f, 800, 400))
                   //縮放動畫 , Y軸1倍放大至3倍
                   .with(scaleXY(imageView, "scaleY", 1, 3f, 800, 400));
        animatorSet.start();
        //動畫移除
        animatorSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                 removeViewInLayout(imageView);
            }
        });
        return super.onTouchEvent(event);
    }

    /**
     *   X軸或Y軸 縮放
     * @param view
     * @param propertyName
     * @param from
     * @param to
     * @param time
     * @param delayTime
     * @return
     */
    public  ObjectAnimator scaleXY(View view, String propertyName, float from, float to, long time, long delayTime) {
        ObjectAnimator _scaleXY=  ObjectAnimator.ofFloat(view,propertyName,from,to);
        ////設置插值器為 勻速(補充:有加速、先加后減等)
        _scaleXY.setInterpolator(new LinearInterpolator());
        //設置開始前延遲
        _scaleXY.setStartDelay(delayTime);
        //設置動畫持續時間
        _scaleXY.setDuration(time);
        _scaleXY.start();
        return _scaleXY;
    }

    /**
     *   X軸或Y軸 平移
     * @param view
     * @param from
     * @param to
     * @param time
     * @param delayTime
     * @return
     */
    public  ObjectAnimator translationY(View view,  String propertyName,float from, float to, long time, long delayTime) {
        ObjectAnimator translation = ObjectAnimator.ofFloat(view, propertyName, from, to);
        translation.setInterpolator(new LinearInterpolator());
        translation.setStartDelay(delayTime);
        translation.setDuration(time);
        return translation;
    }

    /**
     *   透明化處理
     * @param view
     * @param from
     * @param to
     * @param time
     * @param delayTime
     * @return
     */
    public  ObjectAnimator alpha(View view, float from, float to, long time, long delayTime) {
        ObjectAnimator alpha = ObjectAnimator.ofFloat(view, "alpha", from, to);
        alpha.setInterpolator(new LinearInterpolator());
        alpha.setStartDelay(delayTime);
        alpha.setDuration(time);
        return alpha;
    }

    /**
     *  旋轉
     * @param view
     * @param time
     * @param delayTime
     * @return
     */
    public ObjectAnimator rotation(View view, long time, long delayTime) {
        //隨機旋轉角度
        float angle= mRandomAngle[new Random().nextInt(4)];
        ObjectAnimator rotation = ObjectAnimator.ofFloat(view, "rotation", angle);
        rotation.setDuration(time);
        rotation.setStartDelay(delayTime);
        rotation.setInterpolator(new TimeInterpolator() {
            @Override
            public float getInterpolation(float input) {
                //抖動系數越小幅度越大 0-1
                return input;
            }
        });
        return rotation;
    }

    /**
     * 根據手機的分辨率從 dp 的單位 轉成為 px(像素)
     */
    public  int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
}
image.gif

4、布局使用

4.1、使用默認配置(推薦直接使用)

   <com.lzj.douyin.redheart.library.RedHeartLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent"/>
image.gif

4.2、自定義寬、高、引入其他圖片作為效果

   <com.lzj.douyin.redheart.library.RedHeartLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       app:heart_image_resId="@drawable/ic_heart"
       app:heart_width="120"
       app:heart_height="120" />
image.gif

5、Demo地址github**

覺得還行的老鐵,雙擊66。源碼地址歡迎前往

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,412評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,514評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,373評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,975評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,743評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,199評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,262評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,414評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,951評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,780評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,527評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,218評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,649評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,889評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,673評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,967評論 2 374

推薦閱讀更多精彩內容

  • 前言 學習自定義view,想找點東西耍一下,剛好看到抖音的點贊效果不錯,嘗試一下。 抖音效果: 話不多說,先上代碼...
    Wish_xy閱讀 6,055評論 9 50
  • Swift1> Swift和OC的區別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,121評論 1 32
  • 【Android 動畫】 動畫分類補間動畫(Tween動畫)幀動畫(Frame 動畫)屬性動畫(Property ...
    Rtia閱讀 6,198評論 1 38
  • 一、生命輪 列出現階段對你來說最重要的命題,為這些命題以1-10分為標準進行打分,列出自己為每一項命題花費的...
    _安小妮_閱讀 797評論 0 2
  • 喜歡熱鬧 沒有錯 喜歡安靜也沒有錯 但是,把自己喜歡的 硬生生塞給別人 還自覺圓滿 那么,對于別人而言 未必會產生...
    雪舞之陽閱讀 101評論 0 1