gpt4 book ai didi

android - 是否可以为 Flutter 的可访问性焦点系统强制平滑隐式滚动?

转载 作者:行者123 更新时间:2023-12-03 03:23:39 25 4
gpt4 key购买 nike

我目前正在调整 Flutter 应用以与 Android TV 设备配合使用。这方面的文档很少,但我已经设法通过使用可访问性焦点系统使用标准 Remote 进行定向导航来感受我的方式。

但是,在我的一个布局中,我使用了 PageView包含一些项目网格,网格分离成页面以获得更好的定向导航人体工程学。正如所料,创建 PageViewallowImplicitScrolling: true允许您通过将焦点标线移出网格一侧来在页面之间导航。但是,任何上下文中的隐式滚动都不会伴随任何动画,只是立即转换到下一个 View 位置。这最终看起来不太好。实际上,同样的问题适用于所有隐式滚动,无论是在 PageView 中。 , ListView , GridView ,或任何 ScrollView 。

Widget _buildPaginatedGrid(BuildContext build) {
return SliverToBoxAdapter(
child: Container(
height: MediaQuery.of(build).size.height - gameHeroHeight(context),
child: PageView(
allowImplicitScrolling: true,
controller: _pageController,
children: [
_buildRawGrid(build), //just display the same grid twice for testing
_buildRawGrid(build)
]
),
),
);
}

我知道这种滚动是由对 RenderObject.showOnScreen 的调用驱动的。 ,显然持续时间为零,所以我尝试创建一个 SingleChildRenderObjectWidget子类 RenderProxyBox覆盖 RenderObject.showOnScreen强制持续时间的方法。然而,无论我把这个东西放在哪里,围绕每个单独的网格项目,围绕网格,围绕 PageView ,在隐式滚动期间没有任何动画显示,事实上,我的覆盖方法甚至从未被调用过。就像调用永远不会传播到它,无论它放置在小部件层次结构中的哪个位置。

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

class RenderFocusSmoothScroll extends RenderProxyBox {
RenderFocusSmoothScroll({RenderBox child}) : super(child);
@override
void showOnScreen({
RenderObject descendant,
Rect rect,
Duration duration = Duration.zero,
Curve curve = Curves.ease,
}) {
print("showOnScreen");
super.showOnScreen(descendant: descendant, rect: rect, duration: Duration(milliseconds: 200), curve: Curves.ease);
}
}

class FocusSmoothScroll extends SingleChildRenderObjectWidget {
const FocusSmoothScroll({
Key key,
Widget child,
}) : super(key: key, child: child);

@override
RenderFocusSmoothScroll createRenderObject(BuildContext context) {
return RenderFocusSmoothScroll();
}

@override
void updateRenderObject(BuildContext context, RenderFocusSmoothScroll renderObject) {

}
}

关于使用焦点系统的隐式滚动的文档有点缺乏,关于正确覆盖 RenderObject 的文档也是如此。强制对这些传播调用进行自定义处理的方法,因此我们将不胜感激。

最佳答案

好吧,我想通了。结果调用showOnScreen实际上是在框架自己的FocusTraversalPolicy源代码(lib/src/widgets/focus_traversal.dart)。我没想到,我认为焦点遍历策略专门用于建立小部件之间的方向性关系,而不是实际将它们滚动到屏幕上。我只需要覆盖特定函数的主体:

@protected
void _focusAndEnsureVisible(FocusNode node, {ScrollPositionAlignmentPolicy alignmentPolicy = ScrollPositionAlignmentPolicy.explicit}) {
node.requestFocus();
Scrollable.ensureVisible(node.context, alignment: 1.0, alignmentPolicy: alignmentPolicy);
}

调用 ensureVisible不包括持续时间,因此,目标将立即滚动到。我最终需要将这个模块的大部分内容复制到我自己的项目中,因为没有任何方法可以重定向内置的 ReadingOrderTraversalPolicy使用该模块私有(private)函数的不同实现。当然不理想,该功能显然不打算被覆盖,但你绝对可以。

/// Overridden for smooth scrolling.
@protected
void _focusAndEnsureVisible(FocusNode node, {ScrollPositionAlignmentPolicy alignmentPolicy = ScrollPositionAlignmentPolicy.explicit}) {
node.requestFocus();
Scrollable.ensureVisible(
node.context,
alignment: 1.0,
alignmentPolicy: alignmentPolicy,
duration: Duration(milliseconds: 200),
curve: Curves.ease,
);
}

因此,从该文件中复制子类和 mixins 并重命名 ReadingOrderTraversalPolicySmoothReadingOrderTraversalPolicy ,我最终只是坚持了 DefaultFocusTraversal我的顶级 MaterialApp 的构建器包装中的小部件, 像这样:

@override
Widget build(BuildContext context) {
return MaterialApp(
title: '...',
theme: /* ... */,
home: SplashView(),
navigatorKey: Globals.rootNavigatorKey,
initialRoute: '/splash',
routes: <String, WidgetBuilder>{
// ...
},
onGenerateRoute: _generateRoute,
builder: (context, widget) => DefaultFocusTraversal(
policy: SmoothReadingOrderTraversalPolicy(), //imported from my own copy
child: Stack(children: [widget, /* ... */]),
),
);
}

现在隐式滚动很流畅!如果其他人遇到这个问题,我希望这会有所帮助。

感谢@pskink 促使我更深入地了解方法调用的来源,在我想深入了解遍历策略本身之前,我只是被难住了。

关于android - 是否可以为 Flutter 的可访问性焦点系统强制平滑隐式滚动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60235386/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com