Home > Back-end >  Flutter ListView search and click
Flutter ListView search and click

Time:09-28

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

CodePudding user response:

You can wrap the your Padding with a GestureDetector and add actions into the onTap method.

return GestureDetector(
  onTap: () {
    // TODO: Add actions onTap
  },
  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: 24, fontFamily: 'Avenir'),
        ),
  );
);

CodePudding user response:

You need give your _testFuction some content what depends on you tap to let the bottomsheet know what it should to show.Just likes:

return GestureDetector(
  onTap:(){
    _testFuction(context,glossarListOnSearch[index]);
  }
  ...
) 

void _testFuction(context, someContent) {
  showModalBottomSheet(
    context: context,
    builder: (BuildContext bc) {
      return Scaffold(
        body: Text('This is $someContent bottomsheet'),
      );
    },
  );
}

CodePudding user response:

1. Create a Model class for FruitModel You can add as many parameters as you wanted like image URL , quantity , price , nutritional values etc.

class FruitModel {
  int? id;
  String? name;
  String? facts;

  FruitModel({this.id, this.name, this.facts});
}

2. Create List of Fruit and initialize it. Add as many items of fruits in the list as you wanted or you can get the data from Rest API.

List<FruitModel> fruitsList = [];

fruitsList.add(FruitModel(
    id: 1, name: 'Banana', facts: 'Very good for bones and digestion'));

3. Change your test function parameters like this.

      void testFuction(context, FruitModel model) {
    showModalBottomSheet(
      context: context,
      builder: (BuildContext bc) {
        return Scaffold(
          body: Text('${model.facts}'),
        );
      },
    );
  }

Now , you can call the test function as following. It'll pass the whole object for you to the next screen or bottom sheet. You can change it according to your needs :

_testFuction(context,glossarListonSearch[index]);
  • Related