不管是为了封装也好,实现特殊的效果也好,大家或多或少都会进行自定义View的实践,这中间又主要有两种:一种是继承于View或ViewGroup,还有一个是继承于各种已存在的Layout使用XML来写。
今天要来讨论的是第二种,实践就不详细说了,这里主要是针对这种方式带来的布局层次过深的问题提出两个方案。
第一种,注意在布局xml中使用merge,千万不要误解这个只在FrameLayout时候才能用哦,这个的准确作用是在解析XML布局时由此标志位就不解析直接将这一层忽略,将下面层次的view直接添加到上一级中。所以用完之后理所当然的会布局层次会少一层。当然了,你用来封装它的Layout需要和你本来布局XML文件想用的容器一致。
但是,注意了,忽略这里的同时,关于这一级的属性描述也会丢失,比如LinearLayout的orientation属性,比如gravity也会被还原成默认的,还有很多关键的属性哦,这就需要在封装类中通过代码来进行设置(为什么封装它的Layout需要和你本来布局XML文件想用的容器一致也是这个原因),千万不要忘记咯,不然出来的效果会很有问题的。
第二种,和上面的思想差不多,只不过是在代码中将多余的这一层去掉,先将一个封装类中的第一个子View获取出来,然后将封装类子View清空,最后将这个子View添加到上一级的ViewGroup中去,这样View层次就减少了,但是作为接口封装特性的封装类接口依然可以保持。
最后呢,一些情况下上面两种方法可以同时使用的哦,效果很明显。
举一个例子吧,把这两种情况都用上。
WrapperView.java public class WrapperView extends FrameLayout { public WrapperView(Context context) { super(context); mContext = context; // setGravity(Gravity.CENTER_HORIZONTAL); init(); } /** * @Description<br>初始化 */ private void init() { inflate(mContext, R.layout.info, this); } public void Fun1(Object o) { } public void Fun2(Object o) { } }
info.xml <?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout ................. </LinearLayout> </ScrollView> </merge>
DemoActivity.java public class DemoActivity extends Activity { private WrapperView mFView; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mFView = new WrapperView(this); View view = mFView.getChildAt(0); mFView.removeView(view); setContentView(view); } }
这个例子比较简单的,不巧的是正好都是用的FrameLayout,希望没有给大家造成只能用这个的误解。其他的Layout只是需要代码动态设置布局属性来保证显示的正确。
这两个方法在我目前为止的实践中没有什么问题,希望大家多多用发现问题多拍砖,拍完一起讨论更好的解决办法。