Android引导指示层的制作 (ViewStub + SharePreference)

引导指示界面是个什么鬼东西?一张图即明了:

 

 

其实就是给刚安装你的软件的用户指示如何使用的一个蒙层,具有以下特点:

  • 运行中显示,用户使用到特定的环境、特定的界面时才显示(这里请区别下第一次安装时刚启动时好几个滑动界面的“引导欢迎页”)
  • 覆盖于原来界面之上,并且半透明,带有指示文字或图标
  • 软件生命周期内只出现一次(阅后即焚)
  • 不影响原来软件的操作

这一个小小的界面实现起来有一些小的诀窍,使用了ViewStub和SharePrefrence,下面一步步展示如何实现。

 

写布局


 

第一步就是写出这个展示出来效果的布局文件,这里例子很简单,就是一个全屏的.9半透明黑色图加上一个白色文字图片,图片居中。这一步直接给出代码。

根据你的情况自己实现自己所需要的布局。

 

layout\guide_root_slide_left_right.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:focusable="true"
    android:clickable="true"
    android:id="@+id/guide_root"
    android:background="@drawable/bg_dark"
    >
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/img_slide"
        android:layout_centerInParent="true"
        />

</RelativeLayout>

 

使用ViewStub


 

为什么使用ViewStub?首先看下我们的需求,第一是这个页面是动态根据条件呈现的,第二是它并不重要出现过一次后就不再需了,因为希望它不要占多少内存。以此来看,ViewStub就是实现这个引导指示层的最佳控件。

对于在运行时决定可见性的界面我们通常的做法是:

  1. 在布局文件中写好改view或者viewgroup,设置visibility为gone
  2. 在代码中根据运行条件将上述view或者viewgroup的可见性设为visible

这样子没什么不可,但是带来的问题是以后每次进这个界面,系统都会为这个view分配内存并且实例化,从而拖慢了速度,耗费资源(事实上我们只想让它显示仅仅一次就不要了)。而ViewStub呢?它是一个轻量级的View,类似于一个占位符。给他指定一个布局,它默认并不会inflate出来,直到你想让它显示出来的时候才会inflate你所指定的布局从而延迟分配了内存(类似于延迟加载)。

 

由于我们的半透明指示层是要蒙住全屏的,而且才原来的布局界面之上(布局树里面的控件是写在上面位置的先展示,写在下面位置的后展示),所以我们的原来的根布局需要为RelativeLayout,同时在根布局的最下面写上ViewStub:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!-- 原来的Activity内容-->
    ...

    <ViewStub
        android:id="@+id/guide_root_slide"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"

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

</RelativeLayout>

这里ViewStub可以当作是一个普通的View来加入到布局文件里面,同时给他的layout参数执行我们实际想要inflate出来的布局。等于给占位符设置一个“目标”。

 

增加逻辑代码


 

在你的activity代码中,获得这个ViewStub的引用:

ViewStub stubGuideSlide;

// onCreate
stubGuideSlide = (ViewStub) findViewById(R.id.guide_root_slide);

 

然后写一个方法,在你的运行判断逻辑(比如某个按钮的点击回调)里面执行这个方法,这里写上伪代码:

// some on Click listener
...
showGuideSlide();
...



private void showGuideSlide(){

    if(如果第一次到这里)
        展示GuideSlide引导指示层
    else
        不展示
    
}  

 

如何判断是否第一次走到这里呢?我们可以用SharePreference,我们可以随便定义属于这张引导指示层的key,然后判断他是否存在。如果不存在表示第一次进入,进入后我们把这个key对应的SharePeference随便设一个值,下回就不会走到这里了:(showGuideSlide的完整代码如下)

private void showGuideSlide() {

        if (SPUtils.contains(mContext, Constant.GuideVisibilityKey.ROOT_FRAGMENT_SLIDE)) {
            return;
        }

        try {
            final View guideSlideView = stubGuideSlide.inflate();
            RelativeLayout rl = (RelativeLayout) guideSlideView.findViewById(R.id.guide_root);
            if (rl != null) {
                rl.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        guideSlideView.setVisibility(View.GONE);
                    }
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        SPUtils.put(mContext, Constant.GuideVisibilityKey.ROOT_FRAGMENT_SLIDE, true);
    }

上述代码需要解释几个地方:

  1. SPUtils是我自己写的一个SharePreference的帮助类,方便设值和检查是否含有某个key, Constant.GuideVisibilityKey.ROOT_FRAGMENT_SLIDE是这个key的名字
  2. stubGuideSlide.inflate()即通知ViewStub将指定的guide_root_slide_left_right.xml布局文件给inflate出来,从而展示出引导指示层
  3. 我们需要让用户点击这个指示层的任意位置后销毁指示层,所以我们先获取布局的根viewgroup即rl,然后给他设置点击事件,点击的时候把ViewStub给Gone掉,这个时候ViewStub就销毁了。这里不能直接给ViewStub设置点击事件,这样子是没有效果的,您可以尝试一下。

 

posted @ 2015-12-02 16:49  soaringEveryday  阅读(2252)  评论(0编辑  收藏  举报