推薦一個好用小巧的Android引導蒙版(浮層)庫
前言
每當一個專案開發一個新功能,總會想辦法及時讓使用者得知有這樣一個新功能,這時通常會採用引導頁或者蒙版(浮層)的方式提心使用者,這裡有需要關注的新內容。
遇到這種需求,最簡單的想法就是將引導的佈局直接寫在對應的頁面中,在首次開啟時顯示,之後隱藏。但是用這種做法來顯示只會出現一次的佈局,顯然有些浪費資源。而且很low,完全體現不出OOP的程式設計思想。我們的專案中原來使用的是:http://www.jianshu.com/p/5aa96683d0dc
可以看到這是一個非常好的思路,通過DecorView來新增引導層,引導層的相關程式碼就可以從activity中抽離出來。高亮則是通過畫筆的setXfermode來實現。作者也進行了一定的封裝,使用的效果也挺好,但是我始終對呼叫的方法感覺不舒服:
每次使用時要判斷是否顯示過
if(NewbieGuideManager.isNeverShowed(this, NewbieGuideManager.TYPE_COLLECT)) {
new NewbieGuideManager(this, NewbieGuideManager.TYPE_COLLECT).addView
(mCollect, HoleBean.TYPE_CIRCLE).addView(mTitleTv, HoleBean
.TYPE_RECTANGLE).show();
}
通過下列方法顯示出引導層
new NewbieGuideManager(MainActivity.this ,
NewbieGuideManager.TYPE_LIST).addView(view
.getChildAt(0).findViewById(R.id.logo), HoleBean
.TYPE_RECTANGLE).show();
這裡還涉及到一個常量:NewbieGuideManager.TYPE_LIST
,需要在manager類中定義,並且設定對應的佈局:
mNewbieGuide.setEveryWhereTouchable (false).addIndicateImg(R.drawable.left_arrow, ScreenUtils.dpToPx(mActivity,
60), ScreenUtils.dpToPx(mActivity, 110)).addMsgAndKnowTv("這個listview滾動到item6後出現新手引導浮層,\n只有點選我知道啦才會想消失",
-ScreenUtils.dpToPx(mActivity, 250)).show();
並且每增加一種引導浮層就要重複上述3步的過程。
優化的NewbieGuide
由於非常介意上述的呼叫方式,於是我抽空在上述的思路上自己實現一個小巧的庫,主要對呼叫方式進行了封裝,通過鏈式呼叫,一行程式碼就可以實現引導層的實現。
Github:https://github.com/huburt-Hu/NewbieGuide
匯入
先來看下如何匯入專案中:
專案的build.gradle新增
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
module的build.gradle新增
dependencies {
compile 'com.github.huburt-Hu:NewbieGuide:v1.0.2'
}
使用
使用的話非常方便,在需要引導層的地方新增如下程式碼:
NewbieGuide.with(this)//傳入activity
.setLabel("guide1")//設定引導層標示,用於區分不同引導層,必傳!否則報錯
.addHighLight(view, HighLight.Type.RECTANGLE)//新增需要高亮的view
.setLayoutRes(R.layout.view_guide)//自定義的提示layout,不要新增背景色,引導層背景色通過setBackgroundColor()設定
.show();//顯示引導層
setLabel(String label)
方法需要傳入一個當前引導層的標示,用於sp快取當前引導層是否已經顯示過,因此是一個必須的引數,忘了設定的話會丟擲異常!
addHighLight()
方法有三個過載,第一個引數是需要高亮的view(通常是通過findViewById找到的view),第二個引數是高亮的型別,目前有四種:矩形,圓形,橢圓,圓角矩形(如果選擇圓角矩形的話,呼叫過載3個引數的方法,第三個引數是圓角的dp值),預設的話是矩形即只有一個引數的過載。
setLayoutRes(int resId,int... id)
該方法第一個引數傳入xml的佈局,可以任意編輯,如提示的文字,顏色,位置,圖片等,皆有你來自定義。第二個引數是可變引數,傳入該佈局內需要點選消失引導層的view的id。之所以用這種方式是因為通過程式碼來調整檢視非常麻煩,無法直接看到效果,我在使用中經常要部署好多次才會確定最終位置,遠沒有layout.xml來實現佈局方便。
效果
當然,這只是最簡單的實現效果,具體要如何的介面都可以由你來自定義layout,並通過setLayoutRes()方法傳入即可。
更多配置
Controller controller = NewbieGuide.with(this)
.setOnGuideChangedListener(new OnGuideChangedListener() {//設定監聽
@Override
public void onShowed(Controller controller) {
//引導層顯示
}
@Override
public void onRemoved(Controller controller) {
//引導層消失
}
})
.setBackgroundColor(Color.BLACK)//設定引導層背景色,建議有透明度,預設背景色為:0xb2000000
.setEveryWhereCancelable(false)//設定點選任何區域消失,預設為true
.setLayoutRes(R.layout.view_guide, R.id.textView)//自定義的提示layout,第二個可變引數為點選隱藏引導層view的id
.alwaysShow(true)//是否每次都顯示引導層,預設false
.build();//構建引導層的控制器
controller.resetLabel("guide1");
controller.remove();//移除引導層
controller.show();//顯示引導層
實現原理
這個庫非常的小,總共只有5個類,一個介面,一個工具類。
高亮的實現是通過畫筆的setXfermode。即當兩個畫布上都繪製了圖片是,可以控制最終顯示的樣式,有取重疊部分,有去除重疊部分的等等,這個有16中規則,具體下圖:
我所使用時clear屬性,即先通過canvas.drawColor(mBackgroundColor);
繪製背景色,然後通過設定了clear屬性的畫筆
PorterDuffXfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
mPaint.setXfermode(xfermode);
鏤空出需要高亮的view。
view在螢幕的位置可以通過下述方法獲取:
public RectF getRectF() {
RectF rectF = new RectF();
if (mHole != null) {
int[] location = new int[2];
mHole.getLocationOnScreen(location);
rectF.left = location[0];
rectF.top = location[1];
rectF.right = location[0] + mHole.getWidth();
rectF.bottom = location[1] + mHole.getHeight();
}
return rectF;
}
mHole
就是之前傳入的需要高亮的view。
餘下就是呼叫的封裝了,使用了建造者模式來保證鏈式呼叫,有興趣的可以clone程式碼看下,也用不了多少時間。
後記
這個庫也是我第一個公開的庫,目前僅僅實現了基本的功能,後續也會不斷維護和升級。有什麼疑問或者建議,或者需要補充的需求都可以回覆,留言,感覺各位閱讀我的文章~