【问题标题】:How to suppress scroll-into-view behavior in Flutter?如何抑制 Flutter 中的滚动显示行为?
【发布时间】:2020-10-15 23:39:40
【问题描述】:

我有一个 CustomScrollView 和一个隐藏在滚动条上的 SliverAppBar

应用栏上有一个搜索按钮,按下该按钮时,会将TextField 放入应用栏中。

当字段获得焦点时,它会导致滚动视图一直滚动到顶部,并且应用栏卡在“不安全”区域:

Scaffold docs 提到,当显示键盘时,脚手架的插图发生变化并重建脚手架,导致“如果焦点小部件位于可滚动容器内,则会滚动到视图中”。

这似乎是我不想要的行为。我看了但无法理解机制或如何抑制它。这样做可以吗?

图片中视图的源代码为here

我还注意到,这个问题在我之前使用非 sliver 标准小部件的实现中没有发生。我怀疑这是因为应用栏不在可滚动视图中,而 SliverAppBar 位于 CustomScrollView 内部,因此它可以与主体交互。

【问题讨论】:

  • 不确定这是否能解决问题,但尝试使用floating: true, pinned: true, snap: true 制作应用栏。 Doc Reference
  • 我不想将其固定,因此即使解决了滚动和/或安全区域问题,它仍然无法解决我的问题。
  • 好的。只是问,再次设置pinned: false, 会出现滚动/安全区域问题?
  • 上面的 gif 显示了 pinned: false 的情况。 pinned: true 案例将应用栏锁定在正确的位置,但下方的内容仍在滚动,并且滚动到稍微错误的偏移量(逐栏重叠)。

标签: flutter focus flutter-appbar flutter-scaffold


【解决方案1】:

编辑:此问题已由 this PR 修复,它似乎首先出现在 Flutter 1.22.0 中。

经过一番调查,我最终找到了这种行为的机制。

TextField 包裹 EditableText。当后者获得焦点时,它将调用_showCaretOnScreen,其中包括a call to renderEditable.showOnScreen。这会冒泡并最终导致滚动行为。

如果我们向TextField 提供一个总是从hasClients 返回false 的被黑ScrollController,我们可以强制_showCaretOnScreen 提前返回here

class _HackScrollController extends ScrollController {
  // Causes early return from EditableText._showCaretOnScreen, preventing focus
  // gain from making the CustomScrollView jump to the top.
  @override
  bool get hasClients => false;
}

这种行为似乎不是故意的,所以我将其报告为bug #60422

注意事项

这种解决方法可能不是很稳定。

我不知道hasClients 覆盖可能会产生什么不利影响。

docs for TextField 表示scrollController 用于“垂直滚动输入时”。在这个用例中,我们无论如何都不希望垂直滚动,因此解决方法可能不会导致任何问题。在我的简短测试中,它似乎没有导致水平(溢出)滚动问题。

【讨论】:

    【解决方案2】:

    就像文档中提到的那样,在脚手架小部件 https://api.flutter.dev/flutter/material/Scaffold/resizeToAvoidBottomInset.html 中尝试使用 resizeToAvoidBottomInset 参数为 false(默认为 true)

    另外我建议在脚手架之后创建 ValueListenableBuilder(作为主体中的第一个小部件),以避免重建整个脚手架和仅主体小部件

    【讨论】:

    • resizeToAvoidBottomInset: false 不会影响这一点。 ValueListenableBuilder 在脚手架之外,因为在之前的实现中,我需要在构建脚手架时使用结果值。但是,是的,它现在可以搬进去了。
    • 如何使用 resizeToAvoidBottomInset 并用 SafeArea 包装小部件?
    • resizeToAvoidBottomInset 对此完全没有影响。应用栏周围的SafeArea a) 让它看起来很奇怪,因为应用栏应该稍微处于不安全区域,并且 b) 并且不影响滚动到顶部的行为.
    • 您是否将 SliverSafeArea 用于 SliverAppBar?还是只是脚手架上的 SafeArea?
    • 没关系,因为两者都是错误的:脚手架和应用栏都需要在不安全区域。这仍然没有解决滚动行为。
    猜你喜欢
    • 2014-04-23
    • 2021-08-04
    • 2010-10-15
    • 2010-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-10
    相关资源
    最近更新 更多