不管是為了封裝也好,實作特殊的效果也好,大家或多或少都會進行自定義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隻是需要代碼動态設定布局屬性來保證顯示的正确。
這兩個方法在我目前為止的實踐中沒有什麼問題,希望大家多多用發現問題多拍磚,拍完一起讨論更好的解決辦法。