自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Android著色器Tint研究

移動(dòng)開發(fā) Android
Tint 這個(gè)東西 主要用來減少apk體積的,比如說我現(xiàn)在有一個(gè)textview,他的背景圖 有兩種,一種是當(dāng)獲得焦點(diǎn)時(shí)顯示的a圖,另一種是 失去焦點(diǎn)時(shí)顯示的b圖。如果要適配分辨率的話 很有可能圖片會(huì)更多,而且在切換的時(shí)候 因?yàn)槭侵匦录虞d一次bitmap 效率也會(huì)下降很多。所以谷歌就給了一套解決方案 這個(gè)就是tint了。

Tint 這個(gè)東西 主要用來減少apk體積的,比如說我現(xiàn)在有一個(gè)textview,他的背景圖 有兩種,一種是當(dāng)獲得焦點(diǎn)時(shí)顯示的a圖,另一種是 失去焦點(diǎn)時(shí)顯示的b圖。

相信大家開發(fā)的時(shí)候 這種需求做過很多次了,我們一般都會(huì)發(fā)現(xiàn) 這種a圖和b圖 除了顏色不一樣,其他都是一樣的,但是我們做的時(shí)候呢,通常是找ui要了兩張圖。

如果要適配分辨率的話 很有可能圖片會(huì)更多,而且在切換的時(shí)候 因?yàn)槭侵匦录虞d一次bitmap 效率也會(huì)下降很多。所以谷歌就給了一套解決方案 這個(gè)就是tint了。

他的目的就是當(dāng)你發(fā)現(xiàn)有這種需求的時(shí)候,只需要 放一張圖 在apk里即可,當(dāng)你需要改變背景圖的顏色的時(shí)候 就用Tint即可!

下面就來簡(jiǎn)單說一下,tint的使用 以及需要注意的地方。

首先 我們定義一個(gè)簡(jiǎn)單的布局文件: 

 

 

 

我們發(fā)現(xiàn)這2個(gè)imageview 都是引用的同樣一個(gè)drawable資源,并且 在studio這個(gè)xml編輯界面里面 我們很明顯的 能看出來 這個(gè)圖片的顏色是黑色的 對(duì)吧!

那 現(xiàn)在 我們想改一下,想把iv1 這個(gè)imageview的 背景色 改成綠色的! 我們想當(dāng)然的 當(dāng)然會(huì)這么寫:

  1. iv1 = (ImageView) this.findViewById(R.id.iv1); 
  2.   iv2 = (ImageView) this.findViewById(R.id.iv2); 
  3.   final Drawable originBitmapDrawable = getResources().getDrawable(R.drawable.ic_account_circle_black_18dp); 
  4.   iv1.setImageDrawable(tintDrawable(originBitmapDrawable, ColorStateList.valueOf(Color.GREEN))); 

 應(yīng)該很好理解對(duì)吧,代碼就不解釋了。但是我們運(yùn)行以后發(fā)現(xiàn): 

 

 

 

臥槽 怎么2個(gè)都變綠色了!

回顧一下 我們的代碼 我們應(yīng)該能明白 2個(gè)imageview 都是引用的同樣的一個(gè)drawable,要知道 既然是一個(gè)drawable,那系統(tǒng)肯定為了優(yōu)化資源 把這2個(gè)drawable 在內(nèi)存里的拷貝弄成了一份!

還記得 我們以前講的bitmap優(yōu)化那篇么?http://www.cnblogs.com/punkisnotdead/p/4881771.html 和這個(gè)里面的inBitmap 屬性有異曲同工之妙,如果還不理解 你看下面的圖就理解了: 

 

 

 

所以才會(huì)造成上面的情況。你修改了共同變量,所以2個(gè)圖就都被影響了。

解決方法 其實(shí)也很簡(jiǎn)單:

  1. final Drawable originBitmapDrawable = getResources().getDrawable(R.drawable. 
  2. ic_account_circle_black_18dp).mutate();  

修改以后 我們?cè)倏矗?nbsp;

 

 

 

你看這么做就一切正常了。

那有人就要問了,臥槽 你這么做 不是把谷歌給我們做好的圖片內(nèi)存優(yōu)化方案給損壞了么,其實(shí)這種擔(dān)心是多余的,這個(gè)http://android-developers.blogspot.hk/2009/05/drawable-mutations.html

這個(gè)地址會(huì)告訴你 其實(shí)我們做 只是把單獨(dú)的受到影響的那部分 內(nèi)存給單獨(dú)拿出來了,其他沒受到影響的還是共享的數(shù)據(jù)!換句話說 我們內(nèi)存里 會(huì)另外存放的就是一些純的標(biāo)志位 之類的 類似于狀態(tài)值這種東西。

大部分的內(nèi)存還是公用的!

然后接著來,我們看下一個(gè)例子 關(guān)于editext的。 

 

 

 

你看這個(gè)edittext 的顏色是這樣的。那現(xiàn)在我們來修改一下 這個(gè)edittext的背景色

  1. et1 = (EditText) this.findViewById(R.id.et); 
  2.   final Drawable originBitmapDrawable = et1.getBackground(); 
  3.   et1.setBackgroundDrawable(tintDrawable(originBitmapDrawable, ColorStateList.valueOf(Color.GREEN))); 

  

 

 

 

背景色是修改成功了 但是這個(gè)光標(biāo)的顏色 還沒變 非常不協(xié)調(diào), 有人又要說了 我們可以用: 

 

 

 

這個(gè)xml 屬性來修改呀,當(dāng)然了這個(gè)方法確實(shí)是可以的 但是你想 你這么做的話 又要增加資源文件了,不是與我們的tint 背道而馳了么?

所以 這個(gè)地方 我們就要想辦法 突破一下。其實(shí)很多人都能想到方法了,對(duì)于android 沒有 提供給我們的api 比如那些private 函數(shù),

我們通常都是通過反射的方法 去調(diào)用的。 這里也是一樣,稍微想一下 我們就能明白, 這個(gè)地方 我們就先通過反射來獲取到這個(gè)cursorDrawable

然后給他著色,然后在反射調(diào)用方法 給他set進(jìn)去不就行了么?

首先我們都知道 editext 實(shí)際上就是textview,所以我們看一下textview 的源碼 找找看 這個(gè)屬性到底叫啥名字。經(jīng)過一番努力發(fā)現(xiàn) 在這:

  1. // Although these fields are specific to editable text, they are not added to Editor because 
  2.   // they are defined by the TextView's style and are theme-dependent. 
  3.   int mCursorDrawableRes;  

并且我們要看下editor的源碼 這是和edittext息息相關(guān)的:

  1. /** 
  2.      * EditText specific data, created on demand when one of the Editor fields is used. 
  3.      * See {<a href="http://www.jobbole.com/members/57845349">@link</a> #createEditorIfNeeded()}. 
  4.      */ 
  5.     private Editor mEditor; 
  6.  
  7.  
  8. //注意這段代碼屬于editor   
  9. final Drawable[] mCursorDrawable = new Drawable[2];  

有了這段代碼 我們就知道 剩下反射的代碼怎么寫了。 

  1. //參數(shù)就是要反射修改光標(biāo)的edittext對(duì)象 
  2.     private void invokeEditTextCallCursorDrawable(EditText et) { 
  3.         try { 
  4.             Field fCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes"); 
  5.             // 看源碼知道 這個(gè)變量不是public的 所以要設(shè)置下這個(gè)可訪問屬性 
  6.             fCursorDrawableRes.setAccessible(true); 
  7.             //取得 editext對(duì)象里的mCursorDrawableRes 屬性的值 看源碼知道這是一個(gè)int值 
  8.             int mCursorDrawableRes = fCursorDrawableRes.getInt(et); 
  9.             //下面的代碼 是通過獲取mEditor對(duì)象 然后再通過拿到的mEditor對(duì)象來獲取最終我們的mCursorDrawable這個(gè)光標(biāo)的drawable 
  10.             Field fEditor = TextView.class.getDeclaredField("mEditor"); 
  11.             fEditor.setAccessible(true); 
  12.             Object editor = fEditor.get(et); 
  13.             Class<?> clazz = editor.getClass(); 
  14.             Field fCursorDrawable = clazz.getDeclaredField("mCursorDrawable"); 
  15.             fCursorDrawable.setAccessible(true); 
  16.             if (mCursorDrawableRes <= 0) { 
  17.                 return
  18.             } 
  19.             //到這里 我們終于拿到了默認(rèn)主題下 edittext的光標(biāo)的那個(gè)小圖標(biāo)的drawable 
  20.             Drawable cursorDrawable = et.getContext().getResources().getDrawable(mCursorDrawableRes); 
  21.             if (cursorDrawable == null) { 
  22.                 return
  23.             } 
  24.             //既然都拿到了這個(gè)drawble 那就修改他。 
  25.             Drawable tintDrawable = tintDrawable(cursorDrawable, ColorStateList.valueOf(Color.GREEN)); 
  26.             //前面貼出的mCursorDrawable源碼 可以知道 這是一個(gè)二維數(shù)組。所以我們要構(gòu)造出一個(gè)全新的二維數(shù)組 
  27.             Drawable[] drawables = new Drawable[]{tintDrawable, tintDrawable}; 
  28.             //然后再通過反射 把這個(gè)二維數(shù)組的值 放到editor里面 即可! 
  29.             fCursorDrawable.set(editor, drawables); 
  30.         } catch (NoSuchFieldException e) { 
  31.             e.printStackTrace(); 
  32.         } catch (IllegalAccessException e) { 
  33.             e.printStackTrace(); 
  34.         } 
  35.   
  36.     }  

***調(diào)用這個(gè)方法以后看一下效果:

 

很*** 對(duì)吧~~

***tintDrawable這個(gè)方法是用來向下兼容用的。你如果不考慮向下兼容的問題 用系統(tǒng)自帶的方法 就可以了,這里就不做過多介紹了。

  1. public static Drawable tintDrawable(Drawable drawable, ColorStateList colors) { 
  2.         final Drawable wrappedDrawable = DrawableCompat.wrap(drawable); 
  3.         DrawableCompat.setTintList(wrappedDrawable, colors); 
  4.         return wrappedDrawable; 
  5.     }  

當(dāng)然你也可以用http://andraskindler.com/blog/2015/tinting_drawables/ 這個(gè)文章里的方法來做向下兼容:public final class TintedBitmapDrawable extends BitmapDrawable { 

  1.   private int tint; 
  2.   private int alpha; 
  3.   
  4.   public TintedBitmapDrawable(final Resources res, final Bitmap bitmap, final int tint) { 
  5.     super(res, bitmap); 
  6.     this.tint = tint; 
  7.     this.alpha = Color.alpha(tint); 
  8.   } 
  9.   
  10.   public TintedBitmapDrawable(final Resources res, final int resId, final int tint) { 
  11.     super(res, BitmapFactory.decodeResource(res, resId)); 
  12.     this.tint = tint; 
  13.     this.alpha = Color.alpha(tint); 
  14.   } 
  15.   
  16.   public void setTint(final int tint) { 
  17.     this.tint = tint; 
  18.     this.alpha = Color.alpha(tint); 
  19.   } 
  20.   
  21.   @Override public void draw(final Canvas canvas) { 
  22.     final Paint paint = getPaint(); 
  23.     if (paint.getColorFilter() == null) { 
  24.       paint.setColorFilter(new LightingColorFilter(tint, 0)); 
  25.       paint.setAlpha(alpha); 
  26.     } 
  27.     super.draw(canvas); 
  28.   } 
  29.  
責(zé)任編輯:龐桂玉 來源: 安卓開發(fā)精選
相關(guān)推薦

2021-12-23 09:34:05

著色器編程語言軟件開發(fā)

2013-01-30 15:37:19

CSS著色器HTML5

2021-03-18 08:03:58

SteamMesa緩存

2023-10-16 15:58:54

開源Blender

2023-04-12 07:46:24

JavaScriptWebGL

2015-08-07 10:24:17

AndroidMaterialDes

2017-05-08 11:41:37

WebGLThree.js

2013-04-15 14:23:21

2023-11-15 14:15:03

開源Blender

2022-09-26 12:28:16

OpenGLAPI使用移動(dòng)應(yīng)用

2015-07-08 16:38:19

Tint Color

2023-05-06 07:23:57

2025-01-08 10:17:11

2023-03-16 14:33:23

WebGL初始化繪制

2009-12-29 16:21:46

silverlight

2019-07-10 16:45:49

LinuxLinux游戲游戲性能

2012-05-22 01:20:14

SyntaxHighlJavaScriptJava

2024-02-26 00:00:00

前端工具Space.js

2023-09-04 06:52:28

AMD銳龍GPU

2023-04-13 07:45:15

WebGL片元著色器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)