New UI-<ViewStub>标签延时加载布局
——转载请注明出处:coder-pig,欢迎转载,请勿用于商业用途!
小猪Android开发交流群已建立,欢迎大家加入,无论是新手,菜鸟,大神都可以,小猪一个人的
力量毕竟是有限的,写出来的东西肯定会有很多纰漏不足,欢迎大家指出,集思广益,让小猪的博文
更加的详尽,帮到更多的人,O(∩_∩)O谢谢!
小猪Android开发交流群:小猪Android开发交流群群号:421858269
新Android UI实例大全目录:http://blog.csdn.net/coder_pig/article/details/42145907
本节引言:
学习完上一节的include布局复用以后,相信大家都体会到了布局优化的好处,
不过当我们include的布局是一些复杂控件的话,而这些控件我们在实际使用
过程中又用得不多的话,往往会降低页面的加载速度;虽然,我们也可以为其设置
visibility = "gone"的属性,但是在inflate布局的时候,这些控件依旧会被inflate,
也就是说依旧会创建对象,会被实例化,设置属性等,依旧会耗费内存资源,
那么在本节中,我们就来介绍一个轻量级的view: ViewStub
让你的布局在你需要的时候再加载(延时加载)
好了,开始本节内容~
本节正文:
什么是ViewStub?
ViewStub是一个轻量级的View,在布局中不占用任何控件,也不参加
布局的计算与绘制(又叫渲染),可以理解为控件树上的一个占位符,
仅仅是占着那个位置,没有东西,当我们需要的时候,他才会被渲染(加载)
到主界面上,这种行为也叫做延迟加载,也有人称为"惰性的include"
在什么地方使用?
当我们的app中某个布局,我们并不需要把所有的内容都展示出来,可以隐藏一些View视图,
等需要展示的时候再加载,这个时候就可以用到ViewStub了,有点类似于visibility = "gone",
但是不会随布局进行加载,使用例子如下:(点击listview的item后才加载下方的布局)
怎么用?
1)布局中加入<ViewStub标签>
- <ViewStub
- android:id="@+id/stub_add"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:inflatedId="@+id/ly_add"
- android:layout="@layout/ly_test" />
三个关键属性:
①id:设置ViewStub的引用id
②inflatedId:设置加载后的布局对应的id
③layout:要加载的那个布局
ps:第二个属性是可选的,当我们的ViewStub加载后,我们就可以直接通过findViewById(R.id.~)
找到加载的那个布局的对应的对象,~是inflatedId的id!因为ViewStub只能用一次!!!!
2)在加载布局文件的Activity中:
方法一:通过findViewById找到ViewStub对象后,调用该对象的inflate()方法:
ViewStub stub = (ViewStub) findViewById(R.id.stub_add);
stub.inflate();
方法二:通过改变ViewStub对象的visibility属性
ViewStub stub = (ViewStub) findViewById(R.id.stub_add);
stub.setVisibility(View.VISIBLE);
上面写完后,我们如果获得加载布局的对应对象的话,则要通过findViewById(R.id.inflatedId里的id);
找到对应的布局对象了:
View ly_add = (View)findViewById(R.id.ly_add);
处了上面这种写法还,还有一种写法:
因为ViewStub加载完他引用的布局后,他会从控件树中移除,
所以如果你想对引入后的布局进行相关操作的话,那么还是拿一个View来
放着这个布局吧!所以也可以用下面这种写法:
ViewStub stub = (ViewStub) findViewById(R.id.stub_add);
View view = stub.inflate();
或者:
ViewStub stub = (ViewStub) findViewById(R.id.stub_add);
View view = stub.setVisibility(View.VISIBLE);
好了,至于用哪种,你自己喜欢了!
使用ViewStub要注意的地方:
1)ViewStub只能inflate一次,之后ViewStub对象会被置空所以在编写代码
的时候,就不要使用生命周期很长的变量来引用ViewStub控件了,按照上面的教的写法即可!
2)ViewStub加载的只能是布局文件的id,而非某个View
代码示例:
从"惰性include"这个别名,我们就可以知道ViewStub和include其实是类似的
不过前者并不随着布局的渲染和渲染,而是,在我们Inflate或设置Visibility为VISIBLE时
才渲染,而且只用一次,针对的是一次性的东西,在ListView那里用得较多,
当然见仁见智,这里就演示下简单的用法吧:
效果图:
报错结束了,恩,别着急,先贴下代码:
actvitiy_main.xml:
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/LinearLayout1"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- tools:context="com.jay.example.test.MainActivity" >
- <Button
- android:id="@+id/btnLoad"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="加载ViewStub" />
- <Button
- android:id="@+id/btnHide"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="隐藏加载的布局" />
- <Button
- android:id="@+id/btnShow"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="显示加载的布局" />
- <ViewStub
- android:id="@+id/stub_add"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_gravity="center"
- android:inflatedId="@+id/ly_add"
- android:layout="@layout/ly_test" />
- </LinearLayout>
引入的布局:ly_test.xml:
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/LinearLayout1"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- tools:context="com.jay.example.test.MainActivity"
- android:gravity="center">
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@drawable/back"
- android:text="用于测试的ViewStub引入的布局"
- android:textColor="#FFFFFF"
- android:gravity="center_vertical"
- android:textSize="18sp"/>
- </LinearLayout>
MainActivity.java中的代码:
- package com.jay.example.test;
- import android.app.Activity;
- import android.os.Bundle;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.ViewStub;
- import android.widget.Button;
- public class MainActivity extends Activity {
- private Button btnLoad;
- private Button btnHide;
- private Button btnShow;
- private MyClick myClick;
- private ViewStub viewStub;
- private View view;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- findViews();
- setUpViews();
- }
- private void findViews() {
- btnLoad = (Button) findViewById(R.id.btnLoad);
- btnHide = (Button) findViewById(R.id.btnHide);
- btnShow = (Button) findViewById(R.id.btnShow);
- }
- private void setUpViews() {
- myClick = new MyClick();
- btnLoad.setOnClickListener(myClick);
- btnHide.setOnClickListener(myClick);
- btnShow.setOnClickListener(myClick);
- }
- private class MyClick implements OnClickListener {
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.btnLoad:
- viewStub = (ViewStub) findViewById(R.id.stub_add);
- view = viewStub.inflate();
- break;
- case R.id.btnHide:
- view.setVisibility(View.INVISIBLE);
- break;
- case R.id.btnShow:
- view.setVisibility(View.VISIBLE);
- break;
- }
- }
- }
- }
代码分析:
代码很简单,要说的问题就是为什么两次加载ViewStub会报错,而且还报了
NullPointerException,这是因为ViewStub只能够inflate一次,用完就没咯
所以后面实现的隐藏和显示的实现就是控制——引入的布局对象!!!
最后说两句:
关于这个ViewStub的使用很简单但也很重要,可能你现在不觉得,但慢慢界面上控件多了,
就知道了,厚积薄发!加油~
本节参考文献:
http://www.cnblogs.com/plokmju/p/android_viewstub.html
http://blog.csdn.net/mayingcai1987/article/details/6238609
http://blog.csdn.net/hitlion2008/article/details/6737537
https://developer.android.com/reference/android/view/ViewStub.html