Peek & Pop
基于 iOS 同名功能的 Flutter Peek & Pop 实现。
终于,v1.0.0 版本发布了!比以往更加流畅、更加优化、更加美观。高度可定制,非常易于使用。
强烈建议阅读文档并在真实设备上运行示例项目,以充分理解和检查全部功能。
作为 iOS Peek & Pop 功能的粉丝,我也决定为 Flutter 实现它。
该包已在 iOS 上测试过,但在 Android 上尚未测试,因为我无法访问具有 Force Press 功能的 Android 设备。关于帮助
将不胜感激。
对于不支持 Force Press 的设备,该包附带了长按适配功能,*但是*该包的长按版本
仍在开发中,尚未完全测试,因此请将其视为开发预览。
(长按版本已暂时移除。将很快重新添加。)
这个包的强大之处在于我称之为“手势识别重路由”。通常,当一个带有 GestureDetector 或类似组件的新小部件
被推送到用于检测 Force Press 的初始小部件之上,或者当 Navigator 用于弹出新页面时,用户必须重新开始手势
才能让 Flutter 继续更新它。该包修复了这个问题,正如文档中所解释的
//This function is called by the instantiated [PeekAndPopChild] once it is ready to be included in the Peek & Pop process. Perhaps the most
//essential functionality of this package also takes places in this function: The gesture recognition is rerouted from the [PeekAndPopDetector]
//to the instantiated [PeekAndPopChild]. This is important for avoiding the necessity of having the user stop and restart their Force Press.
//Instead, the [PeekAndPopController] does this automatically so that the existing Force Press can continue to update even when if
//[PeekAndPopDetector] is blocked by the view which is often the case especially when using PlatformViews.
安装
很简单。别担心。
如果您不想使用 PlatformViews,可以跳过安装说明。
旧的安装说明已移除。如果您(出于某种原因)想使用 v0.1.9 之前的版本,请参阅该版本的 README 以获取
相应的安装说明。
为了正确显示 PlatformViews,此包需要最新的 Flutter master
分支。*也许*它也能在其他版本上工作,但使用 webview_flutter 进行的测试
似乎只能在最新的 Flutter master 分支上正常显示,该分支改进了 PlatformViews,
允许更好的功能,如正确的缩放和正确的裁剪。
如果您不想使用 PlatformViews,可以跳过此步骤。
要使用最新的 Flutter master 分支,请运行以下命令。
注意:不要忘记添加
webview_flutter。
$ git clone -b master https://github.com/flutter/flutter.git
$ flutter channel master
$ flutter upgrade
$ flutter doctor
$ ./flutter/bin/flutter --version
如何使用
也很简单。
首先,正如文档中所解释的
//I noticed that a fullscreen blur effect via the [BackdropFilter] widget is not good to use while running the animations required for the Peek &
//Pop process as it causes a noticeable drop in the framerate- especially for devices with high resolutions. During a mostly static view, the
//drop is acceptable. However, once the animations start running, this drop causes a visual disturbance. To prevent this, a new optimised blur
//effect algorithm is implemented. Now, the [BackdropFilter] widget is only used until the animations are about to start. At that moment, it is
//replaced by a static image. Therefore, to capture this image, your root CupertinoApp/MaterialApp MUST be wrapped in a [RepaintBoundary] widget
//which uses the [background] key. As a result, the Peek & Pop process is now up to 4x more fluent.
TL;DR:将您的根 CupertinoApp/MaterialApp 包装在 RepaintBoundary 小部件中,并使用“misc.dart”中的 background GlobalKey。
这是新优化的模糊效果算法所必需的。
import 'package:peek_and_pop/misc.dart' as PeekAndPopMisc;
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RepaintBoundary(
key: PeekAndPopMisc.background,
child: MaterialApp(
title: 'Peek & Pop Demo',
home: MyHomePage(title: 'Peek & Pop Demo')
)
);
}
}
如果您想使用“ScaleUp”或“Scale Down”功能,请将您希望在 Peek & Pop 过程中放大或缩小的组件包装在
“misc.dart”中的 scaleUpWrapper 和 scaleDownWrapper 函数中。
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
body: PeekAndPopMisc.scaleDownWrapper(
...,
0.04,
),
);
}
然后,创建一个 PeekAndPopController,例如
PeekAndPopController(
uiChild(), //Widget uiChild
false, //bool uiChildUseCache
peekAndPopBuilder, //PeekAndPopBuilder peekAndPopBuilder
false, //bool peekAndPopBuilderUseCache
{Key key,
quickActionsBuilder : quickActionsBuilder,
sigma : 10,
backdropColor : Colors.black,
alpha : 126,
overlayBuilder : overlayBuilder,
useOverlap : true,
customOverlapRect,
useAlignment, : false,
useIndicator : true,
indicatorScaleUpCoefficient : 0.01,
willPeekAndPopComplete : _willPeekAndPopComplete,
willPushPeekAndPop : _willPushPeekAndPop,
willUpdatePeekAndPop : _willUpdatePeekAndPop,
willCancelPeekAndPop : _willCancelPeekAndPop,
willFinishPeekAndPop : _willFinishPeekAndPop,
willClosePeekAndPop : _willClosePeekAndPop,
onPeekAndPopComplete : _onPeekAndPopComplete,
onPushPeekAndPop : _onPushPeekAndPop,
onUpdatePeekAndPop : _onUpdatePeekAndPop,
onCancelPeekAndPop : _onCancelPeekAndPop,
onFinishPeekAndPop : _onFinishPeekAndPop,
onClosePeekAndPop : _onFinishPeekAndPop,
onPressStart : _onPressStart,
onPressUpdate : _onPressUpdate,
onPressEnd : _onPressEnd,
treshold : 0.5,
startPressure : 0.125,
peakPressure : 1.0,
peekScale : 0.5,
peekCoefficient : 0.05,
popTransition})
Widget uiChild() {}
Widget peekAndPopBuilder(BuildContext context, PeekAndPopControllerState _peekAndPopController);
QuickActionsData quickActionsBuilder(PeekAndPopControllerState _peekAndPopController);
Widget overlayBuiler();
bool _willPeekAndPopComplete(PeekAndPopControllerState _peekAndPopController);
bool _willPushPeekAndPop(PeekAndPopControllerState _peekAndPopController);
bool _willUpdatePeekAndPop(PeekAndPopControllerState _peekAndPopController);
bool _willCancelPeekAndPop(PeekAndPopControllerState _peekAndPopController);
bool _willFinishPeekAndPop(PeekAndPopControllerState _peekAndPopController);
bool _willClosePeekAndPop(PeekAndPopControllerState _peekAndPopController);
void _onPeekAndPopComplete(PeekAndPopControllerState _peekAndPopController);
void _onPushPeekAndPop(PeekAndPopControllerState _peekAndPopController);
void _onUpdatePeekAndPop(PeekAndPopControllerState _peekAndPopController);
void _onCancelPeekAndPop(PeekAndPopControllerState _peekAndPopController);
void _onFinishPeekAndPop(PeekAndPopControllerState _peekAndPopController);
void _onClosePeekAndPop(PeekAndPopControllerState _peekAndPopController);
void _onPressStart(dynamic dragDetails);
void _onPressUpdate(dynamic dragDetails);
void _onPressEnd(dynamic dragDetails);
进一步说明
有关所有参数和方法的完整说明,请参阅文档。
- 如果您的 [uiChild] 在 Peek & Pop 过程中不发生变化,请将 [uiChildUseCache] 设置为 true。
- 如果您的 [peekAndPopBuilder] 在 Peek & Pop 过程中不发生变化,请将 [peekAndPopBuilderUseCache] 设置为 true。
- [overlayBuilder] 是一个可选的第二视图,将在 Peek & Pop 过程中显示。整个小部件将在其他所有内容之后构建。
- 对于所有 [PeekAndPopProcessNotifier] 回调,如 [willPeekAndPopComplete],您可以返回 false 以阻止默认操作。
- 所有 [PeekAndPopProcessNotifier] 和 [PeekAndPopProcessCallback] 回调将返回一个对创建的 [PeekAndPopController] 状态的引用。
您可以保存此实例以供将来使用。 - [pageTransition] 是在直接打开视图或关闭视图时使用的过渡。默认提供了一个 [SlideTransition]。
- 使用 [PeekAndPopControllerState] 的 [void closePeekAndPop()] 方法关闭 Peek & Pop 过程。不要直接调用 [Navigator.of(context).pop()]。
直接调用。 - 使用 [PeekAndPopControllerState] 的 [stage] 变量获取 Peek & Pop 过程阶段的枚举。如果您只想知道 Peek & Pop 过程
何时将完成或已完成,您也可以使用 [willBeDone] 或 [isDone] 变量。 - 我注意到,当 [AppBar] 或 [CupertinoNavigationBar] 构建为完全透明时,它们的高度未包含在 [Scaffold]
或 [CupertinoPageScaffold] 的布局中。因此,从具有透明头的 Peek 阶段移动到具有非透明头的 Pop 阶段
会导致视觉冲突。使用此 [PeekAndPopChildState] 的 [Size get headerSize] 和 [double getHeaderOffset(HeaderOffset headerOffset)] 方法来
解决此问题。