MAIMIHO的博客

不积跬步,无以至千里;不积小流,无以成江海。

用ViewStub优化布局

Google有关ViewStub 的介绍:

“ViewStub 是一种不可视并且大小为 0 的视图,可以延迟到 运行时填充(inflate)布局资源。当 ViewStub
设置为可视或者 inflate() 方法被调用后,就会填充布局资源,然后 ViewStub 便会 被填充的视图替代。”
使用特点:

  • 最佳用途就是实现View的延迟加载,避免资源浪费,在需要的时候才加载View
  • 如果是经常要来回切换ViewStub的显示和隐藏,ViewStub就不适用

先看一个简单的代码:

MainActivity

public class MainActivity extends AppCompatActivity {
    private Button mBtnShow;
    private ViewStub mViewStub;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBtnShow = (Button) findViewById(R.id.btn_show);
        mViewStub = (ViewStub) findViewById(R.id.viewStub);
        mBtnShow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //两种方法都可以显示ViewStub中的内容
//                mViewStub.inflate();
                mViewStub.setVisibility(View.VISIBLE);
            }
        });
    }
}

activity_main.xml

<?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:orientation="vertical">

    <Button
        android:id="@+id/btn_show"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Show ViewStub"
        android:textAllCaps="false" />

    <ViewStub
        android:id="@+id/viewStub"
        android:layout="@layout/content"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:inflatedId="@+id/content_stub" />

</LinearLayout>

content.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/tv_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorAccent"
    android:text="ViewStub 是一种不可视并且大小为 0 的视图,可以延迟到 运行时填充(inflate)布局资源。当 ViewStub
设置为可视或者 inflate() 方法被调用后,就会填充布局资源,然后 ViewStub 便会 被填充的视图替代。"
    tools:showIn="@layout/activity_main" />

这就是ViewStub的简单使用

需要注意两个异常:

java.lang.IllegalArgumentException: ViewStub must have a valid layoutResource

android:layout=”@layout/content”
ViewStub标签里面用的@layout 前面是android:layout include里面是layout
写错了会抛出上面的异常

java.lang.IllegalStateException: ViewStub must have a non-null ViewGroup viewParent

当ViewStub inflate后,这个ViewStub就从View层次中移除了。(findViewById(R.id.viewStub)也会返回null)
所以MainActivity中mViewStub.inflate(); 应该这样写:

public class MainActivity extends AppCompatActivity {
    private Button mBtnShow;
    private ViewStub mViewStub;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBtnShow = (Button) findViewById(R.id.btn_show);
        mBtnShow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mViewStub = (ViewStub) findViewById(R.id.viewStub);
                if (mViewStub != null) {
                    mViewStub.inflate();
                }
            }
        });
    }
}

inflate()和setVisibility(View.VISIBLE);

这两个放到都可以显示ViewStub的视图
setVisibility(View.VISIBLE)会调用inflate()方法
inflate()方法可以返回当前的View

 View stubView = mViewStub.inflate();

ViewStub中的layout_width 和 layout_height

来上一张图:
这里写图片描述
我在ViewStub标签里面的width和height如下:

android:layout_width="match_parent"
android:layout_height="300dp"

在@layout/content中如下

android:layout_width="match_parent"
android:layout_height="match_parent"

可以看到, ViewStub标签里面的width和height属性会覆盖掉填充的布局的属性.

android:inflatedId=”@+id/content_stub”

mBtnShow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mViewStub = (ViewStub) findViewById(R.id.viewStub);
                if (mViewStub != null) {
                    mViewStub.inflate();
                    ((TextView) findViewById(R.id.content_stub)).setText("我只是一个不明真相的吃瓜群众");
                }
            }
        });

现在把 android:inflatedId=”@+id/content_stub” 去掉

mBtnShow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mViewStub = (ViewStub) findViewById(R.id.viewStub);
                if (mViewStub != null) {
                    mViewStub.inflate();
                    ((TextView) findViewById(R.id.tv_content)).setText("我只是一个不明真相的吃瓜群众");
                }
            }
        });

这里写图片描述

可以看到, android:inflatedId=”@+id/content_stub”会覆盖content.xml中根元素的id属性, 这个属性可以不添加.

再看这里

 mBtnShow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mViewStub = (ViewStub) findViewById(R.id.viewStub);
                if (mViewStub != null) {
                    ((TextView) mViewStub.inflate()).setText("我只是一个不明真相的吃瓜群众");
                }
            }
        });

可以看到, mViewStub.inflate()返回的也是content.xml中的TextView.(content.xml的根元素)

阅读更多
文章标签: Android 布局 优化
个人分类: Android Ui
上一篇Android include 细节问题
下一篇Android Merge标签
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭