高亮說明控件

前言:

軟件開發時常常須要對某些按鈕進行說明,引導用戶該怎麼去操做軟件。這種狀況大部分是一個透明的遮罩層,遮罩層上有一部分高亮區顯示要說明的按鈕,按鈕的某個方向上加上一個圖片進行操做說明。好比說小面的效果。android

實現思路

  1. 在控件上覆蓋上原有的控件截圖
  2. 在控件上繪製基本集合圖形,利用混合模式顯示高亮區

編寫代碼

首先利用思路1的方式實現

  1. 編寫一個自定義view,繼承自view,下面直接上代碼,看代碼中的註釋便可理解。git

    public class GuideView extends View {
         private Paint paint;
         //編寫一個GuideBean,裏面存放控件說明的信息,好比圖片,要說明的控件等
         private GuideBean guideBean;
         
          public GuideView(Context context, AttributeSet attrs) {
             super(context, attrs);
         }
         
          @Override
         protected void onDraw(Canvas canvas) {
             super.onDraw(canvas);
             //若是集合中不存在控件說明,直接隱藏該view。
             if (guideBeans == null || guideBeans.size() == 0){
                 this.setVisibility(GONE);
                 return;
              }
             
             //Config是此view的配置類,下面會提到。這裏的OPENMORE指是否在一個屏幕內顯示多個控件說明
             if (Config.OPENMORE){
                 //一屏顯示多個控件說明
                 canvas.drawBitmap(createDstBitmap(width,height), 0, 0, paint);
                 for (int i=0; i<guideBeans.size(); i++){
                     drawBuyView(canvas,guideBeans.get(i));
                 }
             }else {
                 //沒點擊一次,就播放下一個控件說明
                 drawBuyView(canvas,guideBean);
             }
         }
         
         //將要添加的控件說明集合設置進此view中,等待顯示
         public void setGuideBeans(List<GuideBean> guideBeans){
             this.guideBeans = guideBeans;
             invalidate();
         }
         
         //當數據設置好後調用此方法顯示控件說明
         public void showGuide(){
             //將隱藏中的該view設置爲顯示狀態
             this.setVisibility(VISIBLE);
             if (guideBeans != null && guideBeans.size() !=0){
                 //將當前的說明設置爲集合中的第一個對象。
                 guideBean = guideBeans.get(0);
             }
             invalidate();
          }
    }
    複製代碼
  2. 繪製要說明控件的圖片canvas

    /**
     * 繪製高亮區及說明圖片
     * @param canvas
     * @param guideBean
     */
    public void drawBuyView(Canvas canvas,GuideBean guideBean){
        if (guideBean == null){
            return;
        }
        //若是是一屏顯示多個控件說明,遮罩層在循環前繪製一邊便可
        if (!Config.OPENMORE){
            canvas.drawBitmap(createDstBitmap(width,height), 0, 0, paint);
        }
        
        //繪製view的圖像,即將view自己繪製成高亮區
        //須要注意的是,要說明的控件背景不可設置爲透明背景,否在獲取控件圖片時背景也
        //是透明的,這樣控件的顏色與遮罩層的顏色就一致了,起不到高亮的效果
        if (guideBean.getViewBitmap() != null){
            canvas.drawBitmap(guideBean.getViewBitmap(),guideBean.getRect().left,guideBean.getRect().top,paint);
        }
        //說明控件的中線座標,用於計算說明圖片的在x軸上的起始距離(距離屏幕左邊距離)
        int centerLine = guideBean.getRect().left+(guideBean.getRect().right-guideBean.getRect().left)/2;
        //計算說明圖片x軸上的起始位置
        int targetCenter = centerLine - guideBean.getBitmap().getWidth()/2;
        if (guideBean.getBitmap() != null){
            //執行繪製說明圖片的方法
            drawShuoMingPic(canvas,guideBean,targetCenter);
        }
    }
    
     /**
     * 繪製控件說明
     * @param canvas
     * @param guideBean
     */
    private void drawShuoMingPic(Canvas canvas, GuideBean guideBean,int targetCenter) {
        //根據不一樣的方位狀況進行控件繪製。這裏只寫出繪製在控件底部的狀況,所有的代碼有點長,就不貼出來了。
        if (guideBean.getPosition() == Config.BOTTOM){
            canvas.drawBitmap(guideBean.getBitmap(),targetCenter+guideBean.getMarginLeft(),guideBean.getRect().bottom+guideBean.getMarginTop()+guideBean.getMarginBottom(),paint);
        }
    }
    複製代碼
  3. 編寫一個配置類,用於配置該view的屬性bash

    /**
      * view的配置文件,務必在調用showGuide方法前配置完guideview
      */
     public static class Config{
         /**
          * 是否打開一個界面顯示多個控件說明,默認是關閉的
          */
         public static boolean OPENMORE = false;
         
          /**
          * 配置遮罩層顏色
          */
         public static int COLOR = Color.parseColor("#99000000");
     }
    複製代碼
  4. 編寫GuideBean,這個類描述了全部的控件說明信息,好比padding,margin,控件的在屏幕上的位置等信息app

public class GuideBean{
    private Rect rect;
    private int img;
    private Bitmap bitmap;
    private Bitmap viewBitmap;
    private int marginTop,marginBottom,marginLeft,marginRight;
    private boolean isSimpleShape;
    private int position;
    private byte shape;

    /**
     *
     * @param img 要展現的說明圖片
     * @param act 活動界面
     * @param view 想要出現高亮區的控件
     */
    public GuideBean(int img, Activity act, View view) {
        Rect rect = new Rect();
        //獲取控件在屏幕中的座標位置,此座標位置包括了狀態欄的高度和標題欄的高度,
        //因此後面矩陣rect中的top和bottom須要去除這兩個高度的影響。去除方法在GuideViewUtils幫助類中
        view.getGlobalVisibleRect(rect);
        setRectInfo(rect,act);
        this.img = img;
        //獲取控件說明圖片
        bitmap = BitmapFactory.decodeResource(act.getResources(),img);
        this.rect = rect;
        //獲取控件自己的圖片
        this.viewBitmap = GuideViewUtils.loadBitmapFromView(view);
    }
    
    /**
     * 設置控件矩陣的頂部座標和底部座標,這兩個座標與狀態欄和標題欄高度有關
     * @param rect 控件的矩陣
     * @param act 活動
     */
    public void setRectInfo(Rect rect,Activity act){
       rect.top = rect.top - GuideViewUtils.getStatusBarHeight(act) - GuideViewUtils.getInstance().getActionBarHeight(act);
       rect.bottom = rect.bottom - GuideViewUtils.getStatusBarHeight(act) - GuideViewUtils.getInstance().getActionBarHeight(act);
    }
    
    //下面時一堆get和set方法,不貼出來了。
  }
複製代碼
  1. 獲取狀態欄高度,標題欄高度和view的圖片(下面的方法在GuideViewUtils幫助類裏面)
    /**
      * 獲取狀態欄高度
      * @param context
      * @return 狀態欄高度
      */
     public static int getStatusBarHeight(Activity context){
         //判斷存不存在狀態欄
         WindowManager.LayoutParams params = context.getWindow().getAttributes();
         if ((params.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == WindowManager.LayoutParams.FLAG_FULLSCREEN){
             //不存在狀態欄直接返回0
             return 0;
         }else {
             //存在則獲取狀態欄高度
             int height = 0;
             int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
             if (resourceId > 0) {
                 height = context.getResources().getDimensionPixelSize(resourceId);
             }
             return height;
         }
     }
     
     /**
      * 獲取 標題欄高度
      * @param activity
      * @return
      */
     public int getActionBarHeight(Activity activity){
         //判斷傳進來的activity是否是Activity,繼承自Activity的活動是不帶標題欄的
         //繼承自AppCompatActivity的活動是帶有標題欄的
         if (activity instanceof AppCompatActivity){
             //判斷活動中是否存在標題欄,存在返回高度,不存在返回0
             if (((AppCompatActivity) activity).getSupportActionBar() != null){
                 return ((AppCompatActivity) activity).getSupportActionBar().getHeight();
             }else {
                 return 0;
             }
         }else if (activity instanceof Activity){
             if (activity.getActionBar() != null){
                 return activity.getActionBar().getHeight();
             }else {
                 return 0;
             }
         }else {
             return 0;
         }
     }
    複製代碼

調用並顯示控件說明

  1. 佈局編寫
    <com.libowu.guide.view.GuideView
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:id="@+id/guide"/>
    複製代碼
  2. 設置控件說明集合
//說明一下,只有繪製view完成後才能夠設置集合,oncreate中view並無繪製完成,因此控件的高度,在屏幕中的位置沒法
//獲取到,因此放到onWindowFocusChanged中執行了。不過onWindowFocusChanged是隻要屏幕焦點變化時都會調用,不如鎖屏
//開屏,切換先後臺等都有肯能觸發onWindowFocusChanged
@Override
 public void onWindowFocusChanged(boolean hasFocus) {
     super.onWindowFocusChanged(hasFocus);
     //將要說明的控件添加到集合中,讓後給guideview設置數據便可
     guides = new ArrayList<>();
     guides.add(new GuideBean(R.mipmap.guide,this,textView, true, GuideView.Config.OVAL));
     guides.add(new GuideBean(R.mipmap.guide,this,textViewTwo,true, GuideView.Config.OVAL));
     guides.add(new GuideBean(R.mipmap.guide,this,textViewThree,true, GuideView.Config.OVAL));
     guide.setGuideBeans(guides);
 }
複製代碼
  1. 顯示控件說明
textViewTwo.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View view) {
             //想要顯示引導時,調用此方法便可顯示
             guide.showGuide();
         }
     });
複製代碼

引入依賴使用該view

  1. 項目的build.gradle中加入下面內容
allprojects {
     repositories {
         ....
         maven {url "https://jitpack.io"}
     }
 }
複製代碼

2.app的build.gradle中加入依賴
implementation 'com.gitee.libowu:guideView:v0.0.4'maven

總結

這個項目只說了第一種思路,第二種思路並無說,由於代碼有點多,因此先不寫了,有興趣的能夠到碼雲上面clone項目到本地。碼雲地址ide

相關文章
相關標籤/搜索