likes
comments
collection
share

Flutter 实现点击锚点跳转到对应位置

作者站长头像
站长
· 阅读数 24

Flutter 实现点击锚点跳转到对应位置

Flutter 实现点击锚点跳转到对应位置

本文相关代码

Flutter 开发 APP 时,如果同一页面内内容过多,且需要快速跳转时,可添加锚点组(图中四个锚点(按钮)为一个锚点组),点击锚点进行跳转(如开头图示)。

如果多个页面都需要相同的处理,则将锚点组做成共用组件是非常方便的。

思路

  1. APP 页面内容较多,需要放进滚动组件中,本文示例使用了 SingleChildScrollView 。 跳转使用最简单的 Scrollable.ensureVisible(context)。 即滚动到使 context 可见。
  2. 如何得到每个锚点组的 context 呢,可以使用 GlobalKey()currentContext 属性。 每个锚点组的 key 设置为不同的 GlobalKey() ,点击按钮时,Scrollable.ensureVisible() 的参数改为对应 keycurrentContext
  3. 想要制作成共用组件,还需要能根据不同的业务需求设置成不同个数的锚点(按钮),每个锚点显示的文字也可以再定制。
  4. 锚点组放置在各锚点相关内容的上面,这样点击锚点时,就会自动滚到相应的位置(如开头图示)。

定义锚点属性

锚点(按钮)和锚点组需要定义哪些属性呢?下面来分析一下。

  1. 锚点的属性需要知道点击时滚动到哪个锚点组的位置。 所以锚点属性里需要添加上 GlobalKey 类型的 key ,锚点组属性里也需要一个 GlobalKey 类型的 key,为了跳转时获取到相应的锚点组组件。
  2. 如何判断锚点是否选中,可为每个锚点设置一个 id ,锚点组也设置一个 id。 当前锚点组的 id 和 其中某个锚点的 id 相同时,则显示为选中状态。
  3. 最后,还需要的属性就是锚点(按钮)上显示的文字了。

现在基本上能确定,锚点的属性至少有三个。

  1. GlobalKey 类型的 key
  2. id
  3. 显示文字

如果还需要图标或者更多的定制,则可添加其它属性。

代码:

import 'package:flutter/material.dart';

class AnchorProperty {
  GlobalKey? key;
  String id;
  String label;

  AnchorProperty({
    this.key,
    required this.id,
    required this.label,
  });
}

锚点组组件

锚点组组件需要知道要表示多少个锚点(按钮),因为锚点是不固定的,所以需要接收一个 锚点属性 的列表,来动态组装。

锚点组组件的接口属性有以下三个:

  1. properties 锚点属性 的列表
  2. 锚点组的 GlobalKey
  3. 锚点组的 id

build 时,先根据 锚点属性 的列表动态组合成锚点(按钮)列表,再放到锚点组组件里。

注意点:

  1. 锚点组的 key 必须设置为整个锚点组的 GlobalKey
  2. 选中的锚点需要判断后设置背景色

生成锚点组列表

根据定义好的 锚点属性 的列表,生成锚点组列表。 事先定义的各个锚点,只设置 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
评论
请登录