Currently, I have set a fixed height for the TabBarView
using a SizedBox
, but I want to remove this fixed height and make it dynamic. However, without the SizedBox
, TabBarView
collapses. How can I achieve a dynamic height for TabBarView
that adjusts based on the content of its child ListView.builder
widgets?
I have tried using shrinkWrap: true
for the ListView.builder
widgets, but it does not seem to affect the height of TabBarView
. Any suggestions or alternative approaches are appreciated. Thank you!
I need to remove this SizedBox and make the height of the TabBarViews dynamic in nature.
SizedBox(
height: 1000,
child: TabBarView(
controller: tabController,
// physics: const NeverScrollableScrollPhysics(),
children: [
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
// controller: scrollController,
itemCount: 6,
itemBuilder: (context, index) {
return CoursesTab(
index: index,
);
},
),
Whole Code Below
import ~~~
import 'package:provider/provider.dart' as p;
import 'package:flutter_riverpod/flutter_riverpod.dart';
class InstituteInfoScreen extends ConsumerStatefulWidget {
final String? id;
final String? source;
const InstituteInfoScreen({super.key, this.id, this.source});
@override
ConsumerState<InstituteInfoScreen> createState() => _InstituteInfoScreenState();
}
class _InstituteInfoScreenState extends ConsumerState<InstituteInfoScreen>
with SingleTickerProviderStateMixin {
late TabController tabController;
final ScrollController _scrollController1 = ScrollController();
@override
void initState() {
tabController = TabController(
initialIndex: 0,
length: 5,
vsync: this,
animationDuration: const Duration(milliseconds: 300),
);
// TODO: implement initState
// var pixels = _scrollController1.position.pixels;
// _bool = pixels > 373;
_scrollController1.addListener(() {
if (_scrollController1.position.pixels > 415 &&
!(ref.watch(InstituteInfoRiverpodProviders.toggleScrollUi))) {
ref.read(InstituteInfoRiverpodProviders.toggleScrollUi.notifier).update((state) => true);
}
if (_scrollController1.position.pixels < 415 &&
ref.watch(InstituteInfoRiverpodProviders.toggleScrollUi)) {
ref.read(InstituteInfoRiverpodProviders.toggleScrollUi.notifier).update((state) => false);
}
});
super.initState();
}
@override
Widget build(BuildContext context) {
final StudentProvider student = p.Provider.of<StudentProvider>(context, listen: false);
return SafeArea(
child: ref
.watch(
InstituteInfoRepo.getInstituteByIdFutureProvider(
GetInstituteParams(
instituteId: widget.id!,
latitude: student.latitude!,
longitude: student.longitude!,
),
),
)
.when(
data: (institute) {
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: const Color(0xfffff6ff),
foregroundColor: const Color(0xfffff6ff),
primary: false,
surfaceTintColor: const Color(0xfffff6ff),
// shadowColor: const Color(0xfffff6ff),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(24),
bottomRight: Radius.circular(24),
),
),
leading: IconButton(
icon: SvgPicture.asset(
'assets/images/new-ui/icons/back_button.svg',
color: const Color(0xFF201926),
),
onPressed: () {
Navigator.of(context).pop();
},
),
actions: [
IconButton(
onPressed: () {},
icon: SvgPicture.asset(
'assets/images/new-ui/icons/call.svg',
// color: Color(0xFF201926),
),
padding: const EdgeInsets.only(left: 5),
),
IconButton(
onPressed: () {},
icon: SvgPicture.asset(
'assets/images/new-ui/icons/message_circle.svg',
// color: Color(0xFF201926),
),
),
],
bottom: ref.watch(InstituteInfoRiverpodProviders.toggleScrollUi)
? PreferredSize(
preferredSize: const Size.fromHeight(130), // Adjust the height as needed
child: Container(
color: Colors.white,
padding: const EdgeInsets.only(
left: 24.0,
right: 24.0,
top: 16.0,
),
child: CustomBottomWidget(
tabController: tabController,
),
),
)
: null,
),
body: SingleChildScrollView(
physics: ScrollPhysics(),
controller: _scrollController1,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
/// Other Widgets
const SizedBox(height: 24),
ref.watch(InstituteInfoRiverpodProviders.toggleScrollUi)
? Container()
: Padding(
padding: const EdgeInsets.symmetric(horizontal: 18.0),
child: CustomBottomWidget(
tabController: tabController,
),
),
/// I need to remove this SizedBox* and make the height of the TabBarViews dynamic in nature.
SizedBox(
height: 1000,
child: TabBarView(
controller: tabController,
// physics: const NeverScrollableScrollPhysics(),
children: [
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
// controller: scrollController,
itemCount: 6,
itemBuilder: (context, index) {
return CoursesTab(
index: index,
);
},
),
Expanded(
child: AmenitiesTab(
amenities: [
Amenity(
name: 'Wi-Fi',
icon: 'wifi',
),
Amenity(
name: 'Parking',
icon: 'parking',
),
Amenity(
name: 'Swimming Pool',
icon: 'pool',
),
Amenity(
name: 'Gym',
icon: 'gym',
),
Amenity(
name: 'Spa',
icon: 'spa',
),
],
),
),
const AboutInstituteTab(),
ReviewsTab(
reviews: [
Review(
name: 'John Doe',
review:
'The course felt so personalized that I could follow it all along. The instructor knew exactly what he was doing and it was easy for me to grasp the basic concepts as well. Highly recommended!',
),
Review(
name: 'Jane Doe',
review:
'The course felt so personalized that I could follow it all along. The instructor knew exactly what he was doing and it was easy for me to grasp the basic concepts as well. Highly recommended!',
),
Review(
name: 'Alice Doe',
review:
'The course felt so personalized that I could follow it all along. The instructor knew exactly what he was doing and it was easy for me to grasp the basic concepts as well. Highly recommended!',
),
Review(
name: 'Alice Doe',
review:
'The course felt so personalized that I could follow it all along. The instructor knew exactly what he was doing and it was easy for me to grasp the basic concepts as well. Highly recommended!',
),
],
),
const GalleryTab(),
],
),
),
],
),
),
);
},
error: (error, stackTrace) {
return Scaffold(
body: Center(
child: Text(
error.toString(),
),
),
);
},
loading: () => Scaffold(
body: Center(
child: GifView.asset(
"assets/gif/loading.gif",
height: 50,
width: 50,
),
),
),
),
);
}
}
class CustomBottomWidget extends StatelessWidget {
final TabController tabController;
const CustomBottomWidget({
super.key,
required this.tabController,
});
@override
Widget build(BuildContext context) {
return Column(
children: [
Container(
height: 50,
padding: const EdgeInsets.only(
top: 8.0,
bottom: 8.0,
left: 13.55,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
border: Border.all(
color: const Color(0xff9F88B1),
width: 1.5,
),
color: const Color(0xffffffff),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('Search...'),
Row(
children: [
IconButton(
onPressed: () {},
icon: SvgPicture.asset(
'assets/images/new-ui/icons/search.svg',
color: const Color(0xff201926),
),
padding: const EdgeInsets.all(0),
),
SvgPicture.asset(
'assets/images/new-ui/icons/divider.svg',
color: const Color(0xff9F88B1),
),
IconButton(
onPressed: () {},
icon: SvgPicture.asset(
'assets/images/new-ui/icons/voice.svg',
color: const Color(0xff7D23E0),
),
padding: const EdgeInsets.all(0),
),
],
)
],
),
), // Search Widget
const SizedBox(height: 16),
TabBar(
tabs: const [
Tab(
text: 'Courses',
),
Tab(
text: 'Amenities',
),
Tab(
text: 'About Institute',
),
Tab(
text: 'Reviews',
),
Tab(
text: 'Gallery',
),
],
// indicatorPadding: const EdgeInsets.only(left: 0, right: 0),
tabAlignment: TabAlignment.start,
labelColor: const Color(0xff7D23E0),
unselectedLabelColor: const Color(0xff4C4452),
indicatorSize: TabBarIndicatorSize.tab,
isScrollable: true,
padding: const EdgeInsets.only(left: 0, right: 0),
// labelPadding: const EdgeInsets.only(left: 0, right: 0),
physics: const AlwaysScrollableScrollPhysics(),
unselectedLabelStyle: const TextStyle(
fontFamily: 'Avenir',
fontSize: 16,
fontWeight: FontWeight.w400,
height: 1.5,
),
labelStyle: const TextStyle(
fontFamily: 'Avenir',
fontSize: 16,
fontWeight: FontWeight.w600,
height: 1.5,
letterSpacing: 0.16,
),
controller: tabController,
),
],
);
}
}
2
Answers
I simply added this package AutoScaleTabbarView, replaced the TabBarView widget with this & it solved my problem.
Refer below code I have try simple example hope its help to you. Read more about TabBar