I have the following initial situation. A list with buttons in a horizontal order. When I select a button, data is loaded from Firestore with a Stream Builder and displayed below the button list (EventsSection). In EventsSection class I also load data from Firestore using the passed parameter OrgaId (selectedIndex). The problem I have right now is that when I select a button, the entire page is reloaded because of the setState method. The view goes back to the first button. However, I want the selected button to be focused and keep being displayed until another one is selected. What is the best way to solve this?
I tried to scroll to the selected position with a WidgetsBinding.instance.addPostFrameCallback()
Unfortunately, this does not work currently.
class MyPage extends StatefulWidget {
const MyPage({super.key});
@override
State<StatefulWidget> createState() => _MyPageState();
}
class _MyPageState extends State<MyPage> {
int selectedIndex = 1;
late ScrollController _scrollController;
@override
void initState() {
_scrollController = ScrollController();
super.initState();
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]);
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
void updateOrganizationIndex(String id) {
int newIndex = int.parse(id);
setState(() {
selectedIndex = newIndex;
});
WidgetsBinding.instance.addPostFrameCallback((_) {
if (_scrollController.hasClients) {
double offset = newIndex * 120.0;
_scrollController.jumpTo(offset);
}
});
}
@override
Widget build(BuildContext context) {
final Color primaryColor = Theme.of(context).primaryColor;
final Stream<QuerySnapshot> anizationStream = FirebaseFirestore.instance
.collection('anizations')
.where('category', isEqualTo: CategoryType.testcategory.stringValue)
.snapshots();
return SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
StreamBuilder(
stream: anizationStream,
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return SizedBox.shrink();
}
if (snapshot.connectionState == ConnectionState.waiting) {
return SizedBox.shrink();
}
if (snapshot.data!.docs.length == 1) {
selectedIndex = int.parse(snapshot.data!.docs[0].id);
return SizedBox.shrink();
}
return ListView.builder(
controller: _scrollController,
scrollDirection: Axis.horizontal,
padding: EdgeInsets.only(left: 10),
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot document = snapshot.data!.docs[index];
Map<String, dynamic> data =
document.data()! as Map<String, dynamic>;
return Row(
children: [
ElevatedButton(
onPressed: () => updateOrganizationIndex(document.id),
style: selectedIndex == int.parse(document.id)
? ElevatedButton.styleFrom(
backgroundColor: primaryColor,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(8),
),
),
)
: ElevatedButton.styleFrom(
backgroundColor: Colors.transparent,
elevation: 0,
shape: const RoundedRectangleBorder(
side: BorderSide(
color: Color.fromARGB(58, 58, 58, 1),
),
borderRadius: BorderRadius.all(
Radius.circular(8),
),
),
),
child: Text(
data['name'],
style: selectedIndex == int.parse(document.id)
? TextStyle(color: Colors.black)
: TextStyle(color: Colors.white),
),
),
SizedBox(width: 10),
],
);
},
);
}),
SizedBox(height: 20),
EventsSection(
aId: selectedIndex,
upcoming: true,
),
],
),
);
}
}