1. 程式人生 > >推薦一個好用小巧的Android引導蒙版(浮層)庫

推薦一個好用小巧的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中規則,具體下圖:

setXfermode屬性
我所使用時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程式碼看下,也用不了多少時間。

後記

這個庫也是我第一個公開的庫,目前僅僅實現了基本的功能,後續也會不斷維護和升級。有什麼疑問或者建議,或者需要補充的需求都可以回覆,留言,感覺各位閱讀我的文章~