我使用的是SingleChildScrollView。它的scrollDirection设置为Horizontal,行小部件中放置了20多个子小部件。我想以编程方式滚动到行中的一个位置小部件(即第5或第6个位置)。有什么方法可以以编程方式实现吗?
SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( children: buttons, ), )
zpqajqem1#
最简单的方法是使用Scrollable.ensureVisible。可见光法滚动包含给定上下文的可滚动项,以使给定上下文可见。请看下面的代码:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key key, this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { int _value = 0; static final List<GlobalKey> _key = List.generate(20, (index) => GlobalKey()); final List<Widget> buttons = List.generate( 20, (index) => RaisedButton( onPressed: () {}, color: index % 2 == 0 ? Colors.grey : Colors.white, child: Text("Button No # ${index + 1}", key: _key[index]), ), ); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Column( children: [ SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: buttons, ), ), DropdownButton( value: _value, items: List.generate( 20, (index) => DropdownMenuItem( child: Text("Goto Button # ${index + 1}"), value: index), ), onChanged: (value) { setState(() { _value = value; print("calling"); Scrollable.ensureVisible(_key[value].currentContext); }); }, ) ], ), ); } }
p1iqtdky2#
您可以定义ScrollController:
ScrollController
ScrollController _controller = new ScrollController();
将其传递给SingleChildScrollView:
SingleChildScrollView
SingleChildScrollView( controller: _scrollController, scrollDirection: Axis.horizontal, child: Row( children: buttons, ), ),
并以编程方式滚动它,如下所示:
void scroll(double position) { _scrollController.jumpTo(position); }
或者,如果需要滚动动画:
void scrollAnimated(double position) { _scrollController.animateTo(position, Duration(seconds: 1), Curves.ease); }
如果您希望在布局构建完成后立即自动滚动,可以通过重写initState方法来实现:
initState
@override void initState() { super.initState(); WidgetsBinding.instance .addPostFrameCallback((_) => scroll(500)); // scroll automatically 500px (as an example) }
0s7z1bwu3#
您可以在SingleChildScrollView中添加ScrollController并滚动到您想要的特定位置
_scrollController.animateTo( //here specifing position= 100 mean 100px 100, curve: Curves.ease, duration: Duration(seconds: 1),
tktrz96b4#
这也可以在无状态小部件中完成,方法是在构建方法中触发它。使用addPostFrameCallback来确保在渲染完成后完成滚动。您需要为所选的value添加回状态管理。但是您可以选择使用GetX、StatefulWidget或任何其他工具。
addPostFrameCallback
value
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatelessWidget { MyHomePage({Key? key, this.title}) : super(key: key); final String? title; static final List<GlobalKey> _key = List.generate(20, (index) => GlobalKey()); final List<Widget> buttons = List.generate( 20, (index) => ElevatedButton( onPressed: () {}, style: ButtonStyle(backgroundColor: MaterialStateProperty.resolveWith((_)=> index % 2 == 0 ? Colors.lightGreen : Colors.orange)), child: Text("Button No # ${index + 1}", key: _key[index]), ), ); @override Widget build(BuildContext context) { final thisWidget = Scaffold( appBar: AppBar( title: Text(title!), ), body: Column( children: [ SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: buttons, ), ), DropdownButton( value: 0, items: List.generate( 20, (index) => DropdownMenuItem( value: index, child: Text("Goto Button # ${index + 1}")), ), onChanged: (value) { if (value != null) { WidgetsBinding.instance .addPostFrameCallback((_) => Scrollable.ensureVisible(_key[value].currentContext!)); } }, ) ], ), ); WidgetsBinding.instance .addPostFrameCallback((_) => Scrollable.ensureVisible(_key[15].currentContext!)); return thisWidget; } }
4条答案
按热度按时间zpqajqem1#
最简单的方法是使用Scrollable.ensureVisible。
可见光法
滚动包含给定上下文的可滚动项,以使给定上下文可见。
请看下面的代码:
p1iqtdky2#
您可以定义
ScrollController
:将其传递给
SingleChildScrollView
:并以编程方式滚动它,如下所示:
或者,如果需要滚动动画:
如果您希望在布局构建完成后立即自动滚动,可以通过重写
initState
方法来实现:0s7z1bwu3#
您可以在SingleChildScrollView中添加ScrollController并滚动到您想要的特定位置
tktrz96b4#
这也可以在无状态小部件中完成,方法是在构建方法中触发它。使用
addPostFrameCallback
来确保在渲染完成后完成滚动。您需要为所选的value
添加回状态管理。但是您可以选择使用GetX、StatefulWidget或任何其他工具。