前言
我们经常遇到某些view或viewgroup,在一定的条件下才显示,显示的频率比较低,但是view或者viewgroup又比较复杂,比如viewgroup有很多的子view,用普通的VISIABLE,GONE的方法,我们大约需要以下几步操作
1. 把view写到layout内,inflate的时候inflate所有view
2. findview,找到有可能用到的各个view
3. 把某些view设置为gone(当然你也可以在xml里写,但是对于listview还是必须每次setVisibility,避免复用带来的bug)
针对此类场景可以用viewstub,ViewStub是一个没有尺寸大小并且不会在布局中嵌套或渲染任何东西的轻量级的视图。好处就是,我们可以第一步不inflate所有view,对于某些复杂而又显示频率低的view可以放在viewstub内部,暂时不inflate,只inflate一个viewstub。第二部的时候不需要findview所有的view,第三部的时候就没必要setvisibility所有view了
举个例子
我们想要实现一个效果,默认不出现某些视图,点击按钮才出现,这些试图的数量很多,非常复杂(这里举例为viewContent),按钮点击的概率非常低,我们先来看第一种实现方法
方法一
public class MainActivity extends BaseFishActivity {
View viewContent;
Button btn;
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewContent=findViewById(R.id.view_content);
btn = (Button) findViewById(R.id.btn_new);
tv = (TextView) findViewById(R.id.tv_new);
viewContent.setVisibility(View.GONE);
setButtonClick(R.id.btn,new View.OnClickListener() {
@Override
public void onClick(View v) {
viewContent.setVisibility(View.VISIBLE);
}
});
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<TextView android:text="@string/hello_world" android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点我让viewstub出来"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/view_content"
android:background="#00ff77"
android:orientation="vertical">
<TextView
android:id="@+id/tv_new"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是新来的" />
<Button
android:id="@+id/btn_new"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是按钮" />
</LinearLayout>
</LinearLayout>
这是最初想到的做法,我们再oncreate的时候
btn = (Button) findViewById(R.id.btn_new);
tv = (TextView) findViewById(R.id.tv_new);
这里为了demo简单只写了2个view,实际可能十几个,这些view一般都是用不到的,只有在按钮点击之后才会有意义
我们可以稍微优化下,把这些代码移到onClick内部
代码如下
public class MainActivity extends BaseFishActivity {
View viewContent;
Button btn;
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewContent=findViewById(R.id.view_content);
btn = (Button) findViewById(R.id.btn_new);
tv = (TextView) findViewById(R.id.tv_new);
viewContent.setVisibility(View.GONE);
setButtonClick(R.id.btn,new View.OnClickListener() {
@Override
public void onClick(View v) {
if(btn==null){
btn = (Button) findViewById(R.id.btn_new);
tv = (TextView) findViewById(R.id.tv_new);
}
viewContent.setVisibility(View.VISIBLE);
}
});
}
}
其实这里viewcontent可以根本不用渲染,用viewstub来代替,看下面的方案
用viewstub
public class MainActivity extends BaseFishActivity {
ViewStub vs;
View viewContent;
Button btn;
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
vs = (ViewStub) findViewById(R.id.viewstub);
setButtonClick(R.id.btn, new View.OnClickListener() {
@Override
public void onClick(View v) {
viewContent = vs.inflate();
btn = (Button) viewContent.findViewById(R.id.btn_new);
tv = (TextView) viewContent.findViewById(R.id.tv_new);
}
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00ff77"
android:orientation="vertical">
<TextView
android:id="@+id/tv_new"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是新来的" />
<Button
android:id="@+id/btn_new"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是按钮" />
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<TextView android:text="@string/hello_world" android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点我让viewstub出来"/>
<ViewStub
android:id="@+id/viewstub"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout="@layout/aa"
/>
</LinearLayout>
对于现实概率低,结构复杂的viewgroup(超过5个view),比较适合用viewstub来替代。一般来说都是用在viewgroup上的,当然你也可以用在view上,如果这个view比较复杂,渲染成本高的话,比如上面的aa.xml也可以只写一个TextView
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="teeee"/>
总结
- 对于现实概率低,结构复杂的viewgroup(超过5个view),比较适合用viewstub来替代
- 只能inflate一次,inflate完毕之后viewstub就变为null了,第二次inflate会崩溃
- viewstub的布局参数应当写到viewstub内,比如margin值,写在layout内是无效的 ,但是padding是可以写在layout内的
- Viewstub对应的布局中不能用merge
http://blog.youkuaiyun.com/androiddevelop/article/details/37556307