欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android实现新手引导半透明蒙层效果

程序员文章站 2022-05-15 15:19:45
本文实例为大家分享了android实现新手引导半透明蒙层效果的具体代码,供大家参考,具体内容如下 效果图: 其中的文字和我知道啦是ui切得两张透明图片...

本文实例为大家分享了android实现新手引导半透明蒙层效果的具体代码,供大家参考,具体内容如下

效果图:

Android实现新手引导半透明蒙层效果

Android实现新手引导半透明蒙层效果

其中的文字和我知道啦是ui切得两张透明图片

自定义view:

package com.cymobi.library.view.widget;

import android.app.activity;
import android.content.context;
import android.graphics.bitmap;
import android.graphics.canvas;
import android.graphics.paint;
import android.graphics.porterduff;
import android.graphics.porterduffxfermode;
import android.graphics.rectf;
import android.util.log;
import android.view.gravity;
import android.view.view;
import android.view.viewgroup;
import android.view.viewtreeobserver;
import android.widget.framelayout;
import android.widget.relativelayout;

import com.cymobi.library.r;

/**
 * created by xuke on 2017/8/24.
 */

public class guideview extends relativelayout implements viewtreeobserver.ongloballayoutlistener {
  private final string tag = getclass().getsimplename();
  private context mcontent;
  private boolean first = true;
  private static final string show_guide_prefix = "show_guide";
  private int offsetx, offsety;
  private int radius;
  private view targetview;
  private view textguideview;
  private view customguideview;
  private paint mcirclepaint;
  private paint mbackgroundpaint;
  private boolean ismeasured;
  private int[] center;
  private porterduffxfermode porterduffxfermode;
  private bitmap bitmap;
  private int backgroundcolor;
  private canvas temp;
  private direction direction;
  private myshape myshape;
  private int[] location;
  private boolean onclickexit;
  private onclickcallback onclicklistener;
  private int targetviewwidth;
  private int targetviewheight;
  private boolean iscontain = false;
  private boolean needdraw = true;


  public guideview(context context) {
    super(context);
    this.mcontent = context;
  }

  public int[] getlocation() {
    return location;
  }

  public void setlocation(int[] location) {
    this.location = location;
  }

  public int getradius() {
    return radius;
  }

  public void setradius(int radius) {
    this.radius = radius;
  }

  public void setdirection(direction direction) {
    this.direction = direction;
  }

  public void setshape(myshape shape) {
    this.myshape = shape;
  }

  public void setbgcolor(int background_color) {
    this.backgroundcolor = background_color;
  }

  public void settargetview(view targetview) {
    this.targetview = targetview;
  }

  public int[] getcenter() {
    return center;
  }

  public void setcenter(int[] center) {
    this.center = center;
  }

  public void setoffsetx(int offsetx) {
    this.offsetx = offsetx;
  }

  public void setoffsety(int offsety) {
    this.offsety = offsety;
  }

  public void setcontain(boolean contain) {
    this.iscontain = contain;
  }

  public void setcustomguideview(view customguideview) {
    this.customguideview = customguideview;
    if (!first) {
      restorestate();
    }
  }

  public void settextguideview(view textguideview) {
    this.textguideview = textguideview;
    if (!first) {
      restorestate();
    }
  }

  private boolean hasshown() {
    if (targetview == null)
      return true;
    return mcontent.getsharedpreferences(tag, context.mode_private).getboolean(generateuniqid(targetview), false);
  }

  private string generateuniqid(view v) {
    return show_guide_prefix + v.getid();
  }

  public void setonclicklistener(onclickcallback onclicklistener) {
    this.onclicklistener = onclicklistener;
  }

  private void setclickinfo() {
    final boolean exit = onclickexit;
    setonclicklistener(new onclicklistener() {
      @override
      public void onclick(view v) {
        if (onclicklistener != null) {
          onclicklistener.onclickedguideview();
        }
        if (exit) {
          hide();
        }
      }
    });
  }

  public void show() {
    log.v(tag, "show");
    if (hasshown())
      return;

    if (targetview != null) {
      targetview.getviewtreeobserver().addongloballayoutlistener(this);
    }

    this.setbackgroundresource(r.color.transparent);
    this.bringtofront(); //设置在最上层
    ((framelayout) ((activity) mcontent).getwindow().getdecorview()).addview(this);
    first = false;
  }

  public void hide() {
    log.v(tag, "hide");
    if (customguideview != null || textguideview != null) {
      targetview.getviewtreeobserver().removeongloballayoutlistener(this);
      this.removeallviews();
      ((framelayout) ((activity) mcontent).getwindow().getdecorview()).removeview(this);
      restorestate();
    }
  }

  /**
   * 获得targetview 的宽高
   *
   * @return
   */
  private int[] gettargetviewsize() {
    int[] location = {-1, -1};
    if (ismeasured) {
      location[0] = targetview.getwidth();
      location[1] = targetview.getheight();
    }
    return location;
  }

  /**
   * 获得targetview 的半径
   *
   * @return
   */
  private int gettargetviewradius() {
    if (ismeasured) {
      int[] size = gettargetviewsize();
      int x = size[0];
      int y = size[1];

      return (int) (math.sqrt(x * x + y * y) / 2);
    }
    return -1;
  }

  @override
  protected void ondraw(canvas canvas) {
    super.ondraw(canvas);
    log.v(tag, "ondraw");
    if (!ismeasured)
      return;
    if (targetview == null)
      return;
    drawbackground(canvas);
  }


  private void drawbackground(canvas canvas) {
    log.v(tag, "drawbackground");
    needdraw = false;
    // 先绘制bitmap,再将bitmap绘制到屏幕
    bitmap = bitmap.createbitmap(canvas.getwidth(), canvas.getheight(), bitmap.config.argb_8888);
    temp = new canvas(bitmap);

    // 背景画笔
    paint bgpaint = new paint();
    if (backgroundcolor != 0) {
      bgpaint.setcolor(backgroundcolor);
    } else {
      bgpaint.setcolor(getresources().getcolor(r.color.bg_shadow));
    }
    // 绘制屏幕背景
    temp.drawrect(0, 0, temp.getwidth(), temp.getheight(), bgpaint);

    // targetview 的透明圆形画笔
    if (mcirclepaint == null) {
      mcirclepaint = new paint();
    }
    //透明效果
    porterduffxfermode = new porterduffxfermode(porterduff.mode.clear);  //src_out或者clear都可以
    mcirclepaint.setxfermode(porterduffxfermode);
    mcirclepaint.setantialias(true);

    if (myshape != null) {
      rectf oval = new rectf();
      switch (myshape) {
        case circular://圆形
          temp.drawcircle(center[0], center[1], radius, mcirclepaint);
          break;
        case rectangular://圆角矩形
          if (iscontain) {
            oval.left = location[0] - 8;
            oval.top = center[1] - targetviewheight / 2 - 8;
            oval.right = location[0] + targetviewwidth + 8;
            oval.bottom = center[1] + targetviewheight / 2 + 8;
          } else {
            oval.left = location[0] + 5;
            oval.top = center[1] - targetviewheight / 2 + 1;
            oval.right = location[0] + targetviewwidth - 5;
            oval.bottom = center[1] + targetviewheight / 2 - 1;
          }
          temp.drawroundrect(oval, radius, radius, mcirclepaint);
          break;
      }
    } else {
      temp.drawcircle(center[0], center[1], radius, mcirclepaint);
    }

    // 绘制到屏幕
    canvas.drawbitmap(bitmap, 0, 0, bgpaint);
    bitmap.recycle();
  }




  @override
  public void ongloballayout() {
    if (ismeasured)
      return;
    if (targetview.getheight() > 0 && targetview.getwidth() > 0) {
      ismeasured = true;
      targetviewwidth = targetview.getwidth();
      targetviewheight = targetview.getheight();
    }

    // 获取targetview的中心坐标
    if (center == null) {
      // 获取右上角坐标
      location = new int[2];
      targetview.getlocationinwindow(location);
      center = new int[2];
      // 获取中心坐标
      center[0] = location[0] + targetview.getwidth() / 2;
      center[1] = location[1] + targetview.getheight() / 2;
    }
    // 获取targetview外切圆半径
    if (radius == 0) {
      radius = gettargetviewradius();
    }

    //文字图片和提示图片
    createview();

  }

  //文字图片和我知道啦图片一起放
  private void createview() {
    log.v(tag, "createview");

    //文字提示
    layoutparams textviewparams;
    textviewparams = new layoutparams(layoutparams.match_parent, layoutparams.wrap_content);
    textviewparams.setmargins(0, center[1] + radius + 10, 0, 0);

    // 我知道提示布局参数
    layoutparams guideviewparams;
    guideviewparams = new layoutparams(layoutparams.match_parent, layoutparams.wrap_content);
    guideviewparams.setmargins(0, center[1] + radius + 10, 0, 0);

    if (textguideview != null && customguideview != null) {
      if (direction != null) {
        int left = center[0] + targetviewwidth / 2;
        int right = center[0] + targetviewwidth / 2;
        int top = center[1] - targetviewheight / 2;
        int bottom = center[1] + targetviewheight / 2;

        //我自己的项目只需要这两个方向的, 所以这里就只写了top和boottom
        switch (direction) {
          case top:
            this.setgravity(gravity.center_horizontal);
            textviewparams.setmargins(offsetx, top - offsety, -offsetx, -top + offsety);
            guideviewparams.setmargins(offsetx, -3 * offsety + top, -offsetx, -top + 3 * offsety);
            break;
          case bottom:
            this.setgravity(gravity.center_horizontal);
            textviewparams.setmargins(offsetx, bottom + offsety, -offsetx, -bottom - offsety);
            guideviewparams.setmargins(offsetx, bottom + 3 * offsety, -offsetx, -bottom - 3 * offsety);
            break;
        }

        if (this != null)
          this.removeallviews();
        this.addview(textguideview, textviewparams);
        this.addview(customguideview, guideviewparams);
      }
    }
  }


  /**
   * 定义guideview相对于targetview的方位,
   */
  public enum direction {
    left, top, right, bottom,
    left_top, left_bottom,
    right_top, right_bottom
  }

  /**
   * 定义目标控件的形状。圆形,矩形
   */
  public enum myshape {
    circular, rectangular
  }

  /**
   * guideview点击callback
   */
  public interface onclickcallback {
    void onclickedguideview();
  }

  public static class builder {
    static guideview guiderview;
    static builder instance = new builder();
    context mcontext;

    private builder() {
    }

    public builder(context ctx) {
      mcontext = ctx;
    }

    public static builder newinstance(context ctx) {
      guiderview = new guideview(ctx);
      return instance;
    }

    /**
     * 设置目标view
     */
    public builder settargetview(view target) {
      guiderview.settargetview(target);
      return instance;
    }

    /**
     * 设置蒙层颜色
     */
    public builder setbgcolor(int color) {
      guiderview.setbgcolor(color);
      return instance;
    }

    /**
     * 设置文字和图片view 在目标view的位置
     */
    public builder setdirction(direction dir) {
      guiderview.setdirection(dir);
      return instance;
    }

    /**
     * 设置绘制形状
     */
    public builder setshape(myshape shape) {
      guiderview.setshape(shape);
      return instance;
    }

    public builder setradius(int radius) {
      guiderview.setradius(radius);
      return instance;
    }

    /**
     * 设置文字图片
     */
    public builder settextguideview(view view) {
      guiderview.settextguideview(view);
      return instance;
    }

    /**
     * 设置"我知道啦"图片
     */
    public builder setcustomguideview(view view) {
      guiderview.setcustomguideview(view);
      return instance;
    }

    /**
     * 设置图片的偏移量
     */
    public builder setoffset(int x, int y) {
      guiderview.setoffsetx(x);
      guiderview.setoffsety(y);
      return instance;
    }

    /**
     * 设置时候包含 true:画的透明包含目标view
     */
    public builder setcontain(boolean iscontain) {
      guiderview.setcontain(iscontain);
      return instance;
    }

    /**
     * 点击监听
     */
    public builder setonclicklistener(final onclickcallback callback) {
      guiderview.setonclicklistener(callback);
      return instance;
    }

    public guideview build() {
      guiderview.setclickinfo();
      return guiderview;
    }

  }

  public void restorestate() {
    log.v(tag, "restorestate");
    offsetx = offsety = 0;
    radius = 0;
    mcirclepaint = null;
    mbackgroundpaint = null;
    ismeasured = false;
    center = null;
    porterduffxfermode = null;
    bitmap = null;
    needdraw = true;
    temp = null;
  }
}

在自己页面应用:

//文字图片
    final imageview iv1 = new imageview(context);
    iv1.setimageresource(r.drawable.img_guide_work_text);
    relativelayout.layoutparams params1 = new relativelayout.layoutparams(viewgroup.layoutparams.wrap_content, viewgroup.layoutparams.wrap_content);
    iv1.setlayoutparams(params1);

    //我知道啦
    final imageview iv2 = new imageview(context);
    iv2.setimageresource(r.drawable.img_guide_know);
    relativelayout.layoutparams params2 = new relativelayout.layoutparams(viewgroup.layoutparams.wrap_content, viewgroup.layoutparams.wrap_content);
    iv2.setlayoutparams(params2);

 guideview = guideview.builder
        .newinstance(context)
        .settargetview(itemwork) //设置目标view
        .settextguideview(iv1)   //设置文字图片
        .setcustomguideview(iv2)  //设置 我知道啦图片
        .setoffset(0, 80)      //偏移量 x=0 y=80
        .setdirction(guideview.direction.bottom)  //方向
        .setshape(guideview.myshape.rectangular)  //矩形
        .setradius(10)               //圆角
        .setcontain(false)             //透明的方块时候包含目标view 默认false
        .setbgcolor(getresources().getcolor(r.color.bg_shadow))  //背景颜色
        .setonclicklistener(new guideview.onclickcallback() {
          @override
          public void onclickedguideview() {
            guideview.hide();
          }
        })
        .build();
guideview.show();


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。