Android - 自定義View冷知識之動態替換layout.xml中的View
在開發迭代中,有這麼一個場景:
我們給
TextView
定製了不少功能,在下一個版本,需要把程序中的所有TextView
都替換成我自己的CustomTextView
,這個時候你會怎麼做?有沒有一種方法在不改動佈局文件的情況下就能實現動態替換呢?
原理:layout.xml -> Java 對象
首先我們知道一個 layout.xml
轉成 Java
對象,使用的是 LayoutInflater#inflate
方法。
其內部是通過 xml 解析器,解析到標籤比如: Linearlayout
,
inflate()
會調用createViewFromTag()
實例化Linearlayout
對象;createViewFromTag()
方法內部使用了一個Factory
對象;Factory
會調用Factory#onCreateView()
來實例化這個Linearlayout
。
僞代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) { ... final String name = parser.getName(); ... final View temp = createViewFromTag(root, name, inflaterContext, attrs); } View createViewFromTag(View parent, String name, Context context, AttributeSet attrs, boolean ignoreThemeAttr) { ... View view; if (mFactory2 != null) { view = mFactory2.onCreateView(parent, name, context, attrs); } else if (mFactory != null) { view = mFactory.onCreateView(name, context, attrs); } else { view = null; } ... view = createView(name, null, attrs); } |
所以我只要給 LayoutInflater
設置一個我們自定義的 Factory
就可以實現動態替換View。
1 2 3 4 5 | public void setFactory(Factory factory) { } public void setFactory2(Factory2 factory) { } |
替換方法
其實在 Activity 本身就是一個 LayoutInflater$Factory
1 2 3 4 5 6 7 | public class Activity extends ContextThemeWrapper implements LayoutInflater.Factory2, Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener, ComponentCallbacks2, Window.OnWindowDismissedCallback, WindowControllerCallback { } |
所以我們只需要實現 Activity 的 onCreateView 就可以實現 View 的動態替換。
1 2 3 4 5 6 7 8 9 | public class MyActivity extends Activity { public View onCreateView(String name, Context context, AttributeSet attrs) { if (name.equals("TextView")) { return new CustomTextView(context, attrs); } return suqer.onCreateView(name, context, attrs); } } |
插播廣告:OTCBTC 是目前最流暢、最靠譜、最好用的場外交易平臺,支持支付寶、微信、銀行卡支付購買BTC、ETH、EOS、USDT、QTUM、ZEC、GXS、BCH 等數字幣。現在註冊,即可領取比特幣紅包! https://otcbtc.com/referrals/904529093