Flutter ListView search and click

469
import 'package:flutter/material.dart';
import 'dart:ui' as ui;

import 'package:stack_demo/models/FruitModel.dart';

class GlossarScreen extends StatefulWidget {
  @override
  _GlossarScreenState createState() => _GlossarScreenState();
}

class _GlossarScreenState extends State<GlossarScreen> {
  TextEditingController _textEditingController = TextEditingController();

  List<FruitModel> glossarListOnSearch = [];
  List<FruitModel> glossarList = [];

  @override
  void initState() {
    glossarList.add(FruitModel(id: 0, name: 'Apple', facts: 'Good for health'));
    glossarList.add(
        FruitModel(id: 1, name: 'Banana', facts: 'Banana is also for health'));
    glossarList.add(
        FruitModel(id: 2, name: 'Orange', facts: 'Orange good for health'));

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Glossar'),
        flexibleSpace: Container(
          decoration: BoxDecoration(
            gradient: LinearGradient(
                colors: [Color(0xffFBD23E), Color(0xffF6BE03)],
                begin: Alignment.topCenter,
                end: Alignment.bottomCenter),
          ),
        ),
        bottom: PreferredSize(
          preferredSize: Size(0, 60),
          child: Padding(
            padding: const EdgeInsets.fromLTRB(12, 0, 12, 10),
            child: Container(
              //height: 50,
              decoration: BoxDecoration(
                gradient: LinearGradient(
                    colors: [Colors.white60, Colors.white70],
                    begin: Alignment.topCenter,
                    end: Alignment.bottomCenter),
                borderRadius: BorderRadius.circular(50),
              ),
              child: Padding(
                padding: const EdgeInsets.fromLTRB(20, 0, 0, 0),
                child: TextField(
                  textAlign: TextAlign.left,
                  onChanged: (value) {
                    setState(() {
                      glossarListOnSearch = glossarList
                          .where((element) => element.name!
                              .toLowerCase()
                              .contains(value.toLowerCase()))
                          .toList();
                    });
                  },
                  controller: _textEditingController,
                  decoration: InputDecoration(
                      border: InputBorder.none,
                      errorBorder: InputBorder.none,
                      enabledBorder: InputBorder.none,
                      contentPadding: EdgeInsets.all(0),
                      hintText: 'Search'),
                ),
              ),
            ),
          ),
        ),
      ),
      body: Container(
        decoration: BoxDecoration(
          gradient: LinearGradient(
              colors: [Color(0xffFEFDFD), Color(0xffBDBDB2)],
              begin: Alignment.topLeft,
              end: Alignment.bottomRight),
        ),
        child: _textEditingController.text.isNotEmpty &&
                glossarListOnSearch.isEmpty
            ? Column(
                children: [
                  Align(
                    alignment: Alignment.center,
                    child: Padding(
                      padding: const EdgeInsets.fromLTRB(0, 50, 0, 0),
                      child: Text(
                        'No results',
                        style: TextStyle(
                            fontFamily: 'Avenir',
                            fontSize: 22,
                            color: Color(0xff848484)),
                      ),
                    ),
                  )
                ],
              )
            : ListView.builder(
                itemCount: _textEditingController.text.isNotEmpty
                    ? glossarListOnSearch.length
                    : glossarList.length,
                itemBuilder: (context, index) {
                  return GestureDetector(
                    onTap: () {
                      _textEditingController.text.isNotEmpty
                          ? _testFuction(context, glossarListOnSearch[index])
                          : _testFuction(context, glossarList[index]);
                    },
                    child: Padding(
                      padding: const EdgeInsets.fromLTRB(12, 15, 12, 15),
                      child: Text(
                        _textEditingController.text.isNotEmpty
                            ? glossarListOnSearch[index].name!
                            : glossarList[index].name!,
                        style: TextStyle(
                            color: Colors.black,
                            fontSize: 20,
                            fontFamily: 'Avenir'),
                      ),
                    ),
                  );
                },
              ),
      ),
    );
  }
}

void _testFuction(context, FruitModel model) {
  showModalBottomSheet(
    context: context,
    builder: (BuildContext bc) {
      return Scaffold(
        body: Text('${model.facts}'),
      );
    },
  );
}
Share:
469
Berkin
Author by

Berkin

Updated on January 01, 2023

Comments

  • Berkin
    Berkin over 1 year

    So I'm currently trying to implement some searching functionality to my ListView and this does work great actually. When I type in some letters it automatically shows me the right things (-> See Screenshot_Listview_1.png and Screenshot_Listview_2.png).

    There is only one problem. I want the different texts from my listview to be clickable, so when I click on them a new ModalBottomSheet should appear. For example: I'm searching for "Apple" and when I click on the text "Apple" a ModalBottomSheet opens and I can read some facts about apples. I tried the onTap method and it works so far but I only managed to open the same BottomSheet.. But I need different BottomSheets depending on what I have tapped on.

    This is what I got so far. Can you please help me out? I really don't know how to solve this problem. Thank you so much!!

    import 'package:flutter/material.dart';
    import 'dart:ui' as ui;
    
    
    class GlossarScreen extends StatefulWidget {
      @override
      _GlossarScreenState createState() => _GlossarScreenState();
    }
    
    class _GlossarScreenState extends State<GlossarScreen> {
      TextEditingController _textEditingController = TextEditingController();
    
      List<String> glossarListOnSearch = [];
      List<String> glossarList = [
        'Apple',
        'Orange',
        'Banana',
        'Grapefruit',
        'Mango',
        'Kiwi',
        'Grapes',
      ];
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Glossar'),
            flexibleSpace: Container(
              decoration: BoxDecoration(
                gradient: LinearGradient(
                    colors: [Color(0xffFBD23E), Color(0xffF6BE03)],
                    begin: Alignment.topCenter,
                    end: Alignment.bottomCenter),
              ),
            ),
            bottom: PreferredSize(
              preferredSize: Size(0, 60),
              child: Padding(
                padding: const EdgeInsets.fromLTRB(12, 0, 12, 10),
                child: Container(
                  //height: 50,
                  decoration: BoxDecoration(
                    gradient: LinearGradient(
                        colors: [Colors.white60, Colors.white70],
                        begin: Alignment.topCenter,
                        end: Alignment.bottomCenter),
                    borderRadius: BorderRadius.circular(50),
                  ),
                  child: Padding(
                    padding: const EdgeInsets.fromLTRB(20, 0, 0, 0),
                    child: TextField(
                      textAlign: TextAlign.left,
                      onChanged: (value) {
                        setState(() {
                          glossarListOnSearch = glossarList
                              .where((element) => element
                                  .toLowerCase()
                                  .contains(value.toLowerCase()))
                              .toList();
                        });
                      },
                      controller: _textEditingController,
                      decoration: InputDecoration(
                          border: InputBorder.none,
                          errorBorder: InputBorder.none,
                          enabledBorder: InputBorder.none,
                          contentPadding: EdgeInsets.all(0),
                          hintText: 'Search'),
                    ),
                  ),
                ),
              ),
            ),
          ),
          body: Container(
            decoration: BoxDecoration(
              gradient: LinearGradient(
                  colors: [Color(0xffFEFDFD), Color(0xffBDBDB2)],
                  begin: Alignment.topLeft,
                  end: Alignment.bottomRight),
            ),
            child: _textEditingController.text.isNotEmpty &&
                    glossarListOnSearch.isEmpty
                ? Column(
                    children: [
                      Align(
                        alignment: Alignment.center,
                        child: Padding(
                          padding: const EdgeInsets.fromLTRB(0, 50, 0, 0),
                          child: Text(
                            'No results',
                            style: TextStyle(
                                fontFamily: 'Avenir',
                                fontSize: 22,
                                color: Color(0xff848484)),
                          ),
                        ),
                      )
                    ],
                  )
                : ListView.builder(
                    itemCount: _textEditingController.text.isNotEmpty
                        ? glossarListOnSearch.length
                        : glossarList.length,
                    itemBuilder: (context, index) {
                      return GestureDetector(
                        onTap: () {
                          _testFuction(context);
                        },
                        child: Padding(
                          padding: const EdgeInsets.fromLTRB(12, 15, 12, 15),
                          child: Text(
                            _textEditingController.text.isNotEmpty
                                ? glossarListOnSearch[index]
                                : glossarList[index],
                            style: TextStyle(
                                color: Colors.black,
                                fontSize: 20,
                                fontFamily: 'Avenir'),
                          ),
                        ),
                      );
                    },
                  ),
          ),
        );
      }
    }
    
    void _testFuction(context) {
      showModalBottomSheet(
        context: context,
        builder: (BuildContext bc) {
          return Scaffold(
            body: Text('This text should be dependent on what I have tapped on. If I tap on "Apple" a different ModalBottomSheep shall appear then when I press on "Banana".'),
          );
        },
      );
    }
    

    Screenshot_ListView_1

    Screenshot_ListView_2

  • Berkin
    Berkin over 2 years
    Thank you very much but how do I go on? How can I make it possible to open a new page when I press on "Apple" or when I press on "Banana"? So how to differentiate?
  • Berkin
    Berkin over 2 years
    Thank you very much for your answer! But this doesn't work and I don't know why. This code is not working: fruitsList.add(FruitModel( id: 1, name: 'Banana', facts: 'Very good for bones and digestion')); Can you please tell me what to do or how to implement it to my code?
  • Afaq Ahmed
    Afaq Ahmed over 2 years
    1. Create a separate dart file for Fruit Model. 2. Create List in your desired class and import the FruitModel. 3. You have to use FruitModel everywhere for fruits. Can you show me the exact error or problem you're facing?
  • Berkin
    Berkin over 2 years
    So the problem is that fruitsList.add is underlined in red color. Also _testFuction(context,glossarListonSearch[index]); is underlined. Somehow Flutter doesn't know what this code is.
  • Afaq Ahmed
    Afaq Ahmed over 2 years
    Actually , you can check the error by hovering over the red line or by simply going to the Dart Analysis tab at bottom. You have to use the add functionality in init() method of your screen.
  • Berkin
    Berkin over 2 years
    It says: "The name 'fruitsList' is already defined. Try renaming one of the declarations." but I don't really understand what to do now. And I also don't really understand where to put your code inside of mine. I'm so sorry to bother you that much but I'm relatively new to flutter.
  • Afaq Ahmed
    Afaq Ahmed over 2 years
    I edited my response. Now you can easily understand. I used your code.
  • Berkin
    Berkin over 2 years
    Thank you so so much!! It worked!