如何解决Flutter web tabbarview scrollcontroller 不响应键盘滚动
- 我创建了两个标签。
- 在每个选项卡中,我都有用 Scrollbar 包裹的 SingleChildScrollView。
- 我不能在两个选项卡中都使用主滚动控制器,因为这会引发异常:“ScrollController 附加到多个滚动视图。”
- 对于标签一,我使用主滚动控制器,对于标签二,我创建了滚动控制器并附加了它。
- 对于带有主滚动控制器的 Tab ONE,我可以通过键盘和拖动滚动条进行滚动。
- 但是对于带有非主滚动控制器的 Tab TWO,我只能通过拖动滚动条来滚动。此选项卡不响应键盘向上/向下翻页键。
请在下面检查我的代码。指导我如何实现 Tab 2 的键盘滚动。
import 'package:Flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
home: TabExample(),);
}
}
class TabExample extends StatefulWidget {
const TabExample({Key key}) : super(key: key);
@override
_TabExampleState createState() => _TabExampleState();
}
class _TabExampleState extends State<TabExample> {
ScrollController _scrollController;
@override
void initState() {
_scrollController = ScrollController();
super.initState();
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,child: Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: [
Tab(icon: Text('Tab ONE')),Tab(icon: Text('Tab TWO')),],),title: Text('Tabs Demo'),body: TabBarView(
children: [
_buildWidgetA(),_buildWidgetB(),);
}
Widget _buildWidgetA() {
List<Widget> children = [];
for (int i = 0; i < 20; i++) {
children.add(
Padding(
padding: EdgeInsets.symmetric(vertical: 16),child: Container(
height: 100,width: double.infinity,color: Colors.black,);
}
return Scrollbar(
isAlwaysShown: true,showTrackOnHover: true,child: SingleChildScrollView(
child: Column(
children: children,);
}
Widget _buildWidgetB() {
List<Widget> children = [];
for (int i = 0; i < 20; i++) {
children.add(
Padding(
padding: EdgeInsets.symmetric(vertical: 16),color: Colors.green,);
}
return Scrollbar(
controller: _scrollController,isAlwaysShown: true,child: SingleChildScrollView(
controller: _scrollController,child: Column(
children: children,);
}
}
解决方法
您无需创建显式 ScrollController
即可实现此目的。
一个技巧是在 SingleChildScrollView
更改其索引时更改哪个 PrimaryScrollController
将使用 Tab
。
因此,当我们侦听该选项卡已更改为索引 0 时,我们将设置第一个 SingleChildScrolView
为 primary
。当它更改为 1 时,我们会将另一个设置为 primary
。
首先像这样创建一个新的状态变量,
int currentIndex = 0; // This will be the index of tab at a point in time
要监听更改事件,您需要将 Listener 添加到 TabController
。
DefaultTabController(
length: 2,child: Builder( // <---- Use a Builder Widget to get the context this this DefaultTabController
builder: (ctx) {
// Here we need to use ctx instead of context otherwise it will give null
final TabController tabController = DefaultTabController.of(ctx);
tabController.addListener(() {
if (!tabController.indexIsChanging) {
// When the tab has changed we are changing our currentIndex to the new index
setState(() => currentIndex = tabController.index);
}
});
return Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: [
Tab(icon: Text('Tab ONE')),Tab(icon: Text('Tab TWO')),],),title: Text('Tabs Demo'),body: TabBarView(
children: [
_buildWidgetA(),_buildWidgetB(),);
},);
最后,根据 currentIndex
将 primary: true
设置为每个 SingleChildScrollView
。
对于_buildWidgetA
,
Scrollbar(
isAlwaysShown: true,showTrackOnHover: true,child: SingleChildScrollView(
primary: currentIndex == 0,// <--- This will be primary if currentIndex = 0
child: Column(
children: children,);
对于_buildWidgetB
,
Scrollbar(
isAlwaysShown: true,child: SingleChildScrollView(
primary: currentIndex == 1,// <--- This will be primary if currentIndex = 1
child: Column(
children: children,);
现在,您应该可以使用键盘控制这两个选项卡了。
完整代码here
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。