CupertinoMagnifier
一个仿iOS风格的放大镜组件,主要用于文本选择或触摸点细节的局部放大显示
CupertinoMagnifier是Flutter中一个仿iOS风格的放大镜组件,主要用于文本选择或触摸点细节的局部放大显示。它模拟了iOS系统的原生放大镜效果,通过悬浮层展示指定区域的放大视图。
核心逻辑
- 组件通过监听手势位置(如拖拽文本选择手柄)动态定位放大镜。
- 基于
MagnifierController控制放大镜的显示/隐藏和位置更新。 - 内部使用
LayerLink将放大镜与需要放大的内容区域关联,确保放大内容同步。
典型使用场景
- 文本输入框(
CupertinoTextField)中长按拖动选择文本时显示放大镜。 - 自定义手势交互中需要高精度定位的场景(如地图应用中的坐标点放大)。
- 配合
TextSelectionToolbar实现iOS风格的文字操作界面。
示例
基础文本选择放大镜
import 'package:flutter/cupertino.dart';
class BasicMagnifierDemo extends StatelessWidget {
Widget build(BuildContext context) {
return CupertinoApp(
home: CupertinoPageScaffold(
child: Center(
child: CupertinoTextField(
magnifierConfiguration: TextMagnifierConfiguration(
magnifierBuilder: (context, controller, value) {
return CupertinoMagnifier(
controller: controller,
child: Text(value.text), // 放大镜中显示的文字内容
);
},
),
),
),
),
);
}
}
自定义手势控制的放大镜
import 'package:flutter/cupertino.dart';
class CustomMagnifierDemo extends StatefulWidget {
_CustomMagnifierDemoState createState() => _CustomMagnifierDemoState();
}
class _CustomMagnifierDemoState extends State<CustomMagnifierDemo> {
final MagnifierController _controller = MagnifierController();
final LayerLink _layerLink = LayerLink();
Widget build(BuildContext context) {
return CupertinoApp(
home: CupertinoPageScaffold(
child: Stack(
children: [
// 需要放大的内容区域
CompositedTransformTarget(
link: _layerLink,
child: GestureDetector(
onPanUpdate: (details) {
_controller.show(details.localPosition); // 根据手势更新位置
},
child: Container(color: CupertinoColors.activeBlue),
),
),
// 放大镜组件
Positioned(
child: CupertinoMagnifier(
controller: _controller,
layerLink: _layerLink,
),
),
],
),
),
);
}
}
适配暗色主题的放大镜
CupertinoMagnifier(
controller: controller,
color: CupertinoTheme.of(context).bgColor.withOpacity(0.9), // 根据主题调整颜色
shadowColor: CupertinoColors.black.withOpacity(0.2),
)
注意点
-
常见问题与解决方案:
- 性能瓶颈: 频繁调用
controller.show()可能导致帧率下降。建议使用throttle或debounce限制调用频率。 - 兼容性警告: 在非iOS平台使用时,需测试手势响应是否正常(Android可能需额外适配)。
- 内容同步异常: 若放大镜与目标区域错位,检查
LayerLink是否正确绑定到同一CompositedTransformTarget。
- 性能瓶颈: 频繁调用
-
优化技巧:
- 通过
color和shadowColor属性自定义样式,使其更贴合应用主题。 - 使用
MagnifierController的hide()方法在无需显示时及时隐藏,减少资源占用。
- 通过
-
最佳实践:
- 优先与
CupertinoTextField等官方组件配合使用,避免手动处理复杂手势逻辑。 - 在
Stack中确保放大镜位于视图顶层,防止被其他组件遮挡。
- 优先与
构造函数
const CupertinoMagnifier({
Key? key,
required MagnifierController controller, // 控制放大镜行为的核心控制器
LayerLink? layerLink, // 关联放大内容区域的链接对象
Color? color, // 放大镜背景色(默认透明灰)
Color? shadowColor, // 阴影颜色(默认深灰)
Widget? child, // 自定义放大镜内部显示的组件
})
属性
| 属性名 | 属性类型 | 说明 |
|---|---|---|
controller | MagnifierController | 必需。控制放大镜的显示、隐藏和位置更新。 |
layerLink | LayerLink? | 可选。绑定到目标内容的链接,确保放大内容同步。 |
color | Color? | 放大镜背景颜色,默认值为 CupertinoColors.tertiarySystemFill。 |
shadowColor | Color? | 放大镜阴影颜色,默认值为 CupertinoColors.systemGrey。 |
child | Widget? | 自定义放大镜内部显示的组件,如覆盖默认文本显示。 |
关键属性详解
controller: 必须通过MagnifierController()初始化,并通过show(Offset)方法传入手势位置坐标。这是放大镜动态响应的核心。layerLink: 当需要放大非文本内容(如图片)时,此属性必需。需与CompositedTransformTarget配对使用,否则放大镜无法捕获目标区域。color: 透明度过高可能导致放大内容不清晰,建议使用withOpacity(0.8~0.95)保持可读性。