成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Android著色器Tint研究

移動開發 Android
Tint 這個東西 主要用來減少apk體積的,比如說我現在有一個textview,他的背景圖 有兩種,一種是當獲得焦點時顯示的a圖,另一種是 失去焦點時顯示的b圖。如果要適配分辨率的話 很有可能圖片會更多,而且在切換的時候 因為是重新加載一次bitmap 效率也會下降很多。所以谷歌就給了一套解決方案 這個就是tint了。

Tint 這個東西 主要用來減少apk體積的,比如說我現在有一個textview,他的背景圖 有兩種,一種是當獲得焦點時顯示的a圖,另一種是 失去焦點時顯示的b圖。

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

如果要適配分辨率的話 很有可能圖片會更多,而且在切換的時候 因為是重新加載一次bitmap 效率也會下降很多。所以谷歌就給了一套解決方案 這個就是tint了。

他的目的就是當你發現有這種需求的時候,只需要 放一張圖 在apk里即可,當你需要改變背景圖的顏色的時候 就用Tint即可!

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

首先 我們定義一個簡單的布局文件: 

 

 

 

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

那 現在 我們想改一下,想把iv1 這個imageview的 背景色 改成綠色的! 我們想當然的 當然會這么寫:

  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))); 

 應該很好理解對吧,代碼就不解釋了。但是我們運行以后發現: 

 

 

 

臥槽 怎么2個都變綠色了!

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

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

 

 

 

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

解決方法 其實也很簡單:

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

修改以后 我們再看: 

 

 

 

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

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

這個地址會告訴你 其實我們做 只是把單獨的受到影響的那部分 內存給單獨拿出來了,其他沒受到影響的還是共享的數據!換句話說 我們內存里 會另外存放的就是一些純的標志位 之類的 類似于狀態值這種東西。

大部分的內存還是公用的!

然后接著來,我們看下一個例子 關于editext的。 

 

 

 

你看這個edittext 的顏色是這樣的。那現在我們來修改一下 這個edittext的背景色

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

  

 

 

 

背景色是修改成功了 但是這個光標的顏色 還沒變 非常不協調, 有人又要說了 我們可以用: 

 

 

 

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

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

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

然后給他著色,然后在反射調用方法 給他set進去不就行了么?

首先我們都知道 editext 實際上就是textview,所以我們看一下textview 的源碼 找找看 這個屬性到底叫啥名字。經過一番努力發現 在這:

  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息息相關的:

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

***調用這個方法以后看一下效果:

 

很*** 對吧~~

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

  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.     }  

當然你也可以用http://andraskindler.com/blog/2015/tinting_drawables/ 這個文章里的方法來做向下兼容: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.  
責任編輯:龐桂玉 來源: 安卓開發精選
相關推薦

2021-12-23 09:34:05

著色器編程語言軟件開發

2013-01-30 15:37:19

CSS著色器HTML5

2021-03-18 08:03:58

SteamMesa緩存

2023-04-12 07:46:24

JavaScriptWebGL

2023-10-16 15:58:54

開源Blender

2015-08-07 10:24:17

AndroidMaterialDes

2017-05-08 11:41:37

WebGLThree.js

2013-04-15 14:23:21

2022-09-26 12:28:16

OpenGLAPI使用移動應用

2023-11-15 14:15:03

開源Blender

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

2025-06-03 14:14:59

智能技術AI

2019-07-10 16:45:49

LinuxLinux游戲游戲性能

2024-02-26 00:00:00

前端工具Space.js

2023-09-04 06:52:28

AMD銳龍GPU

2012-05-22 01:20:14

SyntaxHighlJavaScriptJava
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91久久精品一区二区二区 | 99精品视频免费在线观看 | 免费看爱爱视频 | 国产在线不卡 | 国产自产c区 | 国产精品福利网站 | 在线一区二区国产 | 97av视频| 国产精品久久99 | 亚洲精品一区二区三区中文字幕 | 日韩欧美天堂 | 羞羞的视频免费在线观看 | 亚洲一卡二卡 | 精品乱子伦一区二区三区 | 日韩久久中文字幕 | 欧美一区视频 | 亚洲精品www. | 亚洲国产成人精品女人久久久 | 欧美一级在线观看 | 日日天天 | 久久高清免费视频 | 91麻豆精品国产91久久久更新资源速度超快 | 毛片a区 | 日韩国产一区二区三区 | 亚洲精品电影网在线观看 | 中文日韩在线 | 亚洲国产成人av好男人在线观看 | 日本字幕在线观看 | 久久久久久国产精品mv | 中文字幕一区二区在线观看 | 国产伦精品一区二区三区照片91 | av在线免费观看不卡 | 日韩在线不卡 | 欧美色影院 | 日本精品久久久久 | 九九精品在线 | 亚洲一区二区三区视频在线 | 久热精品在线播放 | 日本精品一区二区三区在线观看视频 | 成年人在线观看视频 | 久久大全|