so i have created a custom calender on top the dates will be in a horizontal scroll inside a list view builder and below some icons as per the number of the days in a month in anthor list view builder now the list view builder with icons is inside another list view builder which scroll vertically i have used linked scroll controller and if i scroll the top one with dates the whole screen list with horizonal scroll happens as expected But when i scroll any of the one row with icons only the date row is changing not the other rows with icon. so when i scroll row with icon only that one and the top horizontal scroll with the date is scrolling . what iam trying to achieve is to scroll al the icons horizontal scroll even when i scroll any one of it along with the rest
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:linked_scroll_controller/linked_scroll_controller.dart';
import 'package:stacked/stacked.dart';
class TeamViewTab extends StatefulWidget {
@override
_TeamViewTabState createState() => _TeamViewTabState();
}
class _TeamViewTabState extends State<TeamViewTab> {
@override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(
child: _TeamViewList(),
),
],
);
}
}
class _TeamViewList extends StatefulWidget {
@override
__TeamViewListState createState() => __TeamViewListState();
}
class __TeamViewListState extends State<_TeamViewList> {
DateTime now = DateTime.now();
DateTime? _monthAndYear;
DateTime? firstWeekDay;
TeamViewTabViewModel _viewModel = TeamViewTabViewModel();
LinkedScrollControllerGroup _mainScrollControllers =
LinkedScrollControllerGroup();
ScrollController _datesController = ScrollController();
ScrollController _iconsController = ScrollController();
int? _numberOfDays, selectedIndexList;
final List<int> _date = [];
final List<String> _weeks = [];
void _goToElement(double today) {
double jumpTo = _datesController.position.maxScrollExtent / _numberOfDays!;
_datesController.animateTo(jumpTo * (today + 3),
duration: const Duration(seconds: 1), curve: Curves.easeIn);
}
double today = 0.0;
@override
void initState() {
super.initState();
_mainScrollControllers = LinkedScrollControllerGroup();
_datesController = _mainScrollControllers.addAndGet();
_iconsController = _mainScrollControllers.addAndGet();
_monthAndYear = now;
today = now.day.toDouble();
_numberOfDays =
DateUtils.getDaysInMonth(_monthAndYear!.year, _monthAndYear!.month);
for (var i = 1; i <= _numberOfDays!; i++) {
_date.add(i);
firstWeekDay = DateTime(_monthAndYear!.year, _monthAndYear!.month, i);
String week = DateFormat("EEE").format(firstWeekDay!);
_weeks.add(week.substring(0, 1));
}
}
@override
void dispose() {
_datesController.dispose();
_iconsController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
double deviceWidth = MediaQuery.of(context).size.width;
return Column(
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 10),
color: containerBackgroundColorWhite,
height: 120,
width: deviceWidth,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
IconButton(
icon: const Icon(
NeOfficeIcons.chevron_left,
size: 12,
color: greyPrimaryTextColor,
),
onPressed: () async {
await _onChangeOfMonth(false);
},
),
Text(
DateFormat("MMMM yyyy").format(_monthAndYear!),
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: titleTextColor),
),
IconButton(
icon: const Icon(
NeOfficeIcons.chevron_right,
size: 12,
color: greyPrimaryTextColor,
),
onPressed: () async {
await _onChangeOfMonth(true);
},
),
],
),
IconButton(
onPressed: () {
_showLegend();
},
icon: Icon(Icons.info_outline_rounded,
color: infoIconColor, size: 21))
],
),
Padding(
padding: const EdgeInsets.only(left: 10.0),
child: Row(
children: [
SizedBox(
width: 55,
child: Center(
child: Text(
DateFormat("MMM").format(_monthAndYear!),
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: titleTextColor),
),
),
),
Expanded(
child: SizedBox(
height: 60,
child: ListView.builder(
controller: _datesController,
scrollDirection: Axis.horizontal,
itemCount: _numberOfDays,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
setState(() {
selectedIndexList = index;
});
},
child: Container(
width: 48,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(_weeks[index],
style: TextStyle(
color: selectedIndexList !=
null &&
selectedIndexList == index
? findMyFriendColor
: titleTextColor,
fontSize: 12,
fontWeight: FontWeight.bold)),
const SizedBox(height: 10),
Text('${_date[index]}',
style: TextStyle(
color: selectedIndexList !=
null &&
selectedIndexList == index
? findMyFriendColor
: titleTextColor,
fontSize: 12,
fontWeight: FontWeight.bold)),
],
),
),
);
}),
),
)
],
),
),
],
),
),
TeamViewListWidget(
numberOfDays: _numberOfDays!,
selectedIndexList: selectedIndexList,
iconsController: _iconsController,
viewModel: _viewModel,
jumpToCurrentDate: () {
_goToElement(today);
},
)
],
);
}
Future _onChangeOfMonth(bool direction) async {
if (direction) {
setState(() {
_monthAndYear = DateTime(
_monthAndYear!.year, _monthAndYear!.month + 1, _monthAndYear!.day);
_viewModel.getRequiredDataOnChangeOfMonth(
_monthAndYear!.month, _monthAndYear!.year, _monthAndYear!);
_numberOfDays =
DateUtils.getDaysInMonth(_monthAndYear!.year, _monthAndYear!.month);
_weeks.clear();
_date.clear();
if (_monthAndYear!.month == now.month) {
today = now.day.toDouble();
} else {
today = 0;
}
for (var i = 1; i <= _numberOfDays!; i++) {
_date.add(i);
firstWeekDay = DateTime(_monthAndYear!.year, _monthAndYear!.month, i);
String week = DateFormat("EEE").format(firstWeekDay!);
_weeks.add(week.substring(0, 1));
}
});
} else {
setState(() {
_monthAndYear = DateTime(
_monthAndYear!.year, _monthAndYear!.month - 1, _monthAndYear!.day);
_viewModel.getRequiredDataOnChangeOfMonth(
_monthAndYear!.month, _monthAndYear!.year, _monthAndYear!);
_numberOfDays =
DateUtils.getDaysInMonth(_monthAndYear!.year, _monthAndYear!.month);
_weeks.clear();
_date.clear();
if (_monthAndYear!.month == now.month) {
today = now.day.toDouble();
} else {
today = 0;
}
for (var i = 1; i <= _numberOfDays!; i++) {
_date.add(i);
firstWeekDay = DateTime(_monthAndYear!.year, _monthAndYear!.month, i);
String week = DateFormat("EEE").format(firstWeekDay!);
_weeks.add(week.substring(0, 1));
}
});
}
}
}
}
// ignore: must_be_immutable
class TeamViewListWidget extends StatefulWidget {
final int? numberOfDays;
int? selectedIndexList;
TeamViewTabViewModel? viewModel = TeamViewTabViewModel();
ScrollController? iconsController = ScrollController();
Function? jumpToCurrentDate;
TeamViewListWidget({
Key? key,
this.numberOfDays,
this.selectedIndexList,
this.viewModel,
this.iconsController,
this.jumpToCurrentDate,
}) : super(key: key);
@override
State<TeamViewListWidget> createState() => _TeamViewListWidgetState();
}
class _TeamViewListWidgetState extends State<TeamViewListWidget> {
@override
Widget build(BuildContext context) {
double deviceWidth = MediaQuery.of(context).size.width;
return ViewModelBuilder<TeamViewTabViewModel>.reactive(
onModelReady: (_viewModel) {
_viewModel.getRequiredDataOnModelReady();
},
builder: (context, model, child) {
if (widget.viewModel!.isBusy) {
return Expanded(
child: Center(
child: CircularProgressIndicator(
color: primaryColor,
),
),
);
}
if (!widget.viewModel!.isBusy) {
widget.jumpToCurrentDate!.call();
}
return widget.viewModel!.isTeamDetailsAvailable
? Expanded(
child: SizedBox(
width: deviceWidth,
child: ListView.builder(
controller: ScrollController(),
itemCount: widget.viewModel!.teamDetailsModel.length,
itemBuilder: (BuildContext context, int indexOfRow) {
return Container(
margin: const EdgeInsets.symmetric(vertical: 1),
height: 80,
color: indexOfRow % 2 == 0
? null
: containerBackgroundColorWhite,
child: Padding(
padding:
const EdgeInsets.only(left: 15.0, right: 10),
child: Row(
children: [
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: SizedBox(
width: 55,
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
widget
.viewModel!
.teamDetailsModel[
indexOfRow]
.profilePicUrl !=
'NA'
? ClipRRect(
child: Image.network(
widget
.viewModel!
.teamDetailsModel[
indexOfRow]
.profilePicUrl!,
loadingBuilder:
(context, widget, chunk) {
if (chunk == null)
return widget;
return Center(
child:
CircularProgressIndicator(
color: primaryColor,
),
);
},
errorBuilder: (context, obj,
stackTrace) {
return UserProfileIconWidget(
widget
.viewModel!
.teamDetailsModel[
indexOfRow]
.userName!
.substring(0, 2)
.toUpperCase(),
onTap: () async {},
);
},
height: 35,
width: 35,
),
borderRadius:
BorderRadius.circular(60),
)
: UserProfileIconWidget(
widget
.viewModel!
.teamDetailsModel[
indexOfRow]
.userName!
.substring(0, 2)
.toUpperCase(),
onTap: () async {},
),
Text(
widget
.viewModel!
.teamDetailsModel[
indexOfRow]
.userName!
.length <
7
? widget
.viewModel!
.teamDetailsModel[indexOfRow]
.userName!
: widget
.viewModel!
.teamDetailsModel[indexOfRow]
.userName!
.substring(0, 7),
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold),
),
],
),
),
),
Expanded(
child: SizedBox(
height: 60,
child: ListView.builder(
scrollDirection: Axis.horizontal,
// physics: NeverScrollableScrollPhysics(),
controller: widget.iconsController,
itemCount: widget.numberOfDays,
itemBuilder: (BuildContext context,
int indexOfIcon) {
return GestureDetector(
onTap: () {
setState(() {
widget.selectedIndexList =
indexOfIcon;
});
},
child: Container(
width: 48,
child: Icon(
widget.viewModel!
.monthlyDetailsOfTeam[
indexOfRow] !=
null
? widget.viewModel!.monthlyDetailsOfTeam[
indexOfRow]![
indexOfIcon] !=
null
? _iconHelper(widget
.viewModel!
.monthlyDetailsOfTeam[
indexOfRow]![
indexOfIcon]!
.workMode)
: Icons.no_data
: Icons.no_data,
size: 26,
color: widget.selectedIndexList !=
null &&
widget.selectedIndexList ==
indexOfIcon
? titleTextColor
: disabledIconColor),
),
);
},
),
),
),
],
),
),
);
}),
),
)
: Expanded(
child: Center(
child: SizedBox(),
),
);
},
viewModelBuilder: () => widget.viewModel!,
);
}
}
I cannot understand your question clearly But you are using singlechildscrollview .Instead of it you can try interactive viewer