深入分析Android ViewStub的应用详解

在开发应用程序的时候,经常会遇到这样的情况,会在运行时动态根据条件来决定显示哪个View或某个布局。那么最通常的想法就是把可能用到的View都写在上面,先把它们的可见性都设为View.GONE,然后在代码中动态的更改它的可见性。这样的做法的优点是逻辑简单而且控制起来比较灵活。但是它的缺点就是,耗费资源。虽然把View的初始可见View.GONE但是在Inflate布局的时候View仍然会被Inflate,也就是说仍然会创建对象,会被实例化,会被设置属性。也就是说,会耗费内存等资源。

推荐的做法是使用android.view.ViewStub,ViewStub是一个轻量级的View,它一个看不见的,不占布局位置,占用资源非常小的控件。可以为ViewStub指定一个布局,在Inflate布局的时候,只有ViewStub会被初始化,然后当ViewStub被设置为可见的时候,或是调用了ViewStub.inflate()的时候,ViewStub所向的布局就会被Inflate和实例化,然后ViewStub的布局属性都会传给它所指向的布局。这样,就可以使用ViewStub来方便的在运行时,要还是不要显示某个布局。

但ViewStub也不是万能的,下面总结下ViewStub能做的事儿和什么时候该用ViewStub,什么时候该用可见性的控制。

首先来说说ViewStub的一些特点:

1. ViewStub只能Inflate一次,之后ViewStub对象会被置为空。按句话说,某个被ViewStub指定的布局被Inflate后,就不会够再通过ViewStub来控制它了。

2. ViewStub只能用来Inflate一个布局文件,而不是某个具体的View,当然也可以把View写在某个布局文件中。

基于以上的特点,那么可以考虑使用ViewStub的情况有:

1. 在程序的运行期间,某个布局在Inflate后,就不会有变化,除非重新启动。

因为ViewStub只能Inflate一次,之后会被置空,所以无法指望后面接着使用ViewStub来控制布局。所以当需要在运行时不止一次的显示和隐藏某个布局,那么ViewStub是做不到的。这时就只能使用View的可见性来控制了。

2. 想要控制显示与隐藏的是一个布局文件,而非某个View。

因为设置给ViewStub的只能是某个布局文件的Id,所以无法让它来控制某个View。

所以,如果想要控制某个View(如Button或TextView)的显示与隐藏,或者想要在运行时不断的显示与隐藏某个布局或View,只能使用View的可见性来控制。

下面来看一个实例

在这个例子中,要显示二种不同的布局,一个是用TextView显示一段文字,另一个则是用ImageView显示一个图片。这二个是在onCreate()时决定是显示哪一个,这里就是应用ViewStub的最佳地点。

先来看看布局,一个是主布局,里面只定义二个ViewStub,一个用来控制TextView一个用来控制ImageView,另外就是一个是为显示文字的做的TextView布局,一个是为ImageView而做的布局:

复制代码 代码如下:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

  xmlns:android="http://schemas.android.com/apk/res/android"

  android:orientation="vertical"

  android:layout_width="fill_parent"

  android:layout_height="fill_parent"

  android:gravity="center_horizontal">

  <ViewStub

    android:id="@+id/viewstub_demo_text"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_marginLeft="5dip"

    android:layout_marginRight="5dip"

    android:layout_marginTop="10dip"

    android:layout="@layout/viewstub_demo_text_layout"/>

  <ViewStub

    android:id="@+id/viewstub_demo_image"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_marginLeft="5dip"

    android:layout_marginRight="5dip"

    android:layout="@layout/viewstub_demo_image_layout"/>

</LinearLayout>

为TextView的布局:

复制代码 代码如下:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

  xmlns:android="http://schemas.android.com/apk/res/android"

  android:orientation="vertical"

  android:layout_width="wrap_content"

  android:layout_height="wrap_content">

    <TextView

        android:id="@+id/viewstub_demo_textview"

        android:layout_width="fill_parent"

        android:layout_height="wrap_content"

        android:background="#aa664411"

        android:textSize="16sp"/>

</LinearLayout>

为ImageView的布局:

复制代码 代码如下:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

  xmlns:android="http://schemas.android.com/apk/res/android"

  android:orientation="vertical"

  android:layout_width="wrap_content"

  android:layout_height="wrap_content">

    <ImageView

        android:id="@+id/viewstub_demo_imageview"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"/>

</LinearLayout>

下面来看代码,决定来显示哪一个,只需要找到相应的ViewStub然后调用其infalte()就可以获得相应想要的布局:

复制代码 代码如下:

package com.effective;

import android.app.Activity;

import android.os.Bundle;

import android.view.ViewStub;

import android.widget.ImageView;

import android.widget.TextView;

public class ViewStubDemoActivity extends Activity {

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.viewstub_demo_activity);

        if ((((int) (Math.random() * 100)) & 0x01) == 0) {

            // to show text

            // all you have to do is inflate the ViewStub for textview

            ViewStub stub = (ViewStub) findViewById(R.id.viewstub_demo_text);

            stub.inflate();

            TextView text = (TextView) findViewById(R.id.viewstub_demo_textview);

            text.setText("The tree of liberty must be refreshed from time to time" +

                    " with the blood of patroits and tyrants! Freedom is nothing but " +

                    "a chance to be better!");

        } else {

            // to show image

            // all you have to do is inflate the ViewStub for imageview

            ViewStub stub = (ViewStub) findViewById(R.id.viewstub_demo_image);

            stub.inflate();

            ImageView image = (ImageView) findViewById(R.id.viewstub_demo_imageview);

            image.setImageResource(R.drawable.happy_running_dog);

        }

    }

}

运行结果:

使用的时候的注意事项:
1. 某些布局属性要加在ViewStub而不是实际的布局上面,才会起作用,比如上面用的android:layout_margin*系列属性,如果加在TextView上面,则不会起作用,需要放在它的ViewStub上面才会起作用。而ViewStub的属性在inflate()后会都传给相应的布局。

时间: 2024-08-03 22:50:01

深入分析Android ViewStub的应用详解的相关文章

深入分析Android ViewStub的应用详解_Android

在开发应用程序的时候,经常会遇到这样的情况,会在运行时动态根据条件来决定显示哪个View或某个布局.那么最通常的想法就是把可能用到的View都写在上面,先把它们的可见性都设为View.GONE,然后在代码中动态的更改它的可见性.这样的做法的优点是逻辑简单而且控制起来比较灵活.但是它的缺点就是,耗费资源.虽然把View的初始可见View.GONE但是在Inflate布局的时候View仍然会被Inflate,也就是说仍然会创建对象,会被实例化,会被设置属性.也就是说,会耗费内存等资源. 推荐的做法是

Android Animations动画使用详解

一.动画类型 Android的animation由四种类型组成:alpha.scale.translate.rotate XML配置文件中 二. Android动画模式 Animation主要有两种动画模式:tweened 和 frame 一种是tweened animation(渐变动画) 三.XML文件中定义动画 ① 打开Eclipse,新建Android工程 ② 在res目录中新建anim文件夹 ③ 在anim目录中新建一个myanim.xml(注意文件名小写) ④ 加入XML的动画代码

《Android NFC开发实战详解》——6.4节Android NFC P2P开发进阶

6.4 Android NFC P2P开发进阶 Android NFC开发实战详解 本节将介绍Android API 16+中引入的针对NFC P2P功能开发的新功能--文件传输进行介绍.该功能包括setBeamPushUrisCallback和setBeamPushUris两个方法.通过本节的介绍,大家可以结合NFC和蓝牙或WiFi很轻松的实现Android设备之间大数据(如图片.音乐等)的传输. 6.4.1 Beam实现文件传输的方法 Android4.1(Jelly Bean,Androi

Linux下Android ADB驱动安装详解

Linux下Android ADB驱动安装详解 概述 最近由于内置的合作商比较多,本人使用的Ubuntu系统好多厂商的Android手机都无法正确的识别,经过一番折腾,和查阅SDK,现把Linux下ADB驱动配置的方法和当中会遇到的相关问题的解决方法整理出来贡献给大家. Linux下使用手机USB调试模式连接ADB进行Android程序的调试,配置驱动没有Windows来的直观. 具体步骤 首先确认手机连接上电脑,lsusb查看下设备记录. matthew@matthew-1230-laptop

《Android NFC开发实战详解》——6.2节Android NFC P2P开发基础

6.2 Android NFC P2P开发基础 Android NFC开发实战详解 本节主要介绍Android NFC P2P开发中的一些基础知识,为后续的实例开发提供基础.通过本章的学习,使读者熟悉Android中Beam实现的几种方式,Beam NDEF消息和接收Beam消息的方法,同时也会对第4章中提到的Intent过滤机制在P2P中的使用进行阐述. 6.2.1 Android Beam实现的几种方式 在Android中,目前,Beam功能实现的方式可以概括为三种,分别为setNdefPu

Android实现动画效果详解_Android

目前Android平台提供了两类动画一类是Tween动画,第二类就是 Frame动画,具体内容介绍请看下文: 一类是Tween动画,就是对场景里的对象不断的进行图像变化来产生动画效果(旋转.平移.放缩和渐变). 第二类就是 Frame动画,即顺序的播放事先做好的图像,与gif图片原理类似. 实现动画有两种方式:一种使用XML文件(文件放在res/anim),一种直接代码搞定  1.透明度控制动画效果alpha <!-- 透明度控制动画效果alpha 浮点型值: fromAlpha 动画起始时透明

android进程与线程详解

并且已经存在这个应用的线程了(因为有这个应用程序的另一个组件已经运行了),于是这个组件就会在这个已有的进程中启动并且运行在同一个线程中.然而,你完全可以安排不同的组件运行于不同的进程,并且你可以为任何程序创建另外的线程. 进程 默认下,同一个程序的所有组件都运行在同一个进程中并且大多数程序不必改变这一状况.然而,如果你非要与众不同,也可以通过修改manifest文件实现. manifest文件中的所有支持android:process属性的那些项(<activity>,<service&

Android 手势操作编程详解_Android

      手势操作在我们使用智能设备的过程中奉献了不一样的体验.Android开发中必然会进行手势操作方面的编程.那么它的原理是怎样的呢?我们如何进行手势操作编程呢?        手势操作原理        首先,在Android系统中,每一次手势交互都会依照以下顺序执行.        1. 接触接触屏一刹那,触发一个MotionEvent事件.        2. 该事件被OnTouchListener监听,在其onTouch()方法里获得该MotionEvent对象.        3

Android Matrix源码详解_Android

Matrix的数学原理 在Android中,如果你用Matrix进行过图像处理,那么一定知道Matrix这个类.Android中的Matrix是一个3 x 3的矩阵,其内容如下:  Matrix的对图像的处理可分为四类基本变换: Translate           平移变换 Rotate                旋转变换 Scale                  缩放变换 Skew                  错切变换 从字面上理解,矩阵中的MSCALE用于处理缩放变换,MS