亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

ObjectAnimator屬性動畫源碼分析篇

2019-10-21 21:28:15
字體:
來源:轉載
供稿:網友

又和大家見面了,這幾天一直在忙大創項目,所以沒有更新博客,而且我發現看源碼這個東西必須寫個博客或者筆記啊,這之前一段時機筆者已經看了ValueAnimator和ObjectAnimator的源碼了,但是這才過了幾天,搞了會別的事情就忘得幾乎一干二凈了?,F在又要重頭看一遍很痛苦額-。+。

另外,筆者已經在簡書寫了關于屬性動畫的比較系統的詳細的文章,之后會陸續在CSDN上重新寫的(是重新寫,不是復制過去哦,因為第一次寫的實在是太爛了-。=)

好了不繼續扯皮了,我們看來一下今天想要講的東西——ObjectAnimator的源碼分析(使用部分)。

ObjectAnimator使用部分源碼

我們都知道屬性動畫使用分為三部分:創建、添加屬性、啟動。而我們今天要講的就是關于創建和添加屬性。首先來看創建的源碼吧:

創建

首先看一下今天所有用到的背景:

寫了一個自定義的View——PointView,用來實現一個小球的移動效果,PointView代碼如下(可以不用看-。+):

public class PointView extends View {  private Point mCurrentPoint;  private Paint paint;  /**   * 兩個構造方法   **/  public PointView(Context context) {    super(context);    paint = new Paint(Paint.ANTI_ALIAS_FLAG);    paint.setColor(Color.CYAN);    paint.setStrokeWidth(5);    paint.setStyle(Paint.Style.STROKE);  }  public PointView(Context context, @Nullable AttributeSet attrs) {    super(context, attrs);    paint = new Paint(Paint.ANTI_ALIAS_FLAG);    paint.setColor(Color.CYAN);    paint.setStrokeWidth(5);    paint.setStyle(Paint.Style.STROKE);  }  /**   * onDraw開始使用畫筆,如果mCurrentPoint為空,就創建Point對象,   * 否則就直接調用drawPoint方法   **/  @Override  protected void onDraw(Canvas canvas) {    super.onDraw(canvas);    if (mCurrentPoint == null) {      mCurrentPoint = new Point(500, 500);      drawPoint(canvas);    } else {      drawPoint(canvas);    }  }  //設置一個屬性添加的方法  public void setMove(Point point) {    mCurrentPoint = point;    invalidate();  }  //啟動動畫  private void startAnimation() {    ObjectAnimator animator = ObjectAnimator.ofObject(PointView.this, "Move", new BallEvaluator(),        new Point(500, 500),        new Point(500, 800), new Point(700, 800));    animator.setInterpolator(new LinearInterpolator());    animator.setDuration(5000);    animator.start();  }  //在外部調用的方法,通過此方法,開啟小球動作的動畫。  public void moveBall() {    startAnimation();  }  private void drawPoint(Canvas canvas) {    canvas.drawCircle(mCurrentPoint.getX(), mCurrentPoint.getY(), 30, paint);  }  //小球對象的估值器  public class BallEvaluator implements TypeEvaluator<Point> {    float x;    float y;    @Override    public Point evaluate(float fraction, Point startValue, Point endValue) {      float startX = startValue.getX();      float startY = startValue.getY();      float endX = endValue.getX();      float endY = endValue.getY();      x = fraction * (endX - startX);      y = fraction * (endY - startY);      Log.e("ASDSAD", "x = " + x + "y = " + y);      return new Point(startX + x, startY + y);    }  }}

代碼可能有點多,不過這不是主要的,我們今天關注的只是屬性動畫,所以我們只需要看里面的startAnimation方法和setMove方法就好:

  • setMove:由于我們知道屬性動畫ObjectAnimator類是通過將propertyName拼接成對應的set方法,然后通過反射機制去調用該方法,所以我們需要有一個對應的set方法。
  • startAnimation:這個方法我們用來設置我們的動畫以及啟動動畫。setMove方法,很簡單,我們只是將傳入的新的小球對象賦值給了mCurrentBall,然后調用invalidate方法重新繪制。下面看一下startAnimation方法:
ObjectAnimator animator = ObjectAnimator.ofObject(PointView.this, "Move", new BallEvaluator(),        new Point(500, 500),        new Point(500, 800), new Point(700, 800));    animator.setInterpolator(new LinearInterpolator());    animator.setDuration(5000);    animator.start();

我們看一下先進入ofObject方法(相信ofObject里面的參數大家都看得懂):

public static ObjectAnimator ofObject(Object target, String propertyName,      TypeEvaluator evaluator, Object... values) {    ObjectAnimator anim = new ObjectAnimator(target, propertyName);    anim.setObjectValues(values);    anim.setEvaluator(evaluator);    return anim;  }

我們發現ofObject是一個靜態方法:他在里面創建了一個ObjectAnimator對象。然后調用了setObjeectValues和setEvaluator方法,分別添加了數據和估值器。

也就是這個ofObject里面有三個入口等著我們進去:

  • ObjectAnimator的構造方法
  • setObjectValues方法
  • setEvaluator方法

那我們先從ObjectAnimator的構造方法開始看吧。

ObjectAnimator構造方法:

  private ObjectAnimator(Object target, String propertyName) {    setTarget(target);    setPropertyName(propertyName);  }

又是兩個方法,一個一個去看,先進入setTarget:

  @Override  public void setTarget(@Nullable Object target) {    final Object oldTarget = getTarget();    if (oldTarget != target) {      if (isStarted()) {        cancel();      }      mTarget = target == null ? null : new WeakReference<Object>(target);      // New target should cause re-initialization prior to starting      mInitialized = false;    }  }

這些代碼都能夠知道什么意思,這個方法我們只需要注意兩點:

  • 我們將傳入的target傳給了mTarget這個弱引用。
  • mInitialized = false;這個屬性我們可以這么理解,在他的ObjectAnimator沒有準備就緒(初始化過程尚未完成時),他一直都是false。

這個方法跳過。

然后我們看setPropertyName方法:

  public void setPropertyName(@NonNull String propertyName) {    // mValues could be null if this is being constructed piecemeal. Just record the    // propertyName to be used later when setValues() is called if so.    if (mValues != null) {      PropertyValuesHolder valuesHolder = mValues[0];      String oldName = valuesHolder.getPropertyName();      valuesHolder.setPropertyName(propertyName);      mValuesMap.remove(oldName);      mValuesMap.put(propertyName, valuesHolder);    }    mPropertyName = propertyName;    // New property/values/target should cause re-initialization prior to starting    mInitialized = false;  }

首先介紹一下mValues和mValuesMap這兩個屬性,他們都是存儲PropertyValueHolder的屬性,而且儲存的都一樣,只是mValuesMap可以讓我們通過propertyName來查找對應的PropertyValueHolder。

PropertyValuesHolder[] mValues;HashMap<String, PropertyValuesHolder> mValuesMap;

這個方法只是將propertyName放入PropertyValueHolder中(具體邏輯如上,先判斷mValues是否為空,如果不為空就將propertyName放入mValues和mValuesMap中,最后將propertyName賦值給mPropertyName),可以過了。

現在我們的ObjectAnimator構造方法看完了,我們接著看setObjectValues方法:

anim.setObjectValues:

  @Override  public void setObjectValues(Object... values) {    if (mValues == null || mValues.length == 0) {      // No values yet - this animator is being constructed piecemeal. Init the values with      // whatever the current propertyName is      if (mProperty != null) {        setValues(PropertyValuesHolder.ofObject(mProperty, (TypeEvaluator) null, values));      } else {        setValues(PropertyValuesHolder.ofObject(mPropertyName,            (TypeEvaluator) null, values));      }    } else {      super.setObjectValues(values);    }  }

這段代碼的總體邏輯只有一個:如果mValues沒有值,那么就調用setValues方法,否則就調用父類的setObjectValues方法。

感覺很亂啊,穩??!   我們這是第一次創建的對象,所以肯定是為空的,所以我們只需要看setValues方法就好了,但是注意,這里還有PropertyValueHolder,所以我們決定先看一下PropertyValueHolder的ofObject方法:

PropertyValueHolder.ofObject:

  public static <V> PropertyValuesHolder ofObject(Property property,      TypeEvaluator<V> evaluator, V... values) {    PropertyValuesHolder pvh = new PropertyValuesHolder(property);    pvh.setObjectValues(values);    pvh.setEvaluator(evaluator);    return pvh;  }

跟上面ObjectAnimator的ofObject差異不多,我們就不多說了,有兩條路可以選:

  • setObjectValues
  • setEvaluator

先看setObjectValues:

PropertyValueHolder.setObjectValues:

  public void setObjectValues(Object... values) {    mValueType = values[0].getClass();    mKeyframes = KeyframeSet.ofObject(values);    if (mEvaluator != null) {      mKeyframes.setEvaluator(mEvaluator);    }  }

我知道大家都快吐了,現在KeyFrames又出來了,頭皮發麻對吧,穩住,我們堅持?。?/p>

這個KeyFrames是KeyFrameSet的接口,我們看一下KeyframeSet的ofObject方法:

KeyframeSet.ofObject方法:

  public static KeyframeSet ofObject(Object... values) {    int numKeyframes = values.length;    ObjectKeyframe keyframes[] = new ObjectKeyframe[Math.max(numKeyframes,2)];//創建了一個至少為兩位的ObjectKeyFrame對象    if (numKeyframes == 1) {      keyframes[0] = (ObjectKeyframe) Keyframe.ofObject(0f);      keyframes[1] = (ObjectKeyframe) Keyframe.ofObject(1f, values[0]);    } else {      keyframes[0] = (ObjectKeyframe) Keyframe.ofObject(0f, values[0]);      for (int i = 1; i < numKeyframes; ++i) {        keyframes[i] = (ObjectKeyframe) Keyframe.ofObject((float) i / (numKeyframes - 1), values[i]);      }    }    return new KeyframeSet(keyframes);  }

我們終于看到了一個比較熟悉的類,KeyFrame,這個叫做關鍵幀的類終于出現了,我們簡單分析一下這個方法:

首先創建了一個至少為兩位的ObjectKeyFrame對象,然后對values的長度進行判斷,如果只有一個值,那么就將唯一的一個值添加到最后一位(此時也就是第二位),否則就依次添加。最后將ObjectKeyFrame的數組轉換成KeyFrameSet類型返回。

現在我們回到PropertyValueHolder的setObjectValues方法中,接下來我們要看一下setEvaluator方法(需要在KeyFrameSet中查看)

KeyFrameSet.setEvaluator方法:

  public void setEvaluator(TypeEvaluator evaluator) {    mEvaluator = evaluator;  }

這個不用多說,直接過。

現在我們的PropertyValueHolder的ofObject方法已經看完了,我們跳回anim.setObjectValues方法,看一下setValues方法:

setValues:

  public void setValues(PropertyValuesHolder... values) {    int numValues = values.length;    mValues = values;    mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);    for (int i = 0; i < numValues; ++i) {      PropertyValuesHolder valuesHolder = values[i];      mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);    }    // New property/values/target should cause re-initialization prior to starting    mInitialized = false;  }

這個完全就是我們剛才說的儲存PropertyValueHolder的兩個屬性mValues和mValuesMap添加數據的過程,過。

現在我們只差最后一個大方法了,anim.setEvaluator了,激動?。。?/p>

anim.setEvaluator方法:

  public void setEvaluator(TypeEvaluator value) {    if (value != null && mValues != null && mValues.length > 0) {      mValues[0].setEvaluator(value);    }  }

這個方法是給每個PropertyValueHolder對象都執行setEvaluator方法,我們點進去這個方法看一下:

PropertyValueHolder.setEvaluator方法:

  public void setEvaluator(TypeEvaluator evaluator) {    mEvaluator = evaluator;    mKeyframes.setEvaluator(evaluator);  }

又進入了Keyframes的setEvaluator,我們接著看一下KeyFrameSet的setEvaluator方法:

KeyFrameSet.setEvaluator方法:

  public void setEvaluator(TypeEvaluator evaluator) {    mEvaluator = evaluator;  }

這個方法不用說了。

最后我們返回了創建的anim的對象,到現在為止,我們得到我們想要的ObjectAnimator對象了。

這個過程是有點繁瑣,我們現在屢一下思路:

調用了ObjectAnimator.ofObject之后

  1. 首先new一個ObjectAnimator對象,進入ObjectAnimator的構造方法中:在構造方法中,我們執行了兩個方法:setTarget和setPropertyName。
  2. 然后調用了ObjectAnimator的setObjectValues方法:在這個方法中我們首先實例化了PropertyValueHolder對象,然后調用setValues方法將PropertyValueHolder傳入。
  3. 之后調用了ObjectAnimator的setEvaluator方法:添加了估值器。
  4. 最后返回了ObjectAnimator對象。

到這里我們就完成了ObjectAnimator對象實例的創建。

到這里創建部分就全部完成了,接下來我們看一下添加屬性,這個就很簡單了。

添加屬性

我們就舉一個方法為例吧,拿setInterpolator方法為例:

  public void setInterpolator(TimeInterpolator value) {    if (value != null) {      mInterpolator = value;    } else {      mInterpolator = new LinearInterpolator();    }  }

這個方法是我們添加插值器的方法,我們注意到他只是給mInterpolator賦值而已,如果傳入為空,則添加線性插值器。

其他的添加屬性的方法,像setDuration、setRepeatCount等都是如此,大家下去就自己看一下吧。

由于還不會用 starUML,所以現在還沒發畫一張時序圖(只是手畫的,估計大家也不想看哈哈),等學完UML之后會給大家補上的,希望這篇文章大家喜歡。

ObjectAnimator,屬性,動畫,源碼

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對VEVB武林網的支持。如果你想了解更多相關內容請查看下面相關鏈接


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩免费在线观看视频| 国产91精品久| 日韩中文字幕视频在线观看| 日韩成人在线免费观看| 北条麻妃久久精品| 狠狠躁夜夜躁人人爽天天天天97| 日韩激情在线视频| 亚洲偷欧美偷国内偷| 中文字幕日本精品| 97国产真实伦对白精彩视频8| 亚洲新声在线观看| 欧美猛交ⅹxxx乱大交视频| 亲子乱一区二区三区电影| 亚洲精品国产电影| 91精品国产综合久久香蕉| 久久精品国产久精国产思思| 亚洲国产精品电影| 亚洲精品乱码久久久久久金桔影视| 久久不射电影网| 欧美日韩国产一区中文午夜| 国产亚洲精品综合一区91| 91chinesevideo永久地址| 中文字幕亚洲综合久久筱田步美| 亚洲欧美日韩国产中文| 久久久久久久久久亚洲| 在线观看欧美日韩| 国产精品视频成人| 久久久精品国产一区二区| 69久久夜色精品国产69乱青草| 欧美精品videofree1080p| 欧美电影免费观看高清| 中文字幕一区日韩电影| 欧美极品少妇xxxxⅹ裸体艺术| 国产精品久久久久久久久免费看| 欧美黑人一级爽快片淫片高清| 欧美成人精品激情在线观看| 国产一区深夜福利| 中文字幕亚洲无线码在线一区| 国产热re99久久6国产精品| 国产精品美女呻吟| 亚洲小视频在线| 久久欧美在线电影| 国产精品视频区1| 欧美成人第一页| 欧美韩国理论所午夜片917电影| 亚洲精品国产精品乱码不99按摩| 亚洲一级黄色片| 在线成人中文字幕| 国产日韩视频在线观看| 欧美久久久精品| 亚洲二区中文字幕| 最近2019中文免费高清视频观看www99| 色综合久久88色综合天天看泰| 国产精品久久久久久久久免费看| 一本色道久久综合狠狠躁篇怎么玩| 久久综合伊人77777蜜臀| 国产欧美精品日韩精品| 美女久久久久久久久久久| 国产精品久久久久久久久免费| 一区二区三区四区精品| 欧美精品在线免费观看| 一本色道久久88精品综合| 亚洲精品福利免费在线观看| 国产精品偷伦免费视频观看的| 九九精品在线视频| 成人国产精品久久久久久亚洲| 国产精品高清在线观看| 亚洲精品色婷婷福利天堂| 日韩在线免费观看视频| 青青草原成人在线视频| 久久人人爽人人爽人人片av高清| 日韩免费精品视频| 国产91露脸中文字幕在线| 亚洲综合成人婷婷小说| 日韩在线播放视频| 国产精品一区二区三区免费视频| 亚洲娇小xxxx欧美娇小| 欧美激情亚洲国产| 精品免费在线视频| 97精品久久久中文字幕免费| 久久久久久有精品国产| www国产亚洲精品久久网站| 日韩欧美一区二区三区久久| 国产亚洲精品美女久久久| 国产精品午夜视频| 午夜免费日韩视频| 日本久久久久久久久久久| 欧美激情高清视频| 黑人狂躁日本妞一区二区三区| 欧美激情乱人伦一区| 动漫精品一区二区| 久久国产精品电影| 青青草一区二区| 久久97久久97精品免视看| 成人看片人aa| 亚洲精选一区二区| 国产成人精品一区二区在线| 久久影视电视剧免费网站清宫辞电视| 国产精品久久久久久久久久尿| 亚洲免费av网址| 欧美自拍大量在线观看| 国产精品综合网站| 久久久精品国产亚洲| 国产精品美乳在线观看| 亚洲国产欧美一区二区三区久久| 亚洲国产成人精品久久久国产成人一区| 亚洲电影中文字幕| 国产97人人超碰caoprom| 欧美大片大片在线播放| 91精品国产91久久久久福利| 国产精品视频内| 超薄丝袜一区二区| 亚洲sss综合天堂久久| 欧美在线日韩在线| 日韩欧美国产网站| 欧美激情精品久久久久久久变态| 韩国19禁主播vip福利视频| 国产精品wwww| 九九热在线精品视频| 色哟哟亚洲精品一区二区| 国产精品福利久久久| 中文字幕亚洲无线码在线一区| 亚洲欧美在线免费观看| 亚洲一区美女视频在线观看免费| 亚洲毛茸茸少妇高潮呻吟| 国产一区二区日韩| 成人国产精品免费视频| 欧美肥臀大乳一区二区免费视频| 亚洲成人网在线| 国产成人激情小视频| 91在线色戒在线| 韩国一区二区电影| 久久精品国产99国产精品澳门| 中文字幕精品在线视频| 亚洲福利在线播放| 中文字幕欧美精品日韩中文字幕| 久久综合久中文字幕青草| 欧美精品做受xxx性少妇| 成人国内精品久久久久一区| 日韩大陆欧美高清视频区| 亚洲国产福利在线| 国产精品99久久99久久久二8| 最新国产成人av网站网址麻豆| 欧美大片免费观看在线观看网站推荐| 91亚洲国产成人久久精品网站| 中文字幕亚洲二区| 久久夜精品va视频免费观看| 懂色aⅴ精品一区二区三区蜜月| 国产精品九九久久久久久久| 国产日韩亚洲欧美| 91精品国产自产在线观看永久| 亚洲欧美在线免费| 中文在线不卡视频| 欧美在线中文字幕| 亚洲免费av电影| 97超级碰碰碰久久久| 成人福利免费观看| 中文字幕精品一区久久久久| 亚洲色图国产精品| 欧美激情视频播放| 日韩中文字幕视频| 欧美一级电影免费在线观看| 日韩免费观看在线观看| 国内伊人久久久久久网站视频|