I am trying to create the vertical list of items (Containers) of different height which could be scrolled to the fixed position with ScrollablePositionedList.builder
. To manage my list of items, I want to use buttons located in horizontal (also scrollable) menu, one button (for instance, "About object") for one specific widget (for instance, _aboutObject
). Now my code looks like that:
...
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
...
class _SaleOfficeState extends State<SaleOffice> {
final itemController = ItemScrollController(); // for body
final List<String> menuItems = ["Location", "About object"];
Future scrollToItem(int index) async {
itemController.scrollTo(
index: index,
alignment: 0,
duration: Duration(seconds: 1),
);
}
Widget _location() {Container(...)}
Widget _aboutObject() {Container(...)}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// AppBar definition
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
// Top menu container
height: 50,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: menuItems.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: TextButton(
onPressed: () {
print("top menu button is pressed");
scrollToItem(index);
},
child: Text(
menuItems[index],
),
),
);
},
),
),
Expanded(
child: ScrollablePositionedList.builder(
itemCount: menuItem.length,
itemScrollController: itemController,
itemBuilder: (BuildContext context, int index) {
if (index == 0) {
return _location();
} else if (index == 1) {
return _aboutObject();
}
return Container();
},
),
),
],
),
);
}
}
It scrolls correctly when I press the relevant button with needed duration, but immediately goes back to the starting position. I want it to be pinned on the upper position, until another button is presses.
Another strange behavior is: if I use non-existent index, for instance, 2:
await Scrollable.ensureVisible(context);
itemController.scrollTo(
index: 2,
alignment: 0,
duration: Duration(seconds: 1),
);
}
the code reacts and do the same as with index: index
. It seems I do not understand how this scrollable_positioned_list
works. Any advices are highly appreciated.
The task turned out to be more difficult than I thought. The fact is that my widgets, which should be scrolled in a vertical sheet, are of different heights. Therefore, I had to calculate their height dynamically:
// Calculate the height of the container dynamically based on its content
double _calculateContainerHeight(BuildContext context,
Widget Function() widget) {
final RenderBox? renderBox = context.findRenderObject() as RenderBox?;
return renderBox?.paintBounds.size.height ?? 0.0;
}
and then take this into account when adjusting the scrolling:
Expanded(
child: ScrollablePositionedList.builder(
itemCount: menuItems.length,
itemScrollController: itemController,
itemPositionsListener: itemListener,
itemBuilder: (BuildContext context, int index) {
switch (index) {
case 0:
return _location();
case 1:
return !_isFirstBuild ? _aboutObject() : SizedBox();
default:
return Container();
}
},
),
),
, with declaring a new variable bool _isFirstBuild = true;
. If somebody knows more elegant solution, please let me know. Also, something tells me this isn't the end yet as I want to increase the number of scrollable widgets. Perhaps something else will come out along the way.