不使用屬性動(dòng)畫(huà)难礼,通過(guò)反射設(shè)置Vector的屬性

最近看到一篇文章介紹Vector兼容方案的吱七。參考http://www.reibang.com/p/e3614e7abc03

嘗試寫(xiě)了下Demo感覺(jué)還不錯(cuò),但是遇到一個(gè)問(wèn)題鹤竭,需要Vector的顏色需要?jiǎng)討B(tài)調(diào)整踊餐,前面的文章里通過(guò)屬性動(dòng)畫(huà)一步步是可以實(shí)現(xiàn)這個(gè)效果的,但我只是改個(gè)顏色又是要寫(xiě)xml又是要用動(dòng)畫(huà)臀稚,這有點(diǎn)大炮打蚊子了吝岭,而且動(dòng)畫(huà)持續(xù)時(shí)間設(shè)置多少算合適?屬性動(dòng)畫(huà)肯定不是優(yōu)雅的解決方案吧寺。屬性動(dòng)畫(huà)無(wú)非就是反射窜管,既然屬性動(dòng)畫(huà)能修改的,那我們自己通過(guò)反射肯定也是可以修改的稚机。
這篇文章就是介紹下如何避免使用屬性動(dòng)畫(huà)幕帆,來(lái)修改VectorDrawable的屬性。其實(shí)整個(gè)過(guò)程就是查找需要反射的屬性路徑的過(guò)程赖条,只要知道什么是反射失乾,基本沒(méi)什么難度。

既然是反射纬乍,那怎么反射呢碱茁?既然有源碼,跟進(jìn)源碼看看AnimatedVectorDrawable具體是如何操作的仿贬。

<code>
Drawable drawable = imageView.getDrawable();
if (drawable instanceof Animatable) {
((Animatable) drawable).start();
}
</code>

上面是前面文章給的開(kāi)啟Vector動(dòng)畫(huà)的代碼纽竣。我們跟進(jìn)start看看。很不幸是個(gè)接口茧泪。這時(shí)候怎么辦蜓氨?直接debug watch drawable的真實(shí)類,或者打印日志drawable.getClass().toString()看下真實(shí)的類队伟。

Paste_Image.png

這里debug看到drawable其實(shí)是一個(gè)AnimatedVectorDrawable(注意這里Api21以前是兼容包的類穴吹,這里因?yàn)槲业氖謾C(jī)是6.0所以這里是AnimatedVectorDrawable,其實(shí)原理完全一樣)缰泡;
跟進(jìn)AnimatedVectorDrawable的start方法
<code>
@Override
public void start() {
ensureAnimatorSet();
// If any one of the animator has not ended, do nothing.
if (isStarted()) {
return;
}
mAnimatorSet.start();
invalidateSelf();
}
</code>
東西全出來(lái)了刀荒。看見(jiàn)mAnimatorSet.start();寫(xiě)過(guò)屬性動(dòng)畫(huà)棘钞,應(yīng)該會(huì)非常熟悉缠借。跟進(jìn)ensureAnimatorSet方法
<code>
private void ensureAnimatorSet() {
if (!mHasAnimatorSet) {
mAnimatedVectorState.prepareLocalAnimators(mAnimatorSet, mRes);
mHasAnimatorSet = true;
mRes = null;
}
}
</code>
沒(méi)什么好想的,繼續(xù)跟進(jìn)prepareLocalAnimators方法宜猜,
<code>
public void prepareLocalAnimators(@NonNull AnimatorSet animatorSet,
@Nullable Resources res) {
// Check for uninflated animators. We can remove this after we add
// support for Animator.applyTheme(). See comments in inflate().
if (mPendingAnims != null) {
// Attempt to load animators without applying a theme.
if (res != null) {
inflatePendingAnimators(res, null);
} else {
Log.e(LOGTAG, "Failed to load animators. Either the AnimatedVectorDrawable" + " must be created using a Resources object or applyTheme() must be" + " called with a non-null Theme object.");
}
mPendingAnims = null;
}
// Perform a deep copy of the constant state's animators.
final int count = mAnimators == null ? 0 : mAnimators.size();
if (count > 0) {
final Animator firstAnim = prepareLocalAnimator(0);
final AnimatorSet.Builder builder = animatorSet.play(firstAnim);
for (int i = 1; i < count; ++i) {
final Animator nextAnim = prepareLocalAnimator(i);
builder.with(nextAnim);
}
}
}
</code>
這時(shí)候如果眼睛亮的話泼返,應(yīng)該會(huì)直接看見(jiàn)這一行
<code>
final Animator firstAnim = prepareLocalAnimator(0);
</code>
prepareLocalAnimator這里返回了一個(gè)Animator,跟進(jìn)prepareLocalAnimator方法姨拥。
<code>
private Animator prepareLocalAnimator(int index) {
final Animator animator = mAnimators.get(index);
final Animator localAnimator = animator.clone();
final String targetName = mTargetNameMap.get(animator);
final Object target = mVectorDrawable.getTargetByName(targetName);
localAnimator.setTarget(target);
return localAnimator;
}
</code>
一下子就豁然開(kāi)朗了绅喉,
<code>
final Object target = mVectorDrawable.getTargetByName(targetName);
</code>
這一行IDE報(bào)了紅線渠鸽,表示這個(gè)方法不可訪問(wèn)。VectorDrawable里其實(shí)有這個(gè)方法
<code>
Object getTargetByName(String name) {
return mVectorState.mVPathRenderer.mVGTargetsMap.get(name);
}
</code>
好多層柴罐。我們跟到mVGTargetsMap那里看看那里有什么徽缚。可惜的是這個(gè)Map保存是Object類型革屠,這時(shí)候我們可以繼續(xù)debug watch這個(gè)Map查看里面的Object的運(yùn)行時(shí)的實(shí)際類型凿试,不過(guò)向下掃一眼看到了mVGTargetsMap所在的類叫VPathRenderer,這個(gè)類的構(gòu)造方法是這個(gè):
<code>
public VPathRenderer(VPathRenderer copy) {
mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap);
mPath = new Path(copy.mPath);
mRenderPath = new Path(copy.mRenderPath);
mBaseWidth = copy.mBaseWidth;
mBaseHeight = copy.mBaseHeight;
mViewportWidth = copy.mViewportWidth;
mViewportHeight = copy.mViewportHeight;
mOpticalInsets = copy.mOpticalInsets;
mChangingConfigurations = copy.mChangingConfigurations;
mRootAlpha = copy.mRootAlpha;
mRootName = copy.mRootName;
mTargetDensity = copy.mTargetDensity;
if (copy.mRootName != null) {
mVGTargetsMap.put(copy.mRootName, this);
}
}
</code>
倒數(shù)第三行put了this似芝,這表示返回的target其實(shí)就是當(dāng)前類那婉。當(dāng)前類保存在Map里浓恳,然后Map會(huì)通過(guò)
<code>
Object getTargetByName(String name) {
return mVectorState.mVPathRenderer.mVGTargetsMap.get(name);
}
</code>
返回作為Animator的tartget并闲,這時(shí)候想到了什么?屬性動(dòng)畫(huà)原理就是反射getset晰绎,那這個(gè)類非衬椋可能就有mFillColor屬性或者setFillColor方法呛谜。command+F12輸入setfil

Paste_Image.png

好吧,終于發(fā)現(xiàn)你了蝇闭。
<code>
@SuppressWarnings("unused")
void setFillColor(int fillColor) {
mFillColor = fillColor;
}
</code>
其實(shí)不光是fillColor其他的屬性也全部都有呻率。
<code>
int mStrokeColor = Color.TRANSPARENT;
float mStrokeWidth = 0;
int mFillColor = Color.TRANSPARENT;
float mStrokeAlpha = 1.0f;
int mFillRule;
float mFillAlpha = 1.0f;
float mTrimPathStart = 0;
float mTrimPathEnd = 1;
float mTrimPathOffset = 0;
Paint.Cap mStrokeLineCap = Paint.Cap.BUTT;
Paint.Join mStrokeLineJoin = Paint.Join.MITER;
float mStrokeMiterlimit = 4;
</code>
到這里剩下的應(yīng)該就不用說(shuō)了,思路基本已經(jīng)有了呻引,剩下的就簡(jiǎn)單了,無(wú)非就是敲鍵盤(pán)了吐咳。如果你不想敲也可以參考這里:
https://github.com/aesean/VectorHelper/blob/master/VectorHelper
保留作者逻悠,保留原始鏈接后,歡迎轉(zhuǎn)載韭脊。原始鏈接:http://www.reibang.com/p/2db6a5ce871b

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末童谒,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子沪羔,更是在濱河造成了極大的恐慌饥伊,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔫饰,死亡現(xiàn)場(chǎng)離奇詭異琅豆,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)篓吁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)茫因,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人杖剪,你說(shuō)我怎么就攤上這事冻押〕鄞” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵洛巢,是天一觀的道長(zhǎng)括袒。 經(jīng)常有香客問(wèn)我,道長(zhǎng)稿茉,這世上最難降的妖魔是什么锹锰? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮狈邑,結(jié)果婚禮上城须,老公的妹妹穿的比我還像新娘。我一直安慰自己米苹,他們只是感情好糕伐,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著蘸嘶,像睡著了一般良瞧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上训唱,一...
    開(kāi)封第一講書(shū)人閱讀 52,394評(píng)論 1 310
  • 那天褥蚯,我揣著相機(jī)與錄音,去河邊找鬼况增。 笑死赞庶,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的澳骤。 我是一名探鬼主播歧强,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼为肮!你這毒婦竟也來(lái)了摊册?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤颊艳,失蹤者是張志新(化名)和其女友劉穎茅特,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體棋枕,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡白修,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了戒悠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片熬荆。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出卤恳,到底是詐尸還是另有隱情累盗,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布突琳,位于F島的核電站若债,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏拆融。R本人自食惡果不足惜蠢琳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望镜豹。 院中可真熱鬧傲须,春花似錦、人聲如沸趟脂。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)昔期。三九已至已卸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間硼一,已是汗流浹背累澡。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留般贼,地道東北人愧哟。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像哼蛆,于是被迫代替她去往敵國(guó)和親翅雏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 1 背景 不能只分析源碼呀人芽,分析的同時(shí)也要整理歸納基礎(chǔ)知識(shí),剛好有人微博私信讓全面說(shuō)說(shuō)Android的動(dòng)畫(huà)绩脆,所以今...
    未聞椛洺閱讀 2,716評(píng)論 0 10
  • 屬性動(dòng)畫(huà)的集成關(guān)系Paste_Image.png 看一段屬性動(dòng)畫(huà)的使用代碼 跟進(jìn)ObjectAnimator.of...
    明朗__閱讀 7,411評(píng)論 0 2
  • Animation Animation類是所有動(dòng)畫(huà)(scale萤厅、alpha、translate靴迫、rotate)的基...
    四月一號(hào)閱讀 1,923評(píng)論 0 10
  • 學(xué)習(xí)力這東西也真的需要靈感!除了日常生活中已經(jīng)習(xí)慣的各種學(xué)習(xí)力惕味,想創(chuàng)新,還得要寶寶接受玉锌,真的很不容易! 今天么名挥,寶...
    幽香_5126閱讀 163評(píng)論 0 0
  • 濟(jì)寧的天氣很燦爛 早上搭載順風(fēng)車(chē) 沿途的春光很美 路過(guò)太白湖的時(shí)候覺(jué)得有時(shí)間的話到此一游還是極好的 …… 不過(guò)比欣...
    金瀾愛(ài)寫(xiě)作閱讀 148評(píng)論 0 0