'How to Scroll multiple scroll of same Controller at once with sync to another one horizontal scroll?
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!,
);
}
}
Solution 1:[1]
I cannot understand your question clearly But you are using singlechildscrollview .Instead of it you can try interactive viewer
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | AKASH L |
