乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Android 著色器 Tint 研究

       萬皇之皇 2018-01-18



      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即可!


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


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



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


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


      iv1 = (ImageView) this.findViewById(R.id.iv1);

        iv2 = (ImageView) this.findViewById(R.id.iv2);

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

        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í)也很簡單:


      final Drawable originBitmapDrawable = getResources().getDrawable(R.drawable.

      ic_account_circle_black_18dp).mutate();


      修改以后 我們再看:



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


      那有人就要問了,臥槽 你這么做 不是把谷歌給我們做好的圖片內(nèi)存優(yōu)化方案給損壞了么,其實(shí)這種擔(dān)心是多余的,這個(gè)http://android-developers./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的背景色


      et1 = (EditText) this.findViewById(R.id.et);

        final Drawable originBitmapDrawable = et1.getBackground();

        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) 在這:


      // Although these fields are specific to editable text, they are not added to Editor because

        // they are defined by the TextView's style and are theme-dependent.

        int mCursorDrawableRes;


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



      /**

           * EditText specific data, created on demand when one of the Editor fields is used.

           * See {@link #createEditorIfNeeded()}.

           */

          private Editor mEditor;



      //注意這段代碼屬于editor  

      final Drawable[] mCursorDrawable = new Drawable[2];


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


      //參數(shù)就是要反射修改光標(biāo)的edittext對(duì)象

          private void invokeEditTextCallCursorDrawable(EditText et) {

              try {

                  Field fCursorDrawableRes = TextView.class.getDeclaredField('mCursorDrawableRes');

                  // 看源碼知道 這個(gè)變量不是public的 所以要設(shè)置下這個(gè)可訪問屬性

                  fCursorDrawableRes.setAccessible(true);

                  //取得 editext對(duì)象里的mCursorDrawableRes 屬性的值 看源碼知道這是一個(gè)int值

                  int mCursorDrawableRes = fCursorDrawableRes.getInt(et);

                  //下面的代碼 是通過獲取mEditor對(duì)象 然后再通過拿到的mEditor對(duì)象來獲取最終我們的mCursorDrawable這個(gè)光標(biāo)的drawable

                  Field fEditor = TextView.class.getDeclaredField('mEditor');

                  fEditor.setAccessible(true);

                  Object editor = fEditor.get(et);

                  Class?clazz = editor.getClass();

                  Field fCursorDrawable = clazz.getDeclaredField('mCursorDrawable');

                  fCursorDrawable.setAccessible(true);

                  if (mCursorDrawableRes <>0) {

                      return;

                  }

                  //到這里 我們終于拿到了默認(rèn)主題下 edittext的光標(biāo)的那個(gè)小圖標(biāo)的drawable

                  Drawable cursorDrawable = et.getContext().getResources().getDrawable(mCursorDrawableRes);

                  if (cursorDrawable == null) {

                      return;

                  }

                  //既然都拿到了這個(gè)drawble 那就修改他。

                  Drawable tintDrawable = tintDrawable(cursorDrawable, ColorStateList.valueOf(Color.GREEN));

                  //前面貼出的mCursorDrawable源碼 可以知道 這是一個(gè)二維數(shù)組。所以我們要構(gòu)造出一個(gè)全新的二維數(shù)組

                  Drawable[] drawables = new Drawable[]{tintDrawable, tintDrawable};

                  //然后再通過反射 把這個(gè)二維數(shù)組的值 放到editor里面 即可!

                  fCursorDrawable.set(editor, drawables);

              } catch (NoSuchFieldException e) {

                  e.printStackTrace();

              } catch (IllegalAccessException e) {

                  e.printStackTrace();

              }

       

          }


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



      很完美 對(duì)吧~~


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


      public static Drawable tintDrawable(Drawable drawable, ColorStateList colors) {

              final Drawable wrappedDrawable = DrawableCompat.wrap(drawable);

              DrawableCompat.setTintList(wrappedDrawable, colors);

              return wrappedDrawable;

          }


      當(dāng)然你也可以用http:///blog/2015/tinting_drawables/ 這個(gè)文章里的方法來做向下兼容:


      public final class TintedBitmapDrawable extends BitmapDrawable {

        private int tint;

        private int alpha;

       

        public TintedBitmapDrawable(final Resources res, final Bitmap bitmap, final int tint) {

          super(res, bitmap);

          this.tint = tint;

          this.alpha = Color.alpha(tint);

        }

       

        public TintedBitmapDrawable(final Resources res, final int resId, final int tint) {

          super(res, BitmapFactory.decodeResource(res, resId));

          this.tint = tint;

          this.alpha = Color.alpha(tint);

        }

       

        public void setTint(final int tint) {

          this.tint = tint;

          this.alpha = Color.alpha(tint);

        }

       

        @Override public void draw(final Canvas canvas) {

          final Paint paint = getPaint();

          if (paint.getColorFilter() == null) {

            paint.setColorFilter(new LightingColorFilter(tint, 0));

            paint.setAlpha(alpha);

          }

          super.draw(canvas);

        }

      }





        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請遵守用戶 評(píng)論公約

        類似文章 更多