android關於TextView的drawableLeft,drawableTop,drawableRight,drawableRight的drawable大小及位置問題
阿新 • • 發佈:2019-01-24
經常在專案中我們會看到一個按鈕採用圖片及文字結合的方式來顯示介面,我們如何設計佈局了?
第一種方法:使用一個ViewGroup,在ViewGroup中新增一個ImageView和一個TextView組合來達到這種效果。
第二種方式使用Textview的drawableLeft,drawableTop,drawableRight,drawableRight來達到這種效果,但是這又有一個問題,就是不能指定drawable的大小和位置。
系統預設是顯示圖片的載入大小,可在TextView原始碼中的
public void setCompoundDrawablesWithIntrinsicBounds這個方法中看到,這個方法在其建構函式中呼叫。(@Nullable Drawable left, @Nullable Drawable top, @Nullable Drawable right, @Nullable Drawable bottom) { if (left != null) { left.setBounds(0, 0, left.getIntrinsicWidth(), left.getIntrinsicHeight()); } if (right != null) { right.setBounds(0, 0, right.getIntrinsicWidth(), right.getIntrinsicHeight());} if (top != null) { top.setBounds(0, 0, top.getIntrinsicWidth(), top.getIntrinsicHeight()); } if (bottom != null) { bottom.setBounds(0, 0, bottom.getIntrinsicWidth(), bottom.getIntrinsicHeight()); } setCompoundDrawables(left, top, right, bottom); }
最後是把這4個變數存在其內部類Drawables中,api23之前是存在Drawables中的4個成員變數中,之後是存在其mShowing中。
在api23的原始碼中,Textview的ondraw()方法中可以看到,
if (dr.mShowing[Drawables.LEFT] != null) { canvas.save(); canvas.translate(scrollX + mPaddingLeft + leftOffset, scrollY + compoundPaddingTop + (vspace - dr.mDrawableHeightLeft) / 2); dr.mShowing[Drawables.LEFT].draw(canvas); canvas.restore(); }所以我們通過反射可以,改變Drawable中的mBounds變數,以left為例:
try { Class<?> calss = Class.forName("android.widget.TextView"); Field draw = calss.getDeclaredField("mDrawables"); draw.setAccessible(true); Object obj=draw.get(mbtn); if(obj != null){ calss = obj.getClass(); if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){ draw = calss.getDeclaredField("mShowing"); draw.setAccessible(true); Object song = draw.get(obj); if(song != null){ Object[] objs = (Object[]) song; if(objs[1] != null){ Drawable top = (Drawable) objs[1]; top.setBounds(0,0,50,50); } } }else{ draw = calss.getDeclaredField("mDrawableTop"); draw.setAccessible(true); Object song = draw.get(obj); if(song != null){ Drawable top = (Drawable) song; top.setBounds(0,0,50,50); } } } draw = calss.getDeclaredField("mDrawableWidthTop"); draw.setAccessible(true); draw.set(obj,50); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); }最後還要反射Drawables的mDrawableWidthTop變數來讓圖片居中