- I've created two tabs.
- In each tab I have SingleChildScrollView wrapped with Scrollbar.
- I can not have the primary scrollcontroller in both the tabs, because that throws me exception: "ScrollController attached to multiple scroll views."
- For Tab ONE I use primary scrollcontroller, for Tab TWO I created Scrollcontroller and attached it.
- For Tab ONE with primary scrollcontroller I can scroll both by keyboard and dragging scrollbar.
- But for Tab TWO with non primary scrollcontroller, I have to scroll only by dragging scrollbar. This tab doesn't respond to keyboard page up /down keys.
Please check my code below. Guide me on how to achieve keyboard scrolling for Tab TWO.
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),
child: Container(
height: 100,
width: double.infinity,
color: Colors.green,
),
),
);
}
return Scrollbar(
controller: _scrollController,
isAlwaysShown: true,
showTrackOnHover: true,
child: SingleChildScrollView(
controller: _scrollController,
child: Column(
children: children,
),
),
);
}
}
You don't need to create an explicit
ScrollController
to achieve this.One trick is to change which
SingleChildScrollView
is going to use thePrimaryScrollController
whenever theTab
changes it's index.So, when we listen that tab has changed to index 0, we will set that the first
SingleChildScrolView
is theprimary
one. When it changes to 1, we will set the other on asprimary
.First create a new State variable like this,
To listen to the change event, you need to add Listener to the
TabController
.Finally, depending on the
currentIndex
setprimary: true
to eachSingleChildScrollView
.For
_buildWidgetA
,For
_buildWidgetB
,Now, you should be able to control both of the tabs with your keyboard.
Full code here