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 the PrimaryScrollController
whenever the Tab
changes it's index.
So, when we listen that tab has changed to index 0, we will set that the first SingleChildScrolView
is the primary
one. When it changes to 1, we will set the other on as primary
.
First create a new State variable like this,
int currentIndex = 0; // This will be the index of tab at a point in time
To listen to the change event, you need to add Listener to the 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(),
],
),
);
},
),
);
Finally, depending on the currentIndex
set primary: true
to each SingleChildScrollView
.
For _buildWidgetA
,
Scrollbar(
isAlwaysShown: true,
showTrackOnHover: true,
child: SingleChildScrollView(
primary: currentIndex == 0, // <--- This will be primary if currentIndex = 0
child: Column(
children: children,
),
),
);
For _buildWidgetB
,
Scrollbar(
isAlwaysShown: true,
showTrackOnHover: true,
child: SingleChildScrollView(
primary: currentIndex == 1, // <--- This will be primary if currentIndex = 1
child: Column(
children: children,
),
),
);
Now, you should be able to control both of the tabs with your keyboard.
Full code here