Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions requirements/issue-924-fab-on-long-press/TaskContract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# TaskContract — issue #924 [TDFab] 暴露 onLongPress 方法

## 基本信息

- issue: https://github.com/Tencent/tdesign-flutter/issues/924
- 组件:`TFab`
- 分支:`fix/issue-924-fab-on-long-press`
- 目录:`requirements/issue-924-fab-on-long-press`
- 类型:新特性(新增可选回调参数 `onLongPress`)

## 问题描述

业务需要在悬浮按钮上实现长按逻辑(例如长按展开菜单、快捷操作等)。`TFab` 内部使用 `InkWell` 承载点击,但未将长按能力透出,调用方无法接入 `onLongPress`。

## 根因分析

`TFab` 的 `build` 中仅向 `InkWell` 传入了 `onTap: onClick`,缺少 `onLongPress` 参数及对应构造字段,导致 Material 长按手势链路无法由外部配置。

## 修复方案

1. 为 `TFab` 增加可选参数 `onLongPress`(`VoidCallback?`),文档注释为「长按回调」。
2. 在 `InkWell` 上设置 `onLongPress: onLongPress`,与 `onTap` 并存,行为与 Flutter 原生一致。
3. 为满足仓库 `check-issue-fix` 对组件文件的色值检查,将原先硬编码的 `Colors.white` 与手写阴影改为 `TTheme.of(context).textColorAnti` 与主题投影 `shadowsMiddle` / `shadowsBase` 回退链。
4. 补充 `tdesign-component/test/t_fab_test.dart` 覆盖长按与单击共存;示例页增加「交互」模块演示长按弹出 `SnackBar`;同步 `example/assets/api/fab_api.md`。

## 贡献指南对照

- 开发规范:新增 API 使用 `///` 注释;样式与色值从 `TTheme` 获取;保持 `TFab` 命名与现有导出一致。
- 代码 Review 自检:构造方法在字段之前;未引入与需求无关的重构;测试可重复执行。
- 文档自检:示例与 API 表已更新;未手工改动 `tdesign-site/src/**/README.md`。

## 交付物清单

| 序号 | 交付物 | 说明 |
|------|--------|------|
| 1 | `requirements/issue-924-fab-on-long-press/test-cases.md` | 验收用例 |
| 2 | `requirements/issue-924-fab-on-long-press/code-review-report.md` | 代码审查结论 |
| 3 | `requirements/issue-924-fab-on-long-press/acceptance-report.md` | 验收报告 |
| 4 | `requirements/issue-924-fab-on-long-press/pr-body.md` | PR 摘要 |
| 5 | `tdesign-component/lib/src/components/fab/t_fab.dart` | 组件实现 |
| 6 | `tdesign-component/test/t_fab_test.dart` | 单元测试 |
| 7 | `tdesign-component/example/lib/page/t_fab_page.dart` | 示例演示 |
| 8 | `tdesign-component/example/assets/api/fab_api.md` | API 文档 |
43 changes: 43 additions & 0 deletions requirements/issue-924-fab-on-long-press/acceptance-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Acceptance Report — issue #924 [TDFab] 暴露 onLongPress 方法

## 验收结论

状态:通过(自动化测试与文档自检已完成;UI 光感变更建议设计走查)

## 需求对照

| 验收项 | 结果 | 说明 |
|--------|------|------|
| issue 要求透出长按能力 | 通过 | 新增 `onLongPress` 并绑定 `InkWell.onLongPress` |
| 与单击互不干扰 | 通过 | 见 `t_fab_test.dart` TC-02 |
| 示例可人工验证 | 通过 | `TFabPage`「交互」模块长按出 `SnackBar` |
| API 文档 | 通过 | `fab_api.md` 已增加参数行 |

## 执行检查

### 通过项

```bash
cd tdesign-component && flutter test test/t_fab_test.dart
cd tdesign-component && flutter analyze lib/src/components/fab/t_fab.dart
node scripts/issue-workflow/check-issue-fix.mjs \
--requirements-dir requirements/issue-924-fab-on-long-press \
--component-file tdesign-component/lib/src/components/fab/t_fab.dart \
--class-name TFab \
--all-build tdesign-component/demo_tool/all_build.sh \
--require-all-build-class
```

### 未通过项或阻塞项

- 无。

## 人工验收指引

1. 打开示例应用,进入 Fab 示例页,找到「交互」中的「Fab onLongPress 长按回调」。
2. 长按按钮,确认出现「已长按」提示。
3. 在业务工程中引用新版本 `TFab`,传入 `onLongPress` 验证自定义逻辑。

## 环境说明

- Flutter 测试在 macOS 本机执行;`tdesign_flutter_tools` 本地为 path stub,未运行全量 `all_build.sh` 生成 API,已手工维护 `fab_api.md` 与代码一致。
44 changes: 44 additions & 0 deletions requirements/issue-924-fab-on-long-press/code-review-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Code Review Report — issue #924

## 审查结论

状态:通过(自检)

## 修改范围

- `tdesign-component/lib/src/components/fab/t_fab.dart`:新增 `onLongPress`,`InkWell` 透传;图标反色与阴影改走主题。
- `tdesign-component/test/t_fab_test.dart`:新增用例。
- `tdesign-component/example/lib/page/t_fab_page.dart`:新增交互示例模块;`ExamplePage.test` 增加同构项便于站点「单元测试」区块生成。
- `tdesign-component/example/assets/api/fab_api.md`:API 表增加 `onLongPress` 行。

## 规范检查

### 1. 构造方法与字段顺序

- `TFab` 保持「构造方法在前、字段在后」;新增参数置于 `onClick` 之后,与 `InkWell` 参数语义相邻。

### 2. 注释风格

- 新增公开字段使用 `/// 长按回调`。

### 3. all_build 配置

- `TFab` 已在 `tdesign-component/demo_tool/all_build.sh` 中配置,本次未新增组件类名。

### 4. TTheme 使用

- 主色 / 危险态上图标与文字反色使用 `textColorAnti`;投影使用 `shadowsMiddle` 与 `shadowsBase` 回退。

### 5. TResourceDelegate 使用

- 本次无新增用户可见组件内固定文案;示例页 `SnackBar` 文案为演示用途,沿用示例页既有写法。

## 正确性评审

- `onLongPress` 为可选,默认 `null` 时行为与升级前一致(无长按回调)。
- 单击与长按手势由 `InkWell` 区分,与 Flutter 默认语义一致;已由 TC-01、TC-02 锁定。

## 风险与未验证项

- 投影由自定义三层阴影改为主题 `shadowsMiddle` / `shadowsBase`,FAB 外观光感可能与旧版略有差异,但更符合设计 token;若设计侧有专门 FAB 投影 token,可后续单独收敛。
- 本地 `dart run tdesign_flutter_tools` 生成命令不可用(stub 包),`fab_api.md` 已手工同步;若 CI 会跑全量 `all_build.sh`,应以 CI 产物为准再核对一行差异。
58 changes: 58 additions & 0 deletions requirements/issue-924-fab-on-long-press/pr-body.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
### 🤔 这个 PR 的性质是?
> 勾选规则:
> 1.只要有新增参数,就勾选”新特性提交“
> 2.只修改内部bug,未新增参数,才勾选”日常 bug 修复“
> 3.其他选项视具体改动判断

- [ ] 日常 bug 修复
- [x] 新特性提交
- [ ] 文档改进
- [x] 演示代码改进
- [x] 组件样式/交互改进
- [ ] CI/CD 改进
- [ ] 重构
- [ ] 代码风格优化
- [x] 测试用例
- [ ] 分支合并
- [ ] 其他

### 🔗 相关 Issue

需求来源:悬浮按钮需要长按扩展能力。

https://github.com/Tencent/tdesign-flutter/issues/924

### 💡 需求背景和解决方案

**问题**:`TFab` 仅支持单击 `onClick`,业务无法实现长按菜单等交互。

**方案**:

- 新增可选参数 `onLongPress`(`VoidCallback?`),并传给内部 `InkWell.onLongPress`。
- 将原先硬编码的反色与阴影改为 `TTheme` 中的 `textColorAnti` 与 `shadowsMiddle` / `shadowsBase`,满足主题规范与强制检查。

**用法示例**:

```dart
TFab(
theme: TFabTheme.primary,
text: '操作',
onClick: () {},
onLongPress: () {},
)
```

### 📝 更新日志

- feat(TFab): 新增 `onLongPress`,支持长按回调;图标反色与投影改为主题 token。

- [ ] 本条 PR 不需要纳入 Changelog

### ☑️ 请求合并前的自查清单

⚠️ 请自检并全部**勾选全部选项**。⚠️

- [x] pr目标分支为develop分支,请勿直接往main分支合并
- [x] 标题格式为:`组件类名`: 修改描述(示例:`TBottomTabBar`: 修复iconText模式,底部溢出2.5像素)
- [x] ”相关issue“处带上修复的issue链接
- [x] 相关文档已补充或无须补充
19 changes: 19 additions & 0 deletions requirements/issue-924-fab-on-long-press/test-cases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# 测试用例 — issue #924 [TDFab] 暴露 onLongPress 方法

## TC-01

- **前置条件**:使用 `TTheme` + `MaterialApp` 包裹 `TFab`,并设置非空的 `onLongPress` 回调。
- **操作**:对 `TFab` 执行 `longPress` 手势。
- **期望**:`onLongPress` 被调用一次。

## TC-02

- **前置条件**:同一 `TFab` 上同时设置 `onClick` 与 `onLongPress`。
- **操作**:先 `tap`,再 `longPress`。
- **期望**:单击只触发 `onClick`,不触发 `onLongPress`;长按触发 `onLongPress`。

## TC-03

- **前置条件**:运行示例应用,进入「Fab」示例页;打开「单元测试」折叠区,或进入主内容区「交互」模块。
- **操作**:长按展示「长按」文案的悬浮按钮。
- **期望**:出现内容为「已长按」的 `SnackBar`(人工走查)。
1 change: 1 addition & 0 deletions tdesign-component/example/assets/api/fab_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
| icon | Icon? | - | 图标 |
| key | | - | |
| onClick | VoidCallback? | - | 点击事件 |
| onLongPress | VoidCallback? | - | 长按回调 |
| shape | TFabShape | TFabShape.circle | 形状 |
| size | TFabSize | TFabSize.large | 大小 |
| text | String? | - | 文本 |
Expand Down
15 changes: 15 additions & 0 deletions tdesign-component/example/assets/code/fab._buildLongPressFab.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

Widget _buildLongPressFab(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 16),
child: TFab(
theme: TFabTheme.primary,
text: '长按',
onLongPress: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('已长按')),
);
},
),
);
}
31 changes: 30 additions & 1 deletion tdesign-component/example/lib/page/t_fab_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,17 @@ class _TFabPageState extends State<TFabPage> {

@override
Widget build(BuildContext context) {
return ExamplePage(title: tTitle(), exampleCodeGroup: 'fab', children: [
return ExamplePage(
title: tTitle(),
exampleCodeGroup: 'fab',
test: [
ExampleItem(
ignoreCode: true,
desc: 'TFab onLongPress 长按回调',
builder: _buildLongPressFab,
),
],
children: [
ExampleModule(title: '组件类型', children: [
ExampleItem(desc: 'Icon Fab 纯图标悬浮按钮', builder: _buildPureIconFab),
ExampleItem(
Expand All @@ -26,6 +36,9 @@ class _TFabPageState extends State<TFabPage> {
ExampleItem(desc: 'Fab Theme 悬浮按钮主题', builder: _buildThemeFab),
ExampleItem(desc: 'Fab Shape 悬浮按钮形状', builder: _buildShapeFab),
ExampleItem(desc: 'Fab Size 悬浮按钮尺寸', builder: _buildSizeFab)
]),
ExampleModule(title: '交互', children: [
ExampleItem(desc: 'Fab onLongPress 长按回调', builder: _buildLongPressFab),
])
]);
}
Expand Down Expand Up @@ -99,6 +112,22 @@ class _TFabPageState extends State<TFabPage> {
]);
}

@Demo(group: 'fab')
Widget _buildLongPressFab(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 16),
child: TFab(
theme: TFabTheme.primary,
text: '长按',
onLongPress: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('已长按')),
);
},
),
);
}

@Demo(group: 'fab')
Widget _buildSizeFab(BuildContext context) {
return _buildRowDemoWidthDescription([
Expand Down
Loading
Loading