引導指示界面是個什么鬼東西?一張圖即明了:
其實就是給剛安裝你的軟件的用戶指示如何使用的一個蒙層,具有以下特點:
- 運行中顯示,用戶使用到特定的環境、特定的界面時才顯示(這里請區別下第一次安裝時剛啟動時好幾個滑動界面的“引導歡迎頁”)
- 覆蓋於原來界面之上,並且半透明,帶有指示文字或圖標
- 軟件生命周期內只出現一次(閱后即焚)
- 不影響原來軟件的操作
這一個小小的界面實現起來有一些小的訣竅,使用了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就是實現這個引導指示層的最佳控件。
對於在運行時決定可見性的界面我們通常的做法是:
- 在布局文件中寫好改view或者viewgroup,設置visibility為gone
- 在代碼中根據運行條件將上述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); }
上述代碼需要解釋幾個地方:
- SPUtils是我自己寫的一個SharePreference的幫助類,方便設值和檢查是否含有某個key, Constant.GuideVisibilityKey.ROOT_FRAGMENT_SLIDE是這個key的名字
- stubGuideSlide.inflate()即通知ViewStub將指定的guide_root_slide_left_right.xml布局文件給inflate出來,從而展示出引導指示層
- 我們需要讓用戶點擊這個指示層的任意位置后銷毀指示層,所以我們先獲取布局的根viewgroup即rl,然后給他設置點擊事件,點擊的時候把ViewStub給Gone掉,這個時候ViewStub就銷毀了。這里不能直接給ViewStub設置點擊事件,這樣子是沒有效果的,您可以嘗試一下。