乐趣区

关于html:惊天秘密如何在-Flutter-项目中实现操作引导

不要冒然评估我,你只晓得我的名字,却不晓得我的故事,你只是听闻我做了什么,却不知我经验过什么。

俗话说得好,产品有三宝,弹窗浮层加疏导。

上图截图自我司 App 晓黑板中的口算模块,置信每个 App 开发在工作中都碰到这种场景,为了防止用户对新性能产生困惑,会对一些性能加一些疏导操作。在原生开发中,例如 Android 开发中,咱们能够应用 NewbieGuide 等开源库来实现。然而很遗憾的是,在 Dart packages 中找了一圈,满载而归。

然而咱们还是很快就解决了问题,既然解决不了问题,咱们就要学会让这个问题不存在,这时候开发一宝就显得尤其有用了。

本文完,大家下期再见????

~

~

~

开个玩笑。真的猛男,敢于直面惨淡的人生,也敢于正视淋漓的鲜血,这区区需要怎么能打倒咱们。接下来咱们开始推敲一下这个疏导操作要怎么实现,置信各位小伙伴接到这个需要第一个想到的就是,这玩意儿不就是在整个页面下面盖一个蒙层,而后把两头再抠一块进去。最初再加一些文字和一个下一步按钮就行了嘛。你要是把这个需要想得这么简略,那你可就真是大对特对了。所以咱们就按后面说的三步来实现这个货色。当然,你如果不想接着往下看的话,能够间接点击这里应用咱们开发实现的疏导组件库来疾速在你的 Flutter 我的项目中接入疏导性能。

盖个蒙层

那么如何在 Flutter 页面上盖一个浮层呢?翻了一下 Flutter 的 API 文档,找到了两个法宝,别离是 Overlay 和 OverlayEntry。两者的应用办法如下。

class _MyWidgetState extends State<MyWidget> {
  OverlayEntry overlayEntry;
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          RaisedButton(onPressed: () {
              /// 1. 创立一个 overlayEntry 实例,builder 办法返回一个 Widget
              /// 该 Widget 会被渲染到页面顶层
              overlayEntry = OverlayEntry(builder: (context) => Container(color: Colors.white.withOpacity(.4),
                  child: Center(
                    child: RaisedButton(onPressed: () {
                        /// 3. 执行 remove 办法销毁 overlayEntry 实例
                        overlayEntry.remove();},
                      child: Text('点我敞开 OverlayEntry'),
                    ),
                  ),
                ),
              );
              /// 2. 应用 OverlayState.insert 办法来显示 overlayEntry
              Overlay.of(context).insert(overlayEntry);
            },
            child: Text('点我康康 Overlay 的用法'),
          ),
        ],
      ),
    );
  }
}

如果你不嫌烦的话,还能够点击这里亲自试一试成果。

两头抠一块儿

下面解决了浮层问题,上面咱们就来看一下如何让蒙层两头某一块区域亮起来的问题,这个问题很简略,为什么会亮,因为有光,怎么有光。我想到了上帝,因为上帝说要有光,于是就有了光。

成为上帝 I(找到组件所在位置)

接下来就是如何成为上帝的第一步,咱们要找到须要高亮的那个组件的大小和地位,通过我周密的考察,发现在 Flutter 中能够通过 GlobalKey 来获取一个元素的大小和地位,外围代码如下:

/// 1. 申明一个 globalKey
final globalKey = GlobalKey();

RaisedButton(
  /// 2. 将 globalKey 绑定到组件上
  key: globalKey,
  onPressed: () {///},
  child: Text('点我康康控制台输入',),
);

/// 3. 通过上面的代码来获取组件的尺寸和地位
RenderBox renderBox = globalKey.currentContext.findRenderObject();
Size size = renderBox.size;
Offset offset = renderBox.localToGlobal(Offset.zero);
print(size);
print(offset);

其中 Size 中有 widthheight 属性,别离示意高亮组件的宽高属性,Offset 中有 dxdy 属性,别离示意组件左上角间隔屏幕左侧和顶部的间隔。置信做 Web 开发的同学对这个都很相熟了。

如果你不嫌烦的话,还能够点击这里亲自试一试成果。

成为上帝 II(高亮组件所在区域)

咱们曾经在代码层面定位到这个组件的地位了,接下来就是对该区域进行精准打击,让这块区域不被浮层的色彩所笼罩,请看成为上帝的第二步。

先看后果,能够看到两头的组件没有被遮罩层遮住,然而有眼睛的同学可能会发现,为啥高低还会各有一段也没被遮住,那是因为 RaisedButton 高低自带一个 margin,所以代码获取 RaisedButton 的理论占位比看起来要大,有趣味的同学能够去钻研一下怎么去掉这个 margin。又有同学会说了,为啥这个截图是挪动端的截图,不是 Web 浏览器上的截图。这个问题问得好,请看上面外围代码。

OverlayEntry(builder: (context) => Stack(
    children: [
      /// 咱们应用了 ColorFiltered 来实现这个性能
      ColorFiltered(
        colorFilter: ColorFilter.mode(
          /// 遮罩层色彩
          Colors.red.withOpacity(.4),
          BlendMode.srcOut,
        ),
        child: Stack(
          children: [
            Container(
              decoration: BoxDecoration(
                /// 任何色彩均可
                color: Colors.white,
                backgroundBlendMode: BlendMode.dstOut,
              ),
            ),
            Positioned(
              /// 和须要高亮组件的大小和地位均统一
              child: Container(
                /// 任何色彩均可
                color: Colors.white,
                width: size.width,
                height: size.height,
              ),
              left: offset.dx,
              top: offset.dy,
            ),
          ],
        ),
      ),
    ],
  ),
);

下面能够看到,咱们应用了 StackPositioned 来实现将组件放到咱们想要的地位,而后实现高亮的外围组件是 ColorFiltered,ColorFiltered 可太好了,我可太喜爱这个组件了,它能做的事件也很乏味,前面咱们还再出一篇文章去独自地介绍它。敬请期待叭~

而后说一说为啥咱们的截图是挪动端,不再是 Web 端,因为 ColorFiltered 这哥们太强大,以至于 Flutter 团队在 Flutter Web 上还没有齐全实现它。你能够在 Flutter 仓库外面的轻易找到不少对于 ColorFiltered 在 Web 上体现异样的 Issue。

当然如果你不嫌烦的话,而且也违心在 Web 上试一下没有成果的成果,我也很贴心的为你筹备了在线链接。

成为上帝 III(加上下一步按钮和文字)

终于到了最初一步,加上下一步按钮和文字,这就不用说了,创立 overlayEntry 的时候你违心在 builder 办法外面返回啥都行。

那么我还漏掉了什么没说呢?认真思考的同学可能想到,我要怎么更新 overlayEntry 呢,疏导页个别有多个呀,我不能每次都 remove 掉以后的,而后再 insert 一个新的吧,那样页面必定会有闪动。其实如果认真看了 OverlayEntry 文档的话必定不会错过这个 markNeedsBuild 办法。这里就不再举个例子了,我太懒了。总之就是如果 builder 的内容有变动,你对 overlayEntry 执行一次 overlayEntry.markNeedsBuild() 就能够了,Flutter 就会从新渲染一次 builder 返回的内容。以此来做到无闪烁切换疏导页。

置信实现了下面三步,咱们即便没有成为上帝,也能做到有光,让指定区域高亮起来了。一句话总结:

咱们应用了 Overlay 和 ColorFiltered 即实现了疏导页的制作

我看完了

急躁看完了的小伙伴必定都感觉作者诚不欺我,的确很简略,这两个组件我都用过。然而:

So,咱们贴心地开发了一个小的库,并借鉴了 Web 端的出名疏导库 Intro.js 的名字,给它取名为 flutter_intro

少废话,先看货色。

上图即为应用 flutter_intro 的默认主题能够疾速实现的疏导成果。那么我要怎么应用呢?首先在我的项目依赖文件 pubspec.yaml 中引入 flutter_intro。点击这里查看最新版本。

引入 Intro 并实例化一个对象

import 'package:flutter_intro/flutter_intro.dart';

/// 1. 引入 Intro,实例化一个对象,传入必传的 stepCount 参数
/// 和 widgetBuilder 参数,其中 widgetBuilder 能够应用库内置的
/// 办法,这样就只需传入须要显示的文本即可。/// 当然如果你不嫌烦的话,也能够本人实现 widgetBuilder 办法
Intro intro = Intro(
  /// 总共的疏导页数量,必传
  stepCount: 4,

  /// 高亮区域与 widget 的内边距
  padding: EdgeInsets.all(8),

  /// 高亮区域的圆角半径
  borderRadius: BorderRadius.all(Radius.circular(4)),

  /// 应用库默认提供的 useDefaultTheme 能够疾速构建疏导页
  /// 须要自定义疏导页款式和内容,须要本人实现 widgetBuilder 办法
  widgetBuilder: StepWidgetBuilder.useDefaultTheme(
    /// 提醒文本
    texts: [
      '你好呀,我是 Flutter Intro。',
      '我能够帮你在 Flutter 我的项目中快读实现 Step By Step 疏导。',
      '我的用法也非常简略,你能够通过 example 和 api 文档疾速把握和应用。',
      '为了疾速实现疏导,我也默认提供了一套款式,开箱即用,祝大家应用欢快,再见!',
    ],
    /// 按钮文字
    btnLabel: '我晓得了',
    /// 是否在按钮后显示以后步骤
    showStepLabel: true,
  ),
);

下图为 flutter_intro 反对的一些参数配置所对应的地位介绍:

给须要加疏导的的 Widget 绑定 globalKey

好相熟的操作,和下面介绍的截然不同。

当然,这里为了不便大家应用,库的外部为大家创立好了 globalKey,应用的时候只须要通过 intro.keys[下标] 获取就行了。

Placeholder(
  /// 2. 第一个疏导页即绑定 keys 中的第一项,以此内推
  key: intro.keys[0]
)

真是太不便了!

全军出击

好了,咱们曾经做好全副的筹备了。输出以下指令,点击运行。

intro.start(context);

没了,是不是很简略。

你这个太丑了

如果你嫌我的默认主题丑,想要本人实现 widgetBuilder 办法,我也能够承受。

final Widget Function(StepWidgetParams params) widgetBuilder;

该办法会在疏导页呈现时由 flutter_intro 外部调用,并会将当前页面上的一些数据通过参数的模式 StepWidgetParams 传进来,最终渲染在屏幕上的为此办法返回的组件。

class StepWidgetParams {
  /// 返回前一个疏导页办法,如果没有,则为 null
  final VoidCallback onPrev;

  /// 进入下一个疏导页办法,如果没有,则为 null
  final VoidCallback onNext;

  /// 完结所有疏导页办法
  final VoidCallback onFinish;

  /// 以后执行到第几个疏导页,从 0 开始
  final int currentStepIndex;

  /// 疏导页的总数
  final int stepCount;

  /// 屏幕的宽高
  final Size screenSize;

  /// 高亮组件的的宽高
  final Size size;

  /// 高亮组件左上角坐标
  final Offset offset;
}

StepWidgetParams 提供了生成疏导页所须要的所有参数,默认提供的主题也是基于此参数生成疏导页。

序幕

天下没有不散的筵席,然而如果你请客,我能够多陪你吃一会儿。

这篇文章次要介绍了如何在 Flutter 中实现操作疏导,并且咱们基于此封装了一个咱们眼里东半球最好用的 flutter_intro


对 Electron 感兴趣?请关注咱们的开源我的项目 Electron Playground,带你极速上手 Electron。

咱们每周五会精选一些有意思的文章和音讯和大家分享,来掘金关注咱们的 晓前端周刊。


咱们是好将来 · 晓黑板前端技术团队。
咱们会常常与大家分享最新最酷的行业技术常识。
欢送来 知乎、掘金、Segmentfault、CSDN、简书、开源中国、博客园 关注咱们。

退出移动版