1. 程式人生 > >Android 中關於屬性動畫的一些思考,或許能為你解決一定的效能問題

Android 中關於屬性動畫的一些思考,或許能為你解決一定的效能問題

——學之開源,用於開源;初學者的心態,與君共勉!
========================================================

用動畫用的久了漸漸的喜歡上她了,雖然它或許並不是女的,但我希望是~~

用的久了,我漸漸的思考效能的問題了;在我的一篇([Material Design] MaterialButton 效果進階 動畫自動移動進行對齊效果)介紹按鈕點選特效的文章中使用了大量的屬性動畫,但是在後來我想了很久,其是隻需要一個屬性動畫就能解決所有問題。

下面咱們來說說怎麼把多個屬性動畫合成一個。

開始

一般來說,我們在自定義控制元件或者控制一些移動操作的時候會使用到這樣的屬性動畫,其是屬性動畫並不是想象中那麼難,只要看看用法舉一反三用用就會了~

    private float paintX = 0;
    private float paintY = 0;

    private Property<MyView, Float> PaintYProperty = new Property<MyView, Float>(Float.class, "paintY") {
        @Override
        public Float get(MyView object) {
            return object.paintY;
        }

        @Override
        public void set(MyView object, Float value) {
            object.paintY = value;
        }
    };

    private Property<MyView, Float> PaintXProperty = new Property<MyView, Float>(Float.class, "paintX") {
        @Override
        public Float get(MyView object) {
            return object.paintX;
        }

        @Override
        public void set(MyView object, Float value) {
            object.paintX = value;
        }
    };

    private void start() {
        //PaintX
        ObjectAnimator aPaintX = ObjectAnimator.ofFloat(this, PaintXProperty, 0, 100);
        //PaintY
        ObjectAnimator aPaintY = ObjectAnimator.ofFloat(this, PaintYProperty, 0, 100);
        //AnimatorSet
        AnimatorSet set = new AnimatorSet();
        set.playTogether(aPaintX, aPaintY);
        set.start();
    }

在上述的中我們建立了一個關於座標的屬性動畫,一般來說座標含有XY,所以我們定義了兩個屬性動畫;然後打包到一個 AnimatorSet 中管理。至於 AnimatorSet 是什麼?你可以理解為這個類是一個屬性的管理類,你可以新增 N 多的動畫到其中,然後統一排程開啟停止;在 AnimatorSet 中維護著一個動畫佇列。

在上面雖然最後打包到了 AnimatorSet 中進行統一排程,但是你看看 AnimatorSet 中的部分原始碼你就知道其最後也是啟動每一個的屬性動畫進行啟動的。

這也就是我們今天需要想想的地方,你現在完成一個很複雜的操作,其中不但包含一個座標或者是一堆座標,也或者包含了很多的顏色變化,此時你使用屬性動畫就不是一個明智的選擇了;為什麼呢?你想想你要完成我所說的需要建立多少個屬性動畫類?很多吧~浪費記憶體CPU吧?你敢說沒有???

既然今天是說優化,那就來優化優化~~

優化

針對上面的情況我們有兩種解決方案

第一種

使用一個 Animation ,然後在 protected void applyTransformation(float interpolatedTime, Transformation t)中回撥處理具體的情況;具體可以看看我的文章:中有一定的介紹,其效率遠遠要高於上面的多個屬性動畫的情況。

第二種

第一種是採用最基本的 Animation 來實現的,這第二種也是使用屬性動畫。

先看看一部分程式碼:

   public static class ViewProperty {
        private float paintX = 0;
        private float paintY = 0;

        public ViewProperty() {
        }

        public ViewProperty(float paintX, float paintY) {
            this.paintX = paintX;
            this.paintY = paintY;
        }
    }
是的我們使用一個內部類把所有的屬性進行一次封裝;然後就可以只使用一個屬性動畫了;現在看看程式碼:
   private ViewProperty mProperty = new ViewProperty(0, 0);
    private Property<MyView, ViewProperty> PaintProperty = new Property<MyView, ViewProperty>(ViewProperty.class, "paintX") {
        @Override
        public ViewProperty get(MyView object) {
            return object.mProperty;
        }

        @Override
        public void set(MyView object, ViewProperty value) {
            object.mProperty = value;
        }
    };

    private void start() {
        //Paint
        ObjectAnimator aPaint = ObjectAnimator.ofObject(this, PaintProperty, new ViewProperty(0, 0), new ViewProperty(100, 100));
        aPaint.start();
    }
是不是很簡單?是不是隻有一個屬性動畫:ObjectAnimator ,是的 ~是的 ! 

別高興的太早了~~看看實際情況:


擦~~~這個是怎麼了??哪裡出錯了??

思考

我們應該想想,我們的想法是好的,封裝一個屬性集合類的例項,然後就可以只使用一個屬性動畫了;但是問題出在哪裡呢?

我們想想,對於Float,Int這些而言,在更改的時候都是採用 C=A+(B-A)*T 這樣的情況來的,但是對於Object型別來說呢?這個它怎麼減去,怎麼運算?

我想這是應該我們去實現的地方,我們需要告訴程式按照什麼樣的方式去運算: C=A+(B-A)*T 這樣的一個公式,告訴它在時間等值情況下進行了10%的時間的時候應該是:new ViewProperty(10, 10),這個值!

TypeEvaluator

public interface TypeEvaluator<T> {

    /**
     * This function returns the result of linearly interpolating the start and end values, with
     * <code>fraction</code> representing the proportion between the start and end values. The
     * calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>,
     * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
     * and <code>t</code> is <code>fraction</code>.
     *
     * @param fraction   The fraction from the starting to the ending values
     * @param startValue The start value.
     * @param endValue   The end value.
     * @return A linear interpolation between the start and end values, given the
     *         <code>fraction</code> parameter.
     */
    public T evaluate(float fraction, T startValue, T endValue);

}
在動畫類中,有這樣的一個介面,這個介面所完成的工作就是上面的: C=A+(B-A)*T 

其是我們可以看看:

    public static <T, V> ObjectAnimator ofObject(T target, Property<T, V> property,
            TypeEvaluator<V> evaluator, V... values) {
        ObjectAnimator anim = new ObjectAnimator(target, property);
        anim.setObjectValues(values);
        anim.setEvaluator(evaluator);
        return anim;
    }
在屬性動畫 ObjectAnimator 類的例項化中有這樣的一個建構函式,在該建構函式中就允許使用者自己指定自己的運算介面類。

現在我們繼承該介面,並實現它:

PaintEvaluator

    public static class PaintEvaluator implements TypeEvaluator {
        private static final PaintEvaluator sInstance = new PaintEvaluator();

        public static PaintEvaluator getInstance() {
            return sInstance;
        }

        public Object evaluate(float fraction, Object startValue, Object endValue) {
            ViewProperty start = (ViewProperty) startValue;
            ViewProperty end = (ViewProperty) endValue;

            float x = start.paintX + fraction * (end.paintX - start.paintX);
            float y = start.paintY + fraction * (end.paintY - start.paintY);

            return new ViewProperty(x, y);
        }
    }
很簡單吧。就是分別計算x,y;然後返回一個類的例項就OK了。

結束

然後修改上面的啟動程式碼為:

    private ViewProperty mProperty = new ViewProperty(0, 0);
    private static PaintEvaluator PAINTEVALUATOR = new PaintEvaluator();
    private static Property<MyView, ViewProperty> PaintProperty = new Property<MyView, ViewProperty>(ViewProperty.class, "paint") {
        @Override
        public ViewProperty get(MyView object) {
            return object.mProperty;
        }

        @Override
        public void set(MyView object, ViewProperty value) {
            object.mProperty = value;
        }
    };

    private void start() {
        //Paint
        ObjectAnimator paint = ObjectAnimator.ofObject(this, PaintProperty, PAINTEVALUATOR, new ViewProperty(0, 0), new ViewProperty(100, 100));
        paint.start();
    }
OK,大功告成~~
現在才是夠簡單,夠舒爽~~

祝,大家都能寫出稱心如意的程式碼~~

——學之開源,用於開源;初學者的心態,與君共勉!
========================================================

相關推薦

Android 關於屬性動畫一些思考或許解決一定效能問題

——學之開源,用於開源;初學者的心態,與君共勉!======================================================== 序 用動畫用的久了漸漸的喜歡上她了,雖然它或許並不是女的,但我希望是~~ 用的久了,我漸漸的思考效能的問題

android屬性動畫的bug以及ViewCompat

ViewCompat這個類,是andorid對於動畫類操作的相容類,今天寫了一個側拉框,出現的一個bug    今天一不小心遇見一個bug,這個bug如下 正常情況下慢慢畫動畫可以用,但是快速化,動畫就停止了, 今天先貼程式碼,明天貼圖 final CycleInte

android屬性動畫 ObjectionAnimation

   關於動畫:  android中動畫包括 View Animation、Drawable Animation和屬性動畫Property Animation      ●

Android屬性動畫和補間動畫的區別

 屬性動畫和補間動畫的區別是,補間動畫只是表面上實現了平移,旋轉,漸變,縮放,實際上屬性值不變;  屬性動畫實現平移,旋轉,漸變,縮放後,屬性值變了  下面就是測試的例子 程式碼: package com.atguigu.propertyanimation; impor

企業有了ERP為什麼還需要大資料分析企業解決什麼問題?

如果一個企業不做資料分析,那將意味著什麼? 使用者在哪?我怎樣才能和他們互動? 我不知道我的營銷活動到底效果如何? 使用

Android 動畫有哪幾類它們的特點和區別是什麼?

1、Drawable Animation 幀動畫,Frame動畫,指通過指定的每一幀的圖片和播放時間,有序的進行播放而形成的動畫效果 2、View Animation 檢視動畫,也就是所謂的補間動畫。指通過指定View的初始狀態、變化時間、方式、通過一系列的演算法去進行圖片變換,從而

Android動畫(幀動畫、補間動畫屬性動畫

總的來說,安卓動畫可以分為兩類,最初的傳統動畫和Android3.0之後的屬性動畫。 傳統動畫包括:幀動畫( Frame Animation)和補間動畫(Tweened Animation)。 下面來具體說一下各種動畫的使用及特點: 幀動畫:是最容易實

Android開發屬性動畫(ObjectAnimator) 插值器(Time Interpolator )詳解

在 Android開發中,為了保持良好的互動體驗,我們經常會用到動畫來提升使用者體驗,而動畫中屬性動畫用的最多。 雖然動畫可以讓介面看起來不是那麼粗糙,但是很多時候僅僅只是勻速運動的動畫可能不足以描述一些我們想呈現給使用者的介面,比如模擬一個下落的小球,我們知道下落的小球並不是以勻速運動的,

Android開發屬性動畫(ObjectAnimator)的應用

昨天看到一個有意思的動畫,就想用Android 中的屬性動畫(ObjectAnimator)給實現出來,順便複習一下屬性動畫的使用,完成效果如下: 看完了效果,現在該開始動手幹活了~ 首先先分析一下這個動畫用Android 中的屬性動畫該怎麼實現: 看上去這個動畫很簡單,可以用

Android 屬性動畫詳解屬性動畫基本用法!

Hello,大家好,今天要給大家講的是Android 屬性動畫詳解! 在Tween動畫的討論中,我們提到在Android中動畫可以分為三類:①幀動畫②Tween(補間動畫)③Property Anim

Android屬性動畫完全解析Interpolator和ViewPropertyAnimator的用法

大家好,歡迎繼續回到Android屬性動畫完全解析。在上一篇文章當中我們學習了屬性動畫的一些進階技巧,包括ValueAnimator和ObjectAnimator的高階用法,那麼除了這些之外,當然還有一些其它的高階技巧在等著我們學習,因此本篇文章就對整個屬性動畫完

Android動畫和原理(屬性動畫)

1、屬性動畫 屬性動畫通過改變物件的屬性來展示的動畫效果,補間動畫只是設定當前View在區域內移動,產生的動畫效果,其實原View的還在原地,沒有發生改變。 但屬性動畫改變了物件的屬性。也就是改變了物件的顏色,位置,寬高等。 2、示例 publi

android View, Window, Activity, WindowManagerViewRoot幾者之間的關系

line 消息傳遞 post att 顯示 增加 調用 eas window對象 (1)View:最主要的UI組件,表示屏幕上的一個矩形區域。 (2)Window: 表示一個窗體,不一定有屏幕那麽大,能夠非常大也能夠非常小;

cocos2d-x 移植到android編譯的一些問題:fatal error: Box2D/Box2D.h: No such file or directory&quot;

cocos2 app nal get dsc err 2dx ros blue 1、fatal error: Box2D/Box2D.h: No such file or directory" 須要加入box2d庫的支持,改動android.mk

androidwebView加載H5JS不調用問題的解決

gpo see pos ble settings web database android中 加載 使用了html5 頁面,使用webView加載後發現 超鏈接的錨點不可以用 為webView設置下面兩句就好了: mWebView.getSettings().setDo

AndroidPaint的一些使用心得記錄

心得 ant 不可 ext 設置字體大小 畫筆 n) 記錄 12px Paint是Android api中繪制文字,圖形的重要類,位於android.graphics包下,這個類早早就出現了。類似於JavaScript中的Paint,Paint的使用也離不開Canvas。

vue遇到的一些記錄一下

class 會有 判斷 inject safari 項目 否則 lag 結合 最近用vue開發完成了網頁和app的項目試著想記錄下遇到的坑,以免下次遇到的時候就輕松解決了 一、vue開發pc端 1、 cookie不用中文的,和時間格式不要帶’/’ ,否則safari

android 通過不同的條件改變listview字型顏色及背景色

結果圖: 通過介面卡進行操作: public class SystemAdapter extends BaseAdapter { private ArrayList<SjClass> sData; private Context sContext;

androidjson檔案的讀取並用gson轉換成jsonobject,jsonarray

1.手機儲存卡中json檔案的讀取,返回String //從手機儲存卡路徑下解析json,並返回String public static String getFileFromSD(String path) { String result = ""; try { FileInpu

Android沉浸式狀態列改變狀態列顏色類似QQ樣式

1、使用該功能需要使用到第三方庫SystemBarTint 下載地址:https://github.com/jgilfelt/SystemBarTint 2、需要在AndroidMainfest檔案中Application設定樣式 android:the