1. 程式人生 > >Android/安卓仿淘寶直播點贊效果/qq空間點贊效果動畫

Android/安卓仿淘寶直播點贊效果/qq空間點贊效果動畫

之前玩淘寶誤入它的直播頻道,發現它的直播介面的點贊效果挺好看,然後發現QQ控制元件點贊有類似動畫,於是趁有空花了點時間玩玩。

先上個效果圖:


添加了一個按鈕模擬點贊,點選多少次就出現多個水果,他們的運動軌跡和速度是不一樣的,而且帶有淡入淡出效果。這是淘寶直播的效果,qq空間是點選一次就出現好多個的,修改一點邏輯也能實現對應的效果。

gif圖看起來有點不流暢,因為錄製時鎖定的幀率避免超2M不能上傳,實際執行是流暢的。

因為不是做成一個通用控制元件,所以我也就實現了效果,大家如果要用,可以自己加更多自定義內容。實現起來挺簡單的,也就不囉嗦了

用到的知識點:貝塞爾公式(三階)、屬性動畫、動畫集合、自動義估值器

先丟程式碼再說實現過程:

程式碼:

package cn.small_qi.transitiontest.diyview;

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import cn.small_qi.transitiontest.R;
public class PressLikeView extends ViewGroup {
    private List<Integer> images;//圖片
    private List<Interpolator> inters;//插值器
    private Random random;
    private int defaultSize = 150;//圖片預設尺寸(px)
    public PressLikeView(Context context) {
        super(context);
    }
    public PressLikeView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initData();
    }
//初始化資料
    private void initData() {
        random =new Random();
        images = new ArrayList<>();
        inters = new ArrayList<>();
        images.add(R.drawable.a510209);
        images.add(R.drawable.a510213);
        images.add(R.drawable.a510216);
        images.add(R.drawable.a510222);
        images.add(R.drawable.a510225);
        images.add(R.drawable.a510234);
        //....
        inters.add(new LinearInterpolator());
        inters.add(new AccelerateInterpolator());
        inters.add(new AccelerateDecelerateInterpolator());
        inters.add(new DecelerateInterpolator());
        //....
    }

    public PressLikeView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {  }
    //使用預置的隨機圖片
    public void  show(){//這個方法是開放出去的,就是按鈕點選時呼叫,出現一個水果動畫
        ImageView view = new ImageView(getContext());
        view.setImageResource(images.get(random.nextInt(images.size())));//隨機設定一張圖片
        view.setLayoutParams(new LayoutParams(defaultSize,defaultSize));//設定大小
        addView(view);//新增到容器中
        view.layout(getWidth()/2-defaultSize, (int) (getHeight()-defaultSize*1.5),getWidth()/2, (int) (getHeight()-0.5*defaultSize));//計算位置
        startAnim(view);//開始動畫
    }
    //使用自定義的圖片 -- 也可以修改成傳入一個ImageView
    public void  show(Drawable drawable){
        ImageView view = new ImageView(getContext());
        view.setImageDrawable(drawable);
        view.setLayoutParams(new LayoutParams(defaultSize,defaultSize));
        addView(view);
        view.layout(getWidth()/2-defaultSize, (int) (getHeight()-defaultSize*1.5),getWidth()/2, (int) (getHeight()-0.5*defaultSize));
        startAnim(view);
    }

    private void startAnim(final ImageView view) {
        AnimatorSet animatorSet = new AnimatorSet();
        //淡入動畫
        ValueAnimator inAnim = ValueAnimator.ofFloat(0.5f,1f);
        inAnim.setDuration(500);
        inAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                view.setAlpha(value);
                view.setScaleX(value);
                view.setY(value);
            }
        });
        //淡出動畫
        ValueAnimator outAnim = ValueAnimator.ofFloat(1,0);
        outAnim.setDuration(1500);
        outAnim.setStartDelay(1500);//延遲啟動,保證水果飛到一大半再淡出
        outAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                view.setAlpha((float) animation.getAnimatedValue());
            }
        });
        //位移動畫
        ValueAnimator transAnim = ValueAnimator.ofObject(new BezierValue(),new Point(getWidth()/2,getHeight()),new Point(new Random().nextInt(getWidth()),0));
        transAnim.setDuration(3000);
        transAnim.setInterpolator(inters.get(random.nextInt(inters.size())));//隨機設定插值器
        transAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Point point = (Point) animation.getAnimatedValue();
                view.setX(point.x);
                view.setY(point.y);
            }
        });
        //組合動畫
        //三個動畫同時執行
        animatorSet.playTogether(inAnim,transAnim,outAnim);
        //前面兩個動畫延遲執行,最後一個同時執行
        /*animatorSet.playSequentially(inAnim,transAnim);
        animatorSet.play(outAnim);*/
        animatorSet.start();
        animatorSet.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) { }
            @Override
            public void onAnimationEnd(Animator animation) {
                removeView(view);//動畫結束移除ImageView
            }
            @Override
            public void onAnimationCancel(Animator animation) { }
            @Override
            public void onAnimationRepeat(Animator animation) { }
        });
    }
    //自定義插值器
    class BezierValue implements TypeEvaluator<Point>{
        private Random random =new Random();
        private int ctrlPX1, ctrlPX2,ctrlPY1, ctrlPY2;
        private boolean isInit;//只需要初始化一次
        @Override
        public Point evaluate(float fraction, Point startValue, Point endValue) {
            Point point = new Point();
            point.x = (int) cubicPointX(fraction,startValue.x,endValue.x);
            point.y = (int) cubicPointY(fraction,startValue.y,endValue.y);
            return point;
        }
        //貝塞爾計算x
        private double cubicPointX(float fraction, int start, int end){
            if (!isInit){
                //初始化控制點y左邊
                ctrlPY1 = random.nextInt(start+end/2);
                ctrlPY2 = random.nextInt(start+end/2)+(start+end/2);
                //初始化控制點x座標
                if (random.nextBoolean()){//先左後右
                    ctrlPX1 = (int) (random.nextInt(start)-start/4f);//減去start/4 是為了運動曲線更明顯
                    ctrlPX2 = (int) (random.nextInt(start)+start*1.25f);//start是寬度的一半,為了保證後面往右運動,應該是隨機數加上start。現在乘1.25是為了讓曲線更明顯
                }else{//先右後左
                    ctrlPX1 = (int) (random.nextInt(start)+start*1.25f);
                    ctrlPX2 = (int) (random.nextInt(start)-start/4f);
                }
                isInit =true;
            }
           return start*Math.pow((1-fraction),3)+3* ctrlPX1 *fraction*Math.pow((1-fraction),2)
                    +3* ctrlPX2 *Math.pow(fraction,2)*(1-fraction)+end*Math.pow(fraction,3);
        }
        //貝塞爾計算y
        private double cubicPointY(float fraction, int start, int end){
            return start*Math.pow((1-fraction),3)+3* ctrlPY1 *fraction*Math.pow((1-fraction),2)
                    +3* ctrlPY2 *Math.pow(fraction,2)*(1-fraction)+end*Math.pow(fraction,3);
        }
    }
}

其實就是

1.自定義一個ViewGroup,然後每點選一次就往裡面新增一個ImageView,然後設定好它的位置和大小

2.為每一個ImageView設定隨機的圖片,然後對其執行一些列動畫

3.為了某些效果加入了淡入淡出動畫,相信大家都熟悉,根據自己需求來決定怎麼寫就行了

4.主要是運動軌跡動畫,為了路徑不是單純的直線或者簡單的曲線,所以用了自定義估值器配合三階的貝塞爾實現運動路徑

5.為了實現運動速度的不規則,內建了4種插值器,然後每次隨機取一個,用在運動軌跡的動畫上

可能有點難看懂的是我位置的計算和貝塞爾控制點的計算,我這裡簡要說明一下。

初始位置我本來是是要底部居中,但是稍微做了點偏移,計算位置如圖所示:


而貝塞爾兩個控制點和終點的選擇,我是這麼計算的,大家結合程式碼看就看得懂了:


計算好動畫之後,接下來就不難了!執行動畫就好了,這樣就實現的這種效果拉!

--本文結束,謝謝大家閱讀

相關推薦

Android/仿直播效果/qq空間效果動畫

之前玩淘寶誤入它的直播頻道,發現它的直播介面的點贊效果挺好看,然後發現QQ控制元件點贊有類似動畫,於是趁有空花了點時間玩玩。 先上個效果圖: 添加了一個按鈕模擬點贊,點選多少次就出現多個水果,他們的運動軌跡和速度是不一樣的,而且帶有淡入淡出效果。這是淘寶直播的效果,qq

仿頁面的搜索引擎,擊輸入框文字不消失

arch 大堆 urn images ace src func 國際 lan 1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="UTF-8

android 資料重構(仿瀏覽記錄,足跡)

資料結構 ->資料重構 原因 處理這個資料的主要原因是,後臺伺服器返回的資料格式在ios那邊因為其控制元件可以對資料進行分割槽顯示,可以直接處理,而在android上我們顯示控制元件就是li

Android開發之仿商品詳情頁

看到有人在問如何實現淘寶商品詳情頁效果,手癢了就擼了一個,獻上效果圖 大致梳理一下思路,這裡不提供原始碼 狀態列透明使用開源庫StatusBarCompat,為了相容手機4.4 dependencies { compile ('com.

Android fragment+viewpager 仿qq介面 實現選選單切換介面+滑動切換viewpager切換介面

原始碼地址 http://download.csdn.net/detail/zhangjm_123/7902245 最近寫了一個fragment+viewpager仿qq的app,先上圖                   如圖,介面底部有四個textview,分別

android軟件開發之仿選擇規格的實現

per con attribute back view.gone boolean 做了 over ear 在一些app開發項目中選擇商品規格這個功能最容易遇到問題,想要實現需要的全部功能,但一直沒有成功,所以就去找了個Demo,學習界面UI采用recyclerview,it

Android開發仿商品詳情瀏覽效果 兩步曲

效果圖: 第一步佈局檔案: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/andr

Android仿底部圖示導航欄

       在上一篇中,簡單的使用透明主題的Activity實現了仿微信右側頂部的對話方塊,上午又花了兩個小時研究了一下淘寶底部的導航欄實現,網上的做法也有很多,今天我就使用一種通過基本控制元件加上佈局的方式,沒有任何的自定義風格,控制元件等來實現,還是老樣子,先看一下效果

java B2B2C springmvc mybatis仿電子商城系統-整合企業架構的技術

spring cloud本身提供的元件就很多,但我們需要按照企業的業務模式來定製企業所需要的通用架構,那我們現在需要考慮使用哪些技術呢? 下面我針對於spring cloud微服務分散式雲架構做了以下技術總結,希望可以幫助到大家: 需要JAVA Spring Cloud大型企業分散式

Android自定義控制元件實戰——仿商品瀏覽介面

用手機淘寶瀏覽商品詳情時,商品圖片是放在後面的,在第一個ScrollView滾動到最底下時會有提示,繼續拖動才能瀏覽圖片。仿照這個效果寫一個出來並不難,只要定義一個Layout管理兩個ScrollView就行了,當第一個ScrollView滑到底部時,再次向上滑動進入第二

Android 仿商品詳情標題欄變色,佈局層疊效果

如圖效果 思路:如圖可以將圖片中佈局分成三個部分,1標題欄透明背景,2上半部分佈局,3下半部分佈局,當我們向上拉動的時候,1佈局實現漸變,從透明變到白色,2佈局背景色漸變到白色,23佈局隨滾動條上拉,並且慢慢改變2佈局paddingtop的屬性,其中1佈局漂浮在整個scro

android 自定義ViewGroup實現仿的商品詳情頁

最近公司在新版本上有一個需要, 要在首頁新增一個滑動效果, 具體就是仿照X寶的商品詳情頁, 拉到頁面底部時有一個粘滯效果,  如下圖 X東的商品詳情頁,如果使用者繼續向上拉的話就進入商品圖文描述介面: 剛開始是想拿來主義,直接從網上找個現成的demo來用, 但是網上無一

Android 仿商品詳情頁下拉足跡Demo

DropDownMultiPager 仿淘寶等商品詳情頁下拉足跡效果SimpleDemo 可colne之後看MainActivity的呼叫,方便二次開發 依賴 compile 'com.nin

仿商品詳情頁面Android

1、需求: 要實現一個類似淘寶、京東的商品詳情頁面。首先是在看一些前輩的思路,檢視之後,發現博主qifengdeqingchen的文章不錯,然後去下載下來檢視demo。 2、查閱資料 來看看前輩的思路圖。使用兩個scrollView,兩個scr

android自定義ProgressBar(仿)的載入效果

三種方式實現自定義圓形頁面載入中效果的進度條 To get a ProgressBar in the default theme that is to be used on white/light back ground, use one of the inverse st

android 仿、京東商品詳情頁 向上拖動檢視圖文詳情控制元件

/** * Created by baoyunlong on 16/6/8. */ public class PullUpToLoadMore extends ViewGroup { public static String TAG = PullUpToLoadMore.class.getName

Android 小樣之高仿時間軸物流資訊

最近做訂單系統,用到時間軸資訊,首先想到的是淘寶的物流時間軸(網購狗)。不多廢話,首先來看看淘寶物流資訊的樣式 這裡給出兩種解決方法: 使用LinearLayout動態新增view生成物流資訊

Android一點 仿購物車動畫

首先看看ios上的淘寶購物車的動畫效果ios淘寶購物車動畫 我們實現的效果 看特效是分為兩個介面,一個是主view,一個是彈出層。彈出層是用dialog實現的,只是加入了彈出的動畫,這裡就不分析了,我們主要看主view的動畫是怎麼實現的,初看好像只是

Android 仿京東等我的訂單介面及任意列表拓展

概述 目前像淘寶及展示列表等都有多個item展示的需求,可能大多數如果沒做過,第一眼就是ListView去巢狀ListView,雖然這樣是可以完成,但是這樣做會導致手機過度繪製,為什麼呢?因為當一個Item載入的時候又會去更新item裡面的adapter,ap

【商城開發三】Android 仿商品詳情頁下拉足跡修改版

開發商城的快有半個月了,需要做到詳情頁下拉足跡的效果,網上找了找沒找到,找到一個差不多還有點問題,然後在基礎上進行了二次開發 感謝http://blog.csdn.net/yaphetzhao/article/details/53736471  YaphetZhao的部落格