一行代码实现Android App指引

概述

前几周app改版,在修改老代码的过程中发现了一个指引,让我想起很久以前项目里指引实现是在布局文件中添加布局,并在代码中插入很多非业务的代码,这样写感觉不好。指引本只是一个不太重要,可能经常变动的功能,说不定下个版本又改了,当它和正常业务耦合在一起以后,就显得代码有点混乱了。有没有一种方法,可以无缝嵌入,将指引和正常业务彻底解耦?前几天早晨,几个公众号都发了同样一篇博客来抠个图吧~——更优雅的Android UI界面控件高亮的实现,看到这篇博客的时候有种醍醐灌顶的感觉,这不正是我想要的指引吗?看完博客中的实现原理后,决定动手重复造一个轮子,本文简单分析一下这个轮子是如何实现的,并分析了一下优缺点。下面先看个效果:

在这里插入图片描述

指引需求分析

不谈技术实现,首先分析一下指引这个需求本身。

入门级指引

入门级的指引,就是最简单的指引,在app安装新版本或者覆盖安装新版本后第一时间弹出来几张图片。为了突出某些功能,会高亮显示一些内容,同时还有一些指示性的箭头,或者在高亮旁边有文本描述。

升级版指引

升级版指引,在用户第一次进入到个页面的时候,告诉用户哪几个按钮有是做什么的。指引内容和入门级的差不多,高亮显示View,箭头、文本描述,点击高亮View后跑到下一步指引直到指引结束。

指引需求的抽象

简单指引一般由UI切图就好,这里以app内部的指引需求分析指引,如图(图片是随便找的),指引一般包括以下内容:
在这里插入图片描述

  1. 满屏幕的半透明遮罩层;
  2. 高亮显示突出显示底层app页面的某个或者某些View;
  3. 在高亮显示的View旁边可能有一些带文本的图片,或者指示方向的图片+文本;
  4. 高亮部分可以响应点击事件,并且很有可能点击后继续显示下一步指引,直到显示完。

指引的技术实现

分析了指引的需求后,得到指引的基本元素,决定用自定义View实现,命名这个自定义View为GuideView。实现整个指引流程如下:
1.定义指引绘制要素Shape,及其派生类:Rectangle、Oval、BitmapDecoration、TextDecoration;
2.定义每一步指引的信息GuideInfo,并获取高亮区域的坐标矩形;
3.定义GuideView继承View,绘制指引要素:Shape;
4.定义GuideManager,管理多步骤指引;
5.定义GuideDialog承载GuideView,覆盖在页面上,和GuideManager

指引的要素:Shape

指引的基本要素包括:高亮显示的View区域,图片,文本等饰品。定义个接口,命名为Shape,那么Shape有子类:高亮的矩形(Rectangle),高亮的圆形(Oval),图片(BitmapDecoration),文本(TextDecoration)。指引要素实现代码如下:

interface Shape {
   
    fun draw(canvas: Canvas, paint: Paint)
}

class Oval(private val rect: RectF) : Shape {
   
    override fun draw(canvas: Canvas, paint: Paint) {
   
        canvas.drawOval(rect, paint)
    }
}

class Rectangle(
    private val rect: RectF,
    private val xRadius: Float = 0F,
    private val yRadius: Float = 0F
) : Shape {
   
    override fun draw(canvas: Canvas, paint: Paint) {
   
        canvas.drawRoundRect(rect, xRadius, yRadius, paint)
    }
}
class BitmapDecoration(
    private val bitmap: Bitmap,
    private val left: Float,
    private val top: Float
) : Shape {
   
    override fun draw(canvas: Canvas, paint: Paint) {
   
        canvas.drawBitmap(bitmap, left, top, paint)
    }
}
class TextDecoration(
    protected val text: String,         // 要绘制的文本
    protected val textSize: Float,      // 字体大小
    protected val textColor: Int,       // 字体颜色
    protected val startX: Float,        // x轴起点(left)
    protected val startY: Float,        // y轴七点(top)
    protected val bold: Boolean = false // 粗体
) : Shape {
   
    override fun draw(canvas: Canvas, paint: Paint) {
   
        paint.color = textColor
        paint.textSize = textSize
        paint.typeface = if (bold) {
   
            Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD)
        } else {
   
            Typeface.DEFAULT_BOLD
        }
        canvas.drawText(text, startX, startY, paint)
    }
}

封装指引步骤:GuideInfo

上面介绍了指引要素Shape,接下来需要继续完成指引要素的封装,命名为GuideInfo。GuideInfo封装了一个指引页面(或者说一帧)包含的所有显示要素,也就是多个Shape,包括:高亮的View区域,图片,文本等。GuideView显示指引,也就是把一个GuideInfo对象的Shape绘制出来。

class GuideInfo(
    private val targetView: View,            // 高亮显示的,要指引的View
    val padding: Int = 0,                    // 高亮区域的padding(如果要显示大一些时可设置padding)
    val isOval: Boolean = false,             // 高亮区域是否时圆形
    val radius: Float = 0F,                  // 如果时矩形,那么可以设置圆角
    private val paddingLeft: Int = 0,        // 四个方向的padding
    private val paddingTop: Int = 0,
    private val paddingRight: Int = 0,
    private val paddingBottom: Int = 0,
    autoShape: Boolean = false // 是否使用自定义的高亮区域,true: 自动根据View的Background获取Shape
) {
   

    val mShapes = mutableListOf<Shape>()
    var mTargetHighlightShape: Shape? = null // 这就是高亮显示的地方
    val targetBound: RectF                   // 高亮View的矩形区域,可根据这个矩形设置其它Shape的位置
}

一个GuideInfo对象代表一个指引步骤(一帧),一个完整的指引,可能包含多个步指引

绘制指引要素:GuideView

绘制指引的大概流程如下:

  1. 绘制一个半透明遮罩层;
  2. 绘制高亮显示的View区域;
  3. 绘制其它装饰,如图片,文本等。

代码如下:


class GuideView : View, View.OnTouchListener, GestureDetector.
  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值