How to make items of list view in this app be added to history page upon being tapped?

33 Views Asked by At

I am trying to build a Flutter app where I have a list view builder in the home screen, but I also want to have a history page where users can see pages they have viewed. I can not make my history page work, so I have created a sample of my code and get feedback.

PS: I have no background in programming and doing this for enjoyment. This also will be my first project, so I do not know if making a history page requires a lot of coding or it is this simple I am making it out.

NOTE: in the code below the items in the list view sometimes disappear. To have them back just tap the X in the text field.

import 'package:flutter/material.dart';
import 'package:routemaster/routemaster.dart';

void main() => runApp(MyApp());

final routes = RouteMap(
  routes: {
    '/': (_) => CupertinoTabPage(
          child: HomePage(),
          paths: const ['/scientists', '/settings'],
        ),
    '/scientists': (_) =>
        const MaterialPage(child: ScientistsBiographyScreen()),
    // '/settings': (_) => MaterialPage(child: HistoryScreen()),
  },
);

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerDelegate: RoutemasterDelegate(routesBuilder: (_) => routes),
      routeInformationParser: const RoutemasterParser(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final tabState = CupertinoTabPage.of(context);

    return ScientistsBiographyScreen();
  }
}

class ScientistsBiographyScreen extends StatefulWidget {
  const ScientistsBiographyScreen({Key? key}) : super(key: key);

  @override
  State<ScientistsBiographyScreen> createState() =>
      _ScientistsBiographyScreenState();
}

class _ScientistsBiographyScreenState extends State<ScientistsBiographyScreen> {
  final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
  final List<String> allscientistsBiography = [
    "einstein",
    "tesla",
    "einstein",
    "tesla",
    "einstein",
    "tesla",
    "einstein",
    "tesla",
    "einstein",
    "tesla",
    "einstein",
    "tesla",
    "einstein",
    "tesla",
    "einstein",
    "tesla",
    "einstein",
    "tesla",
  ];

  List<String> filteredScientists = [];
  final TextEditingController _searchController = TextEditingController();
  final List<String> tappedScientists = [];

  void filterScientists(String query) {
    setState(() {
      filteredScientists = allscientistsBiography
          .where((scientist) =>
              scientist.toLowerCase().contains(query.toLowerCase()))
          .toList();
    });
  }

  void clearSearch() {
    _searchController.clear();
    filterScientists('');
  }

  void showHistoryScreen() {
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => HistoryScreen(tappedScientists)),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: const ScientistsAppbar(),
      key: scaffoldKey,
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Directionality(
            textDirection:
                TextDirection.ltr, // Set the text direction to right-to-left
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: SizedBox(
                height: 60,
                child: TextField(
                  controller: _searchController,
                  onChanged: filterScientists,
                  decoration: InputDecoration(
                    labelText: 'Search here',
                    prefixIcon: const Icon(Icons.search),
                    suffixIcon: IconButton(
                      icon: const Icon(Icons.clear),
                      onPressed: clearSearch,
                    ),
                    border: const OutlineInputBorder(),
                  ),
                ),
              ),
            ),
          ),
          Expanded(
            child: Directionality(
              textDirection:
                  TextDirection.ltr, // Set the text direction to right-to-left
              child: ScientistsBiography(
                scientists: filteredScientists,
                onTapScientist: (scientistsBiography) {
                  setState(() {
                    tappedScientists.add(scientistsBiography);
                  });
                  if (scientistsBiography == "einstein") {
                    Routemaster.of(context).push('/scientists-einstein');
                  }
                  if (scientistsBiography == "tesla") {
                    Routemaster.of(context).push('/scientists-tesla');
                  }
                },
              ),
            ),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: showHistoryScreen,
        child: const Icon(Icons.history),
      ),
    );
  }

  @override
  void dispose() {
    _searchController.dispose();
    super.dispose();
  }
}

class HistoryScreen extends StatelessWidget {
  final List<String> tappedScientists;
  const HistoryScreen(this.tappedScientists, {Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('History'),
      ),
      body: ListView.builder(
        itemCount: tappedScientists.length,
        itemBuilder: (BuildContext context, int index) {
          return ListTile(
            title: Text(tappedScientists[index]),
          );
        },
      ),
    );
  }
}

class ScientistsBiography extends StatelessWidget {
  final List<String> scientists;
  final Function(String) onTapScientist;

  const ScientistsBiography({
    Key? key,
    required this.scientists,
    required this.onTapScientist,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: scientists.length,
      itemBuilder: (BuildContext context, int index) {
        return ListTileScientists(
          scientistsBiography: scientists[index],
          onTap: () {
            onTapScientist(scientists[index]);
          },
        );
      },
    );
  }
}

class ListTileScientists extends StatelessWidget {
  final String scientistsBiography;
  final VoidCallback? onTap;

  const ListTileScientists({
    Key? key,
    required this.scientistsBiography,
    this.onTap,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: onTap,
      child: ListTile(
        key: key,
        title: Text(scientistsBiography),
        trailing: const Icon(Icons.arrow_forward),
      ),
    );
  }
}

class CardButton extends StatelessWidget {
  final String label;
  final VoidCallback? onPressed;

  const CardButton({
    Key? key,
    required this.label,
    this.onPressed,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 50,
      child: Card(
        child: InkWell(
          onTap: onPressed,
          child: Center(
            child: Text(
              label,
              style: const TextStyle(fontSize: 16),
            ),
          ),
        ),
      ),
    );
  }
}

class ScientistsAppbar extends StatelessWidget implements PreferredSizeWidget {
  const ScientistsAppbar({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return AppBar(
      // centerTitle: true,
      title: ShaderMask(
        shaderCallback: (Rect bounds) {
          return const LinearGradient(
            colors: [
              Color.fromARGB(255, 142, 154, 215),
              Color.fromARGB(255, 219, 84, 84)
            ], // Define your gradient colors here
            tileMode: TileMode.clamp,
          ).createShader(bounds);
        },
        child: const Text(
          'Scientists',
          style: TextStyle(
            fontSize: 24.0, // Adjust font size as needed
            fontWeight: FontWeight.bold, // Adjust font weight as needed
            color: Colors.white, // Text color (will be masked by the gradient)
          ),
        ),
      ),
      leading: IconButton(
        icon: const Icon(Icons.history),
        onPressed: () {
          Routemaster.of(context).pop();
        },
      ),
    );
  }

  @override
  Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}

class ScientistsAppbarStyle extends StatelessWidget {
  const ScientistsAppbarStyle({
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    return ShaderMask(
      shaderCallback: (Rect bounds) {
        return const LinearGradient(
          colors: [
            Color.fromARGB(255, 255, 255, 255),
            Color.fromARGB(255, 111, 84, 219)
          ], // Define your gradient colors here
          tileMode: TileMode.clamp,
        ).createShader(bounds);
      },
      child: const Text(
        'Scientists',
        style: TextStyle(
          fontSize: 24.0, // Adjust font size as needed
          fontWeight: FontWeight.bold, // Adjust font weight as needed
          color: Colors.white, // Text color (will be masked by the gradient)
        ),
      ),
    );
  }
}
1

There are 1 best solutions below

0
Jongphil Moon On

I ran your code but seems like the history page is working just fine when I pressed the floating button. If you were referring to the history button on the appbar (Next to page title "Scientist") then the solution for it would be as followed :

Send the tappedScientists to ScientistsAppbar class.

Widget build(BuildContext context) {
return Scaffold(
  appBar: ScientistsAppbar(tappedScientists: tappedScientists),
  key: scaffoldKey,
  body: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    crossAxisAlignment: CrossAxisAlignment.center,
    children: [
      Directionality(
        textDirection:

Then call the tappedScientists from the ScientistsAppbar class.

class ScientistsAppbar extends StatelessWidget implements 
 PreferredSizeWidget {
  final List<String> tappedScientists;
  const ScientistsAppbar({required this.tappedScientists, Key? key})
   : super(key: key);

In the same class provide a route to the history page for the onpressed

leading: IconButton(
    icon: const Icon(Icons.history),
    onPressed: () {
      Navigator.push(
        context,
        MaterialPageRoute(
            builder: (context) => HistoryScreen(tappedScientists)),
      );
    },
  ),