I'm currently working on implementing a list-detail design in Flutter using the AutoRoute package. My objective is to create an adaptive layout where on larger screens, it displays as a dual-pane layout, while on smaller screens, it should transition to separate screens. Additionally, I need to highlight the list item corresponding to the currently selected detail item.
Resources:
However, I've encountered 3 major challenges:
- Tracking Active Inner Route: The list page, serving as a wrapper for the detail page, needs to identify the active inner route to highlight the currently selected item in the list.
- Route Configuration: If I include the details page as a child of the list, it functions correctly on larger screens. However, I'm unable to navigate to a new screen for the details without altering the
routesproperty of the router, since it would require the details page to exist as an entirely separate route, instead of a child of ListRoute. - Consistent Route on Device Configuration Changes: I need to ensure that the route remains consistent despite changes in device configuration. For instance, transitioning from a large screen with two panes to a smaller screen should adjust the detail screen to occupy the entire screen. In my current implementation it just "disappears" and shows up the list instead.
My router:
@AutoRouterConfig()
class AppRouter extends _$RepRouter {
AppRouter(this.ref);
@override
List<AutoRoute> get routes => [
AutoRoute(
initial: true,
page: ListRoute.page,
children: [
AutoRoute(
page: DetailRoute.page
),
],
),
];
}
ListPage code:
@RoutePage()
class ListPage extends HookWidget {
const ListPage({super.key});
@override
Widget build(BuildContext context) {
// This widget will render only primary widget on smaller screens and
// both primary and secondary on bigger screens
return AdaptiveDualPaneLayout(
maxPrimaryWidth: 372,
primary: list(context, null),
secondaryBuilder: (context) => AutoRouter(
placeholder: (context) => const Center(
child: Text("Select an item first"),
),
),
);
}
Widget list(BuildContext context, int? selectedItemId) {
final strings = Strings.of(context);
return CustomScrollView(
slivers: [
CustomSliverAppBar(
title: Text("List-detail Layout"),
),
SliverList.builder(
itemBuilder: (context, index) => CustomListTile(
elevation: index == selectedItemId ? 4 : 0,
title: Text('Item $index'),
subtitle: Text('Subtitle $index'),
onTap: selectedItemId == index ? null :
() => AutoRouter.of(context).navigate(DetailRoute(id: index));
),
),
],
);
}
}
TL;DR:
- How can I track the active inner route in the list page to highlight the selected item?
- How can I ensure that, when the screen size is big enough, the details appear as a secondary pane (as currently implemented) while still enabling navigation to a new page when the screen is small?
- How can I ensure that the route remains consistent when the device configuration changes, such as resizing the window? For instance, if the user has a large screen with two panes and item 1 displayed in the details page, resizing below the two-pane threshold should transition the detail screen to occupy the entire screen.