Lazy inflate之ViewStub

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ethanhola/article/details/51008644

很多时候我们想要的功能是,一个view在需要它的时候让它显示,不需要它的时候不希望它显示,最常见的思路是设置view的visible属性,gone、invisible或者visible,但这个做法有个缺陷,就是无论设置哪个属性,这个layout文件都会被解析,做了很多无用功。ViewStub就是为了解决这个问题的。

ViewStub继承自View,复写了View的onMeasure方法:

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(0, 0);
    }

长高都是0,也就是说,ViewStub最开始是不存在的。但是ViewStub可以与一个布局进行绑定,“Stub”的意思就是存根嘛,凭着存根就可以找到最终想显示的布局文件,注意,这里说的是布局文件,ViewStub只能静态的显示布局,Java代码构造的view是不能用ViewStub的。

以下一个demo展示了ViewStub的简单使用,在主视图中点击按钮显示一个Button和一个ImageView:

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:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="showStubBtn"
        android:text="showBtn" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="showStubImg"
        android:text="showImg" />

    <ViewStub
        android:id="@+id/stub_btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout="@layout/layout_stub_btn"/>

    <ViewStub
        android:id="@+id/stub_img"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout="@layout/layout_stub_img"/>
</LinearLayout>

每个ViewStub“绑定”一个真实的布局文件:

(1)layout_stub_btn.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">

    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button in stub" />
</LinearLayout>

(2)layout_stub_img.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">

    <ImageView
        android:id="@+id/img"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

MainActivity:

package com.ethan.testviewstub;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewStub;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    public void showStubBtn(View view) {
        ViewStub stub = (ViewStub) findViewById(R.id.stub_btn);
        if (stub != null) {
            stub.inflate();
        } else {
                    //这里第二个点击按钮会执行,Stub为null
            Toast.makeText(this, "stub is null now ", Toast.LENGTH_LONG).show();
        }
        Button btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this, "hola", Toast.LENGTH_SHORT).show();
            }
        });
    }

    public void showStubImg(View view) {
        ViewStub stub = (ViewStub) findViewById(R.id.stub_img);
        stub.inflate();
        ImageView img = (ImageView) findViewById(R.id.img);
        img.setImageResource(R.drawable.ic_launcher);
    }
}

好啦,一个简单的例子完成了,可以看出ViewStub的使用场景很狭窄,个人认为只有在一个View被inflate之后不再改动(被解析的布局可以有事件响应)后才考虑使用ViewStub,毕竟拿着存根不如拿着实物好。

源码地址:https://github.com/boomstack/TestViewStub

猜你喜欢

转载自blog.csdn.net/ethanhola/article/details/51008644