Flutter 实现点击锚点跳转到对应位置
Flutter 实现点击锚点跳转到对应位置
Flutter 开发 APP 时,如果同一页面内内容过多,且需要快速跳转时,可添加锚点组(图中四个锚点(按钮)为一个锚点组),点击锚点进行跳转(如开头图示)。
如果多个页面都需要相同的处理,则将锚点组做成共用组件是非常方便的。
思路
- APP 页面内容较多,需要放进滚动组件中,本文示例使用了
SingleChildScrollView
。 跳转使用最简单的Scrollable.ensureVisible(context)
。 即滚动到使 context 可见。 - 如何得到每个锚点组的 context 呢,可以使用
GlobalKey()
的currentContext
属性。 每个锚点组的key
设置为不同的GlobalKey()
,点击按钮时,Scrollable.ensureVisible()
的参数改为对应key
的currentContext
。 - 想要制作成共用组件,还需要能根据不同的业务需求设置成不同个数的锚点(按钮),每个锚点显示的文字也可以再定制。
- 锚点组放置在各锚点相关内容的上面,这样点击锚点时,就会自动滚到相应的位置(如开头图示)。
定义锚点属性
锚点(按钮)和锚点组需要定义哪些属性呢?下面来分析一下。
- 锚点的属性需要知道点击时滚动到哪个锚点组的位置。
所以锚点属性里需要添加上
GlobalKey
类型的key
,锚点组属性里也需要一个GlobalKey
类型的key
,为了跳转时获取到相应的锚点组组件。 - 如何判断锚点是否选中,可为每个锚点设置一个
id
,锚点组也设置一个id
。 当前锚点组的id
和 其中某个锚点的id
相同时,则显示为选中状态。 - 最后,还需要的属性就是锚点(按钮)上显示的文字了。
现在基本上能确定,锚点的属性至少有三个。
GlobalKey
类型的key
id
- 显示文字
如果还需要图标或者更多的定制,则可添加其它属性。
代码:
import 'package:flutter/material.dart';
class AnchorProperty {
GlobalKey? key;
String id;
String label;
AnchorProperty({
this.key,
required this.id,
required this.label,
});
}
锚点组组件
锚点组组件需要知道要表示多少个锚点(按钮),因为锚点是不固定的,所以需要接收一个 锚点属性 的列表,来动态组装。
锚点组组件的接口属性有以下三个:
- properties 锚点属性 的列表
- 锚点组的
GlobalKey
- 锚点组的
id
build 时,先根据 锚点属性 的列表动态组合成锚点(按钮)列表,再放到锚点组组件里。
注意点:
- 锚点组的 key 必须设置为整个锚点组的
GlobalKey
。 - 选中的锚点需要判断后设置背景色
生成锚点组列表
根据定义好的 锚点属性 的列表,生成锚点组列表。
事先定义的各个锚点,只设置 id
和 显示文字,生成锚点组列表里,为每个锚点属性生成 GlobalKey
。
代码可参考仓库。
画面渲染
生成锚点组列表后,再把锚点组列表的每一个锚点组放到相关内容部分的上面。
有状态组件的内部状态变量及初始化:
anchorProperties
: 锚点属性列表anchors
: 锚点组列表
在 initState()
中定义好锚点属性列表后生成锚点组列表。如下:
List<AnchorProperty> anchorProperties = [];
List<Anchor> anchors = [];
@override
void initState() {
anchorProperties.add(AnchorProperty(id: '1', label: '人物'));
anchorProperties.add(AnchorProperty(id: '2', label: '风光'));
anchorProperties.add(AnchorProperty(id: '3', label: '建筑'));
anchorProperties.add(AnchorProperty(id: '4', label: '运动'));
anchors = AnchorHelper.anchorList(anchorProperties);
}
build
中的主要部分如下:
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
anchors.isNotEmpty ? anchors[0] : Container(),
Container(
height: 400,
color: Colors.teal,
child: const Center(child: Text('人物相关内容'))),
anchors.isNotEmpty ? anchors[1] : Container(),
Container(
height: 400,
color: Colors.orangeAccent,
child: const Center(child: Text('风光相关内容'))),
anchors.isNotEmpty ? anchors[2] : Container(),
Container(
height: 400,
color: Colors.indigoAccent,
child: const Center(child: Text('建筑相关内容'))),
anchors.isNotEmpty ? anchors[3] : Container(),
Container(
height: 400,
color: Colors.lime,
child: const Center(child: Text('运动相关内容'))),
],
),
)
结束语
主要使用了 GlobalKey()
的 currentContext
属性 和滚动的 Scrollable.ensureVisible(context)
方法。
其实不是太复杂的小功能,如果多个画面都有类似的设计,做成共用组件后,使用起来会比较方便。
转载自:https://juejin.cn/post/7294428296958378021