I have 4 tabs in a flutter tab bar. I am using a silver App bar and the tab bar is inside the bottom property of the silver app bar. I have 4 containers of different sizes inside SingleChilScrollView.
The functionality I want to achieve is when a user clicks on the first tab the screen scrolls to the first container and when a user clicks on the 4th tab the screen scrolls to the 4th container and again when a user clicks on the 1st tab the screen scroll back to the first container. I will be implementing this functionality for the flutter web version.
the code is below, but the screen doesn't scroll when user clicks the tabs.
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class ScrollContainerPage extends StatefulWidget {
@override
State<ScrollContainerPage> createState() => _ScrollContainerPageState();
}
class _ScrollContainerPageState extends State<ScrollContainerPage> {
ScrollController _scrollController = ScrollController();
List<GlobalKey> _globalKey = List.empty(growable: true);
late final secondContainerPosition;
late final thirdContainerPosition;
late final fourthContainerPosition;
bool initilized = false;
@override
void initState() {
for (int i = 0; i < 4; i++) {
_globalKey.add(GlobalKey());
}
super.initState();
}
getPosition() {
RenderBox box2 =
_globalKey[1].currentContext!.findRenderObject()! as RenderBox;
Offset position2 = box2.localToGlobal(Offset.zero);
if (!initilized) {
secondContainerPosition = position2.dy;
}
RenderBox box3 =
_globalKey[2].currentContext!.findRenderObject()! as RenderBox;
Offset position3 = box3.localToGlobal(Offset.zero);
if (!initilized) {
thirdContainerPosition = position3.dy;
}
RenderBox box4 =
_globalKey[3].currentContext!.findRenderObject()! as RenderBox;
Offset position4 = box4.localToGlobal(Offset.zero);
if (!initilized) {
fourthContainerPosition = position4.dy;
}
initilized = true;
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: DefaultTabController(
length: 4,
child: NestedScrollView(
floatHeaderSlivers: false,
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
return [
SliverAppBar(
leadingWidth: 200,
centerTitle: true,
//titleSpacing: 0,
//expandedHeight: 200.0,
backgroundColor: Colors.white,
leading: const Icon(Icons.arrow_back_ios,color: Colors.black,),
title: !kIsWeb? const Text("About us",
style: TextStyle(
color: Colors.black,
fontSize: 16.0,
),
):
SizedBox(
height: 40,
width: MediaQuery.of(context).size.width*0.5,
child: Center(
child: TextField(
cursorColor: const Color.fromRGBO(0, 79, 224, 1),
//maxLines: 5,
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(horizontal: 20),
prefixIcon: const Icon(Icons.search),
prefixIconColor: Colors.red,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
borderSide: const BorderSide(color: Color.fromRGBO(118, 118, 128, 1), width: 2),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
borderSide: const BorderSide(color: Color.fromRGBO(118, 118, 128, 1), width: 1.5),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
borderSide: const BorderSide(color: Color.fromRGBO(0, 79, 224, 1), width: 1.5),
),
),
),
),
),
actions: kIsWeb?[
Container(
margin: const EdgeInsets.fromLTRB(12,12,80,12),
padding: const EdgeInsets.symmetric(vertical: 5,horizontal: 30),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
border: Border.all(color: const Color.fromRGBO(4, 80, 225, 1)),
),
child: InkWell(
onTap: (){
},
child: Row(
children: const [
Icon(Icons.person_outline,
color: Color.fromRGBO(4, 80, 225, 1),
),
SizedBox(width: 10,),
Text('Sign in',
style: TextStyle(
color: Color.fromRGBO(4, 80, 225, 1),
fontSize: 14.0,
// fontWeight: FontWeight.w600,
),
),
],
),
),
),
]:null,
floating: !kIsWeb?true: false,
pinned: true,
snap: !kIsWeb?true: false,
bottom: TabBar(
indicatorColor: const Color.fromRGBO(0, 79, 224, 1),
tabs: [
Tab(icon: GestureDetector(
onTap: (){
setState(() {
getPosition();
_scrollController.animateTo(
_scrollController.position.minScrollExtent,
duration: const Duration(milliseconds: 500),
curve: Curves.ease);
});
},
child: const Text('scroll to red container', style: TextStyle(color: Colors.black),)),),
Tab(icon: GestureDetector(
onTap: (){
setState(() {
getPosition();
_scrollController.animateTo(secondContainerPosition,
// !kIsWeb ? 1140 : 1000,
duration: const Duration(milliseconds: 500),
curve: Curves.ease);
});
},
child: const Text('scroll to yellow container', style: TextStyle(color: Colors.black),)),),
Tab(icon: GestureDetector(
onTap: (){
setState(() {
getPosition();
_scrollController.animateTo(thirdContainerPosition,
// !kIsWeb ? 3380 : 2000,
duration: const Duration(milliseconds: 500),
curve: Curves.ease);
});
},
child: const Text('scroll to pink container', style: TextStyle(color: Colors.black),)),),
Tab(icon: GestureDetector(
onTap: (){
setState(() {
getPosition();
_scrollController.animateTo(fourthContainerPosition,
// _scrollController.position.maxScrollExtent,
duration: const Duration(milliseconds: 500),
curve: Curves.ease);
});
},
child: const Text('scroll to pink container', style: TextStyle(color: Colors.black),)),),
]
),
),
];
},
body:
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
key: _globalKey[0],
height: 1000,
color: Colors.red,
child: const Text('red container')
),
const SizedBox(
height: 30,
),
Container(
key: _globalKey[1],
height: 1700,
color: Colors.yellow,
child: Text('yellow Container')
),
const SizedBox(
height: 30,
),
Container(
key: _globalKey[2],
height: 3000,
color: Colors.pink,
child: Text('pink Container')
),
const SizedBox(
height: 30,
),
Container(
key: _globalKey[3],
height: 500,
color: Colors.orange,
child: Text('orangeContainer'),
),
const SizedBox(
height: 30,
),
],
),
),
),
),
);
}
}
You need to add your _scrollController
to your SingleChildScrollView
widget to make it work.
body : SingleChildScrollView(
controller: _scrollController, //just add this line
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
key: _globalKey[0],
height: 1000,
color: Colors.red,
child: const Text('red container')),
const SizedBox(
height: 30,
),
Container(
key: _globalKey[1],
height: 1700,
color: Colors.yellow,
child: Text('yellow Container')),
const SizedBox(
height: 30,
),
Container(
key: _globalKey[2],
height: 3000,
color: Colors.pink,
child: Text('pink Container')),
const SizedBox(
height: 30,
),
Container(
key: _globalKey[3],
height: 500,
color: Colors.orange,
child: Text('orangeContainer'),
),
const SizedBox(
height: 30,
),
],
),
),
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.