之前记录了自己走通 LayoutInflater
的源码整体流程,一直想搞个好玩的东西,想起之前看到过的换肤方案,决定写个换系统控件的库。
项目地址,项目的具体使用,可以看README
首先需要确定,LayoutInflater
对于Android
自带的view
读入的名字是没有全名的,具体创建的时候是通过写上前缀,然后借助反射进行实例化的
举例:
<TextView
...
/>
作为xml读入以后,是只有TextView
的
而
<dove.flyer.xu.mineView
....
/>
作为xml读入后,是整个名字存在的,即dove.flyer.xu.mineView
,具体细节前面文章已经叙述了,此处不重复了
明确,Factory
如果可以构建view
对象的话,后面的view
实例化操作是不会被进行的。
首先定位到createViewFromTag
。
源码中,以Factory
为例子,如果Factory
为空的时候,是不会执行里面代码的,如果设置了,则会执行。而执行后,如果view
不为空,则下面的view
创建都会失效,也就是说,如果Factory
创建成功了view
,那么后面创建view
部分的代码并不会执行。Facory2
也同理。
而Factory
和Factory2
在一开始就是空的,只需要设置好这个Factory
,那具体的view
创建就会被它俩其中一个接手。
View createViewFromTag(View parent, String name, AttributeSet attrs, boolean inheritContext){
....
if (mFactory2 != null) {
view = mFactory2.onCreateView(parent, name, viewContext, attrs);
} else if (mFactory != null) {
view = mFactory.onCreateView(name, viewContext, attrs);
} else {
view = null;
}
if(view == null ...){
...
}
if(view == null ...){
...
}
....
}
明确Factory
是可以被set
进去的
调用getLayoutInflater().setFactory(factory)
即可
剩下的就是考虑Activity
会在何时才会创建view
,自然是setContentView(R.layout_aa.xml)
,该方法会触发整个对应layout.xml
的inflate
所以剩下的就是在onCreate
的时候,在setContentView
之前,把自己的Factory
给设置进去,把传进来的名字,修改成自己的view
就可以了。
以上几点拼在一起就可以进行系统控件的统一替换,具体Factory
重写的细节请参考源码。
网友评论