Soojeong Lee

Jul 12, 2025

Soojeong Lee

Jul 12, 2025

Soojeong Lee

Jul 12, 2025

Let's create a detailed page.

Let's create a detailed page.

Now it's the detailed page's turn.

Getting the Detail Page Root

Now we need a detail page for the user to see. Since the app mainly moves from a list to a detail flow, we have added the memory_detail.dart page and route.

import 'package:go_router/go_router.dart';

import '/screens/memory_detail.dart';
import '/screens/screen2.dart';
import '/screens/screen3.dart';
import 'main_scaffold.dart';
import 'screens/memories.dart';

final goRouter = GoRouter(
  initialLocation: '/memories',
  routes: [
    ShellRoute(
      builder: (context, state, child) => MainScaffold(child: child),
      routes: [
        GoRoute(
          path: '/memories',
          pageBuilder: (context, state) =>
              const NoTransitionPage(child: MemoriesScreen()),
        ),
        GoRoute(
          path: '/screen2',
          pageBuilder: (context, state) =>
              const NoTransitionPage(child: Screen2()),
        ),
        GoRoute(
          path: '/screen3',
          pageBuilder: (context, state) =>
              const NoTransitionPage(child: Screen3()),
        ),
      ],
    ),
    GoRoute(
      path: '/memories/:id',
      builder: (context, state) {
        final id = state.pathParameters['id']!;
        return MemoryDetailScreen(id: id);
      },
    ),
  ],
);

The reason for creating a separate route with /memories/:id and not including it in the above Shell Route is that it is not part of the layout that belongs to MainScaffold.

By passing the id as a dynamic route, we can retrieve and display the corresponding details, thus we used pathParameter. This allows the screen to receive and utilize the relevant id information.

class MemoryDetailScreen extends StatelessWidget {
  final String id;

  const MemoryDetailScreen({super.key, required this.id});


Setting the Screen Layout

For now, I have set a layout that roughly displays the necessary information without applying any objects.

What I want to show is

  • A brief (obituary, memorial) information about the deceased

  • Photos/videos displayed in a gallery format

  • Text data in the form of notes also displayed as a preview in a gallery format

This is about what I have set.

import 'package:flutter/material.dart';

class MemoryDetailScreen extends StatelessWidget {
  final String id;

  const MemoryDetailScreen({super.key, required this.id});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Memories')),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Card(
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(12),
              ),
              elevation: 2,
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Row(
                  children: [
                    const CircleAvatar(
                      radius: 30,
                      backgroundColor: Colors.grey,
                      // backgroundImage: AssetImage('assets/profile.jpg'),
                    ),
                    const SizedBox(width: 16),
                    Expanded(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(
                            'Dad',
                            style: Theme.of(
                              context,
                            ).textTheme.titleLarge?.apply(fontWeightDelta: 2),
                          ),
                          SizedBox(height: 4),
                          Text(
                            'Date of Passing: 02/09/2025',
                            style: TextStyle(color: Colors.grey),
                          ),
                          Text(
                            'Memorial Site: Hambaeksan Memorial Park 9-5-182',
                            style: TextStyle(color: Colors.grey),
                          ),
                        ],
                      ),
                    ),
                    const Icon(Icons.arrow_forward_ios, size: 16),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),
            Text(
              'Photos / Videos',
              style: Theme.of(context).textTheme.titleMedium,
            ),
            const SizedBox(height: 12),
            GridView.builder(
              itemCount: 9,
              shrinkWrap: true,
              physics: const NeverScrollableScrollPhysics(),
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 3,
                crossAxisSpacing: 8,
                mainAxisSpacing: 8,
                childAspectRatio: 1,
              ),
              itemBuilder: (context, i) {
                return Container(
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(8),
                    color: Colors.grey[300],
                    // image: DecorationImage(
                    //   image: NetworkImage('https://example.com/image_$i.jpg'),
                    //   fit: BoxFit.cover,
                    // ),
                  ),
                );
              },
            ),
            Text('Texts', style: Theme.of(context).textTheme.titleMedium),
            const SizedBox(height: 12),
            GridView.builder(
              itemCount: 9,
              shrinkWrap: true,
              physics: const NeverScrollableScrollPhysics(),
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 3,
                crossAxisSpacing: 8,
                mainAxisSpacing: 8,
                childAspectRatio: 1,
              ),
              itemBuilder: (context, i) {
                return Container(
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(8),
                    color: Colors.grey[300],
                    // image: DecorationImage(
                    //   image: NetworkImage('https://example.com/image_$i.jpg'),
                    //   fit: BoxFit.cover,
                    // ),
                  ),
                );
              },
            ),
            const SizedBox(height: 80),
          ],
        ),
      ),
    );
  }
}

One thing I would like to share here is that, if possible, I recommend not setting the text size and boldness separately every time, but instead applying it from the Theme.of(context).textTheme class. This is for the sake of maintainability and design consistency.

Additionally, I have added a Floating Action Button to allow for new types of data to be added at any time.

 floatingActionButton: FloatingActionButton(
  child: const Icon(Icons.add),
  onPressed: () {},
),

This should bring the detail page to a certain degree.

Progress is visible little by little.

Comments

Comments

Comments