Flutter开发者

Tooltip

2018-09-27

上期回顾

在前面的文章中我们讲到了Wrap的用法,介绍了Flutter中的流式布局,在文章的最后让大家实现如下效果:

其实实现起来非常的简单,使用Align设置对齐方式为topCenter让Wrap上中对齐,然后自定义Button借助于Contaner和OutlineButton来实现上面的按钮效果,然后处理点击事件弹出SnackBar即可。

具体代码如下,就不再具体讲解了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

import 'package:flutter/material.dart';

void main() {
runApp(new MaterialApp(
home: new MyApp(),
));
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Wrap"),
centerTitle: true,
),
body: Align(
alignment: Alignment.topCenter,
child: Wrap(
spacing: 10.0,
runSpacing: 5.0,
direction: Axis.horizontal,
alignment: WrapAlignment.start,
children: <Widget>[
MyButton("斗罗大陆"),
MyButton("遮天"),
MyButton("盗墓笔记"),
MyButton("天龙八部"),
MyButton("凡人修仙传"),
MyButton("大主宰"),
MyButton("仙逆"),
MyButton("斗鱼"),
MyButton("校花的贴身高手"),
MyButton("酒神"),
MyButton("最好的我们"),

],
)),
);
}
}

class MyButton extends StatelessWidget {
final text;

MyButton(this.text);

@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(left: 3.0, right: 3.0),
child: OutlineButton(
borderSide: BorderSide(
color: Colors.blueAccent, width: 2.0, style: BorderStyle.solid),
disabledBorderColor: Colors.grey,
highlightedBorderColor: Colors.redAccent,
onPressed: () {
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text(text),
action: new SnackBarAction(
label: "撤回",
onPressed: () {},
),
));
},
child: Text(text),
));
}
}

轻量级操作提示

在面的文章中,我们讲到了Dialog、Snackbar以及BottomSheet的用法,这些操作提示都是比较重量级的,存在屏幕上的时间较长或者会直接打断用户的操作。

当然并不是说这些操作提示不好,只是我需要给大家讲今天的内容啊,轻量级的操作提示Tooltip

Tooltip是继承于StatefulWidget的一个Widget,它并不需要其他借助于类似showDialog、showModalBottomSheet或者SnackBarAction类似的方法来调出,当用户长按被Tooltip包裹的Widget时,会自动弹出相应的操作提示。


接下来还是具体来看下如何使用吧!

Tooltip

首先还是到源码里面群看下Tooltip的构造方法。

1
2
3
4
5
6
7
8
9
10
11

Tooltip({
Key key,
@required this.message,//提示的内容
this.height = 32.0,//Tooltip的高度
this.padding = const EdgeInsets.symmetric(horizontal: 16.0),//padding
this.verticalOffset = 24.0,//具体内部child Widget竖直方向的距离
this.preferBelow = true,//是否显示在下面
this.excludeFromSemantics = false,
this.child,
})

构造方法依然是很简单(岂止是构造方法简单,真个源码实现也是非常的简单),接下来还是先看个最简单的例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

import 'package:flutter/material.dart';

void main() {
runApp(new MaterialApp(
home: new MyApp(),
));
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Tooltips"),
),
body: Center(
child: Tooltip(
message: "点击删除",
child: Icon(
Icons.delete,
size: 50.0,
)),
),
);
}
}

我们在Icon的最外面包裹了一个Tooltip,并且设置message为“点击删除”,这样一来每次当我们长按这个图标就会自动弹出一个tip

当然,我们可以修改Tooltip的其他属性来更改它的显示效果。

比如,我想要这个tip显示在这个图标的上面,我们只需要修改如下属性即可

preferBelow: false,

或者,我们想要让这个tip距离我们的Icon的垂直方向的距离大一些,修改如下属性:

verticalOffset: 60.0,

又或许你觉得tip的显示区域太小了,你想要让它变大点?

借助于hight属性可以修改tip的高度

height: 132.0

但是正如你所见,tip的宽度不会改变,如果想要修改tip的同时宽度和高度,使用padding是一个不错的选择

padding: EdgeInsets.symmetric(vertical: 50.0, horizontal: 50.0)

还没结束

其实已经结束了啊,哈哈。

如果你觉得上述的样式修改依然不能满足你,那怎么办?

来看下源码吧

这里仅仅贴出了tip的这个Widget构造的源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

class _TooltipOverlay extends StatelessWidget {
const _TooltipOverlay({
Key key,
this.message,
this.height,
this.padding,
this.animation,
this.target,
this.verticalOffset,
this.preferBelow,
}) : super(key: key);

final String message;
final double height;
final EdgeInsetsGeometry padding;
final Animation<double> animation;
final Offset target;
final double verticalOffset;
final bool preferBelow;

@override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
final ThemeData darkTheme = ThemeData(
brightness: Brightness.dark,
textTheme: theme.brightness == Brightness.dark ? theme.textTheme : theme.primaryTextTheme,
platform: theme.platform,
);
return Positioned.fill(
child: IgnorePointer(
child: CustomSingleChildLayout(
delegate: _TooltipPositionDelegate(
target: target,
verticalOffset: verticalOffset,
preferBelow: preferBelow,
),
child: FadeTransition(
opacity: animation,
child: Opacity(
opacity: 0.9,
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: height),
child: Container(
decoration: BoxDecoration(
color: darkTheme.backgroundColor,
borderRadius: BorderRadius.circular(2.0),
),
padding: padding,
child: Center(
widthFactor: 1.0,
heightFactor: 1.0,
child: Text(message, style: darkTheme.textTheme.body1),
),
),
),
),
),
),
),
);
}
}

我们可以看到_TooltipOverlay这个Widget继承于StatelessWidget,构造方法传入了很多的参数用于构建这个tip,当然我们上面讲到的几个属性也都在这里有体现。

比如我们可以修改BoxDecoration中的属性来修改tip的高,修改BoxDecoration中的属性来控制tip的样式,或者修改Center中的widthFactor和heightFactor来控制宽高比等等。

我们再看看message使用的地方。

1
2
3
4
5
6

child: Center(
widthFactor: 1.0,
heightFactor: 1.0,
child: Text(message, style: darkTheme.textTheme.body1),
)

好吧,我们的message最终提现也就是个Text而已。所以我们也可以进行下修改,放置自己想要的Widget

但是呢,如果没有特殊的需要还是不建议修改哦,毕竟material官方对tooltips的颜色大小方向等都已经做了最合适的定义。

material.io

好了,真的结束了

小结

  • Tooltip可以很方便的实现轻量级的提示
  • Tooltip可以包裹在任何你想要包裹的Widget上面来达到提示的效果
  • 通过修改Tooltip的属性可以很简单的修改达到想要的效果。
  • 更特殊的要求可以根据源码自己实现一个Tooltip看看哦

试一下

根据前面讲到的一大堆实现自定义Tooltip的效果

使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

打赏请备注姓名或者昵称,方便我后期统计哦

关注公众号,及时查阅最新文章