Sachin Rajput
Sachin Rajput

Reputation: 248

How to use Gesture control and change color on chip selection in Flutter

context :

I want to click on a particular services person/product and open a page where details can be shown more like a details page

Problem

I think that Gesture control should work but I'm not able to put it the right way in my code

How to change chip color on selection the data is getting filtered but i want to add 2 more things

  1. highlight the chip that is selected
  2. so a text message stating Not Available if there is nothing available, rather then leaving blank and

My Code

class _HomeScreenState extends State<HomeScreen> {
  int _selectedIndex = 0;
  int _selectedCategoryIndex = -1;
  String _selectedUserType = "Maid";
  PageController pageController = PageController();
  List array = ["Maid", "Driver", "Engineer", "Gardener", "Pilot","carpainter", "guard", "plumber"];

  List data = [
    {
      "name": "Sachin Rajput",
      "profilePic":
      "https://lh3.googleusercontent.com/a-/AAuE7mCfQn-gP_FJZUUU4GC4aSU1km9t_e5PL6zsV-NwdA=k-s48",
      "category": ["Maid", "Engineer"],
      "rating": 5,
      "bg": Colors.red
    },
    {
      "name": "Sachin Tendulkar",
      "profilePic":
      "https://lh3.googleusercontent.com/a-/AAuE7mCfQn-gP_FJZUUU4GC4aSU1km9t_e5PL6zsV-NwdA=k-s48",
      "category": ["Gardener", "Pilot", "Engineer"],
      "rating": 5,
      "bg": Colors.amberAccent
    },
    {
      "name": "Sachin Test",
      "profilePic":
      "https://lh3.googleusercontent.com/a-/AAuE7mCfQn-gP_FJZUUU4GC4aSU1km9t_e5PL6zsV-NwdA=k-s48",
      "category": ["carpainter", "guard", "plumber"],
      "rating": 5,
      "bg": Colors.blue
    }
  ];
  List product_data = [
    {
      "name": "P1",
      "profilePic":
      "https://lh3.googleusercontent.com/a-/AAuE7mCfQn-gP_FJZUUU4GC4aSU1km9t_e5PL6zsV-NwdA=k-s48",
      "category": ["Dusting"],
      "rating": 5,
      "bg": Colors.red
    },
    {
      "name": "P2",
      "profilePic":
      "https://lh3.googleusercontent.com/a-/AAuE7mCfQn-gP_FJZUUU4GC4aSU1km9t_e5PL6zsV-NwdA=k-s48",
      "category": ["Mopping"],
      "rating": 5,
      "bg": Colors.amberAccent
    },
    {
      "name": "P3",
      "profilePic":
      "https://lh3.googleusercontent.com/a-/AAuE7mCfQn-gP_FJZUUU4GC4aSU1km9t_e5PL6zsV-NwdA=k-s48",
      "category": ["cleaning"],
      "rating": 5,
      "bg": Colors.blue
    }
  ];
  List filteredData = [];

  void onTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
    pageController.jumpToPage(index);
  }

  void tappedCategory(int index) {
    _selectedCategoryIndex = index;
    _selectedUserType = array[index];
    _filterData();
  }

  @override
  void initState() {
    super.initState();
    _filterData();
  }

  _filterData() {
    print(_selectedUserType);
    filteredData =  data.where((element) => element["category"].contains(_selectedUserType)).toList();
    print(filteredData);
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: PageView(
                  controller: pageController,
                  children: [
                    SafeArea(
                      child: Column(
                          mainAxisAlignment: MainAxisAlignment.start,
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                        Padding(
                          padding:  EdgeInsets.symmetric(vertical: 5),
                          child: Container(
                            // color: Colors.purple,
                              // margin: const EdgeInsets.only(top: 45, bottom: 15),
                              padding: const EdgeInsets.only(left: 10, right: 10),
                              child: Row(
                                  children: [
                                    Expanded(
                                      child: Column(
                                        crossAxisAlignment: CrossAxisAlignment.start,
                                          children:  [
                                        Text("Bengaluru",
                                          style: TextStyle(
                                            color: APP_COLOR.mainColor,
                                          ),
                                        ),
                                        Text("R.T Nagar")
                                      ]),
                                    ),
                                    customContainer(iconData: Icons.search,),
                                    SizedBox(width: 10,),
                                    customContainer(iconData: Icons.notifications,),
                                  ])),
                        ),
                        Expanded(
                        child: SingleChildScrollView(
                          child: Column(
                            children: [

                              Padding(
                                padding:  EdgeInsets.symmetric(vertical: 10,horizontal: 10),
                                child: Align(
                                  alignment: Alignment.centerLeft,
                                  child:
                                  Text(
                                    'Popular Services',
                                  ),
                                ),
                              ),
                              Container(
                                height: MediaQuery.of(context).size.height / 12,
                                child: ListView(
                                  shrinkWrap: true,
                                  scrollDirection: Axis.horizontal,
                                  children: List<Widget>.generate(
                                      array.length, // place the length of the array here
                                      (int index) {
                                        return Container(
                                          margin: const EdgeInsets.all(2.0),
                                          child: GestureDetector(
                                            onTap: () {
                                              tappedCategory(index);
                                            },
                                            child: Chip(label: Text(array[index])),
                                          ),
                                        );
                                      }).toList(),
                                ),
                              ),
                              Container(
                                height: MediaQuery.of(context).size.height / 6,
                                child: ListView.builder(
                                  scrollDirection: Axis.horizontal,
                                  // physics: NeverScrollableScrollPhysics(),
                                  itemCount: filteredData.length,
                                  itemBuilder: (context, index) {
                                    var item = filteredData[index];
                                    return Padding(
                                      padding:  EdgeInsets.symmetric(horizontal: 10),
                                      child: Container(
                                        color: item['bg'],
                                        child: Center(
                                          child: Padding(
                                            padding:  EdgeInsets.symmetric(horizontal: 20),
                                            child: Text(item["name"].toString()),
                                          ),
                                        ),
                                      ),
                                    );
                                  },
                                  // This next line does the trick.
                                ),
                              ),
                              Padding(
                                padding:  EdgeInsets.symmetric(vertical: 10,horizontal: 10),
                                child: Row(
                                  mainAxisAlignment:MainAxisAlignment.spaceBetween,
                                  children: [
                                    Text(
                                      'Popular Products',
                                    ),
                                    Align(
                                      alignment: Alignment.centerRight,
                                      child:
                                      Text(
                                        'View All',
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                              Container(
                                height: MediaQuery.of(context).size.height / 6,
                                child: ListView.builder(
                                  scrollDirection: Axis.horizontal,
                                  itemCount: product_data.length,
                                  itemBuilder: (context, index) {
                                    var item = product_data[index];
                                    return Padding(
                                      padding:  EdgeInsets.symmetric(horizontal: 10),
                                      child: Container(
                                        color: item['bg'],
                                        child: Center(
                                          child: Padding(
                                            padding:  EdgeInsets.symmetric(horizontal: 60),
                                            child: Text(item["name"].toString()),
                                          ),
                                        ),
                                      ),
                                    );
                                  },
                                  // This next line does the trick.
                                ),
                              ),
                              Padding(
                                padding:  EdgeInsets.symmetric(vertical: 10,horizontal: 10),
                                child: Row(
                                  mainAxisAlignment:MainAxisAlignment.spaceBetween,
                                  children: [
                                    Text(
                                      'Our Products',
                                    ),
                                    Align(
                                      alignment: Alignment.centerRight,
                                      child:
                                      Text(
                                        'View All',
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                              Container(
                                height: MediaQuery.of(context).size.height / 6,
                                child: ListView.builder(
                                  scrollDirection: Axis.horizontal,
                                  itemCount: product_data.length,
                                  itemBuilder: (context, index) {
                                    var item = product_data[index];
                                    return Padding(
                                      padding:  EdgeInsets.symmetric(horizontal: 10),
                                      child: Container(
                                        color: item['bg'],
                                        child: Center(
                                          child: Padding(
                                            padding:  EdgeInsets.symmetric(horizontal: 60),
                                            child: Text(item["name"].toString()),
                                          ),
                                        ),
                                      ),
                                    );
                                  },
                                  // This next line does the trick.
                                ),
                              ),
                              Padding(
                                padding:  EdgeInsets.symmetric(vertical: 10,horizontal: 10),
                                child: Row(
                                  mainAxisAlignment:MainAxisAlignment.spaceBetween,
                                  children: [
                                    Text(
                                      'New Products',
                                    ),
                                    Align(
                                      alignment: Alignment.centerRight,
                                      child:
                                      Text(
                                        'View All',
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                              Container(
                                height: MediaQuery.of(context).size.height / 6,
                                child: ListView.builder(
                                  scrollDirection: Axis.horizontal,
                                  itemCount: product_data.length,
                                  itemBuilder: (context, index) {
                                    var item = product_data[index];
                                    return Padding(
                                      padding:  EdgeInsets.symmetric(horizontal: 10),
                                      child: Container(
                                        color: item['bg'],
                                        child: Center(
                                          child: Padding(
                                            padding:  EdgeInsets.symmetric(horizontal: 60),
                                            child: Text(item["name"].toString()),
                                          ),
                                        ),
                                      ),
                                    );
                                  },
                                ),
                              ),
                            ],
                          ),
                        ),
                      )
                      ]),
                    ),
                    Container(color: Colors.blue,),
                    Container(color: Colors.white,),
                    Container(color: Colors.yellow,),
                    Container(color: Colors.blue,),
                    Container(color: Colors.white,),
                    Container(color: Colors.yellow,)
                  ],
                ),
        bottomNavigationBar: BottomNavigationBar(
          items: const <BottomNavigationBarItem>[
            BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
            BottomNavigationBarItem(
                icon: Icon(Icons.cleaning_services), label: 'Services'),
            BottomNavigationBarItem(
                icon: Icon(Icons.local_convenience_store), label: 'Store'),
            BottomNavigationBarItem(
                icon: Icon(Icons.account_balance_wallet), label: 'Wallet'),
            BottomNavigationBarItem(
                icon: Icon(Icons.bookmarks), label: 'Bookmarked'),
            BottomNavigationBarItem(
                icon: Icon(Icons.assessment), label: 'Current Orders'),
            BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profile'),
          ],
          currentIndex: _selectedIndex,
          selectedItemColor: APP_COLOR.mainColor,
          unselectedItemColor: Colors.grey,
          onTap: onTapped,
        ));
  }

  Widget customContainer({required IconData iconData}){
    return Container(
      width: 45,
      height: 45,
      padding: const EdgeInsets.only(left: 0, right: 0),
      decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(15),
          color: APP_COLOR.mainColor,),
      child:  Icon(
        iconData,
        color: Colors.white,
      ),
    );
  }

}

I've recently started the flutter journey so i might have asked a very basic question so it will be great if you can explain the changes as well taht you made so i can understand it better

Upvotes: 1

Views: 248

Answers (3)

Prabhakaran
Prabhakaran

Reputation: 1544

Hope this helps

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

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  PageController pageController = PageController();
  int _selectedIndex = 0;

  void onTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
    pageController.jumpToPage(index);
  }
  
  @override
  void dispose() {
    pageController.dispose();
    super.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: PageView(
          controller: pageController,
          children: [
            const HomePage(),
            Container(
              color: Colors.blue,
            ),
            Container(
              color: Colors.white,
            ),
            Container(
              color: Colors.yellow,
            ),
            Container(
              color: Colors.blue,
            ),
            Container(
              color: Colors.white,
            ),
            Container(
              color: Colors.yellow,
            )
          ],
        ),
        bottomNavigationBar: BottomNavigationBar(
          items: const <BottomNavigationBarItem>[
            BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
            BottomNavigationBarItem(
                icon: Icon(Icons.cleaning_services), label: 'Services'),
            BottomNavigationBarItem(
                icon: Icon(Icons.local_convenience_store), label: 'Store'),
            BottomNavigationBarItem(
                icon: Icon(Icons.account_balance_wallet), label: 'Wallet'),
            BottomNavigationBarItem(
                icon: Icon(Icons.bookmarks), label: 'Bookmarked'),
            BottomNavigationBarItem(
                icon: Icon(Icons.assessment), label: 'Current Orders'),
            BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profile'),
          ],
          currentIndex: _selectedIndex,
          selectedItemColor: Colors.red,
          unselectedItemColor: Colors.grey,
          onTap: onTapped,
        ));
  }
}

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

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int _selectedCategoryIndex = 0;
  String _selectedUserType = "Maid";
  List array = [
    "Maid",
    "Driver",
    "Engineer",
    "Gardener",
    "Pilot",
    "carpainter",
    "guard",
    "plumber"
  ];

  List data = [
    {
      "name": "Sachin Rajput",
      "profilePic":
      "https://lh3.googleusercontent.com/a-/AAuE7mCfQn-gP_FJZUUU4GC4aSU1km9t_e5PL6zsV-NwdA=k-s48",
      "category": ["Maid", "Engineer"],
      "rating": 5,
      "bg": Colors.red
    },
    {
      "name": "Sachin Tendulkar",
      "profilePic":
      "https://lh3.googleusercontent.com/a-/AAuE7mCfQn-gP_FJZUUU4GC4aSU1km9t_e5PL6zsV-NwdA=k-s48",
      "category": ["Gardener", "Pilot", "Engineer"],
      "rating": 5,
      "bg": Colors.amberAccent
    },
    {
      "name": "Sachin Test",
      "profilePic":
      "https://lh3.googleusercontent.com/a-/AAuE7mCfQn-gP_FJZUUU4GC4aSU1km9t_e5PL6zsV-NwdA=k-s48",
      "category": ["carpainter", "guard", "plumber"],
      "rating": 5,
      "bg": Colors.blue
    }
  ];
  List product_data = [
    {
      "name": "P1",
      "profilePic":
      "https://lh3.googleusercontent.com/a-/AAuE7mCfQn-gP_FJZUUU4GC4aSU1km9t_e5PL6zsV-NwdA=k-s48",
      "category": ["Dusting"],
      "rating": 5,
      "bg": Colors.red
    },
    {
      "name": "P2",
      "profilePic":
      "https://lh3.googleusercontent.com/a-/AAuE7mCfQn-gP_FJZUUU4GC4aSU1km9t_e5PL6zsV-NwdA=k-s48",
      "category": ["Mopping"],
      "rating": 5,
      "bg": Colors.amberAccent
    },
    {
      "name": "P3",
      "profilePic":
      "https://lh3.googleusercontent.com/a-/AAuE7mCfQn-gP_FJZUUU4GC4aSU1km9t_e5PL6zsV-NwdA=k-s48",
      "category": ["cleaning"],
      "rating": 5,
      "bg": Colors.blue
    }
  ];
  List filteredData = [];

  void tappedCategory(int index) {
    _selectedCategoryIndex = index;
    _selectedUserType = array[index];
    _filterData();
  }

  @override
  void initState() {
    super.initState();
    _filterData();
  }
  
  @override
  void dispose() {
    super.dispose();
  }

  _filterData() {
    filteredData = data
        .where((element) => element["category"].contains(_selectedUserType))
        .toList();
    setState(() {});
  }

  Widget customContainer({required IconData iconData}) {
    return Container(
      width: 45,
      height: 45,
      padding: const EdgeInsets.only(left: 0, right: 0),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(15),
        color: Colors.red,
      ),
      child: Icon(
        iconData,
        color: Colors.white,
      ),
    );
  }

  Widget customProductsList({required String title, required List dataList}) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.start,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Padding(
          padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Text(title),
              const Align(
                alignment: Alignment.centerRight,
                child: Text(
                  'View All',
                ),
              ),
            ],
          ),
        ),
        SizedBox(
          height: MediaQuery.of(context).size.height / 6,
          child: dataList.isNotEmpty
              ? ListView.builder(
            scrollDirection: Axis.horizontal,
            itemCount: dataList.length,
            itemBuilder: (context, index) {
              var item = dataList[index];
              return Padding(
                padding: const EdgeInsets.symmetric(horizontal: 10),
                child: Container(
                  color: item['bg'],
                  child: Center(
                    child: Padding(
                      padding: const EdgeInsets.symmetric(horizontal: 60),
                      child: Text(item["name"].toString()),
                    ),
                  ),
                ),
              );
            },
            // This next line does the trick.
          )
              : const Center(
            child: Text('No data found.'),
          ),
        ),
      ],
    );
  }
  
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 5),
              child: Container(
                // color: Colors.purple,
                // margin: const EdgeInsets.only(top: 45, bottom: 15),
                  padding: const EdgeInsets.only(left: 10, right: 10),
                  child: Row(children: [
                    Expanded(
                      child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            const Text(
                              "Bengaluru",
                              style: TextStyle(
                                color: Colors.red,
                              ),
                            ),
                            const Text("R.T Nagar")
                          ]),
                    ),
                    customContainer(
                      iconData: Icons.search,
                    ),
                    const SizedBox(
                      width: 10,
                    ),
                    customContainer(
                      iconData: Icons.notifications,
                    ),
                  ])),
            ),
            Expanded(
              child: SingleChildScrollView(
                child: Column(
                  children: [
                    const Padding(
                      padding: EdgeInsets.symmetric(
                          vertical: 10, horizontal: 10),
                      child: Align(
                        alignment: Alignment.centerLeft,
                        child: Text(
                          'Popular Services',
                        ),
                      ),
                    ),
                    SizedBox(
                      height: MediaQuery.of(context).size.height / 12,
                      child: ListView(
                        shrinkWrap: true,
                        scrollDirection: Axis.horizontal,
                        children: List<Widget>.generate(
                            array
                                .length, // place the length of the array here
                                (int index) {
                              return Container(
                                margin: const EdgeInsets.all(2.0),
                                child: GestureDetector(
                                  onTap: () {
                                    tappedCategory(index);
                                  },
                                  child: Chip(
                                    label: Text(array[index]),
                                    backgroundColor:
                                    _selectedCategoryIndex == index
                                        ? Colors.green
                                        : Colors.grey,
                                  ),
                                ),
                              );
                            }).toList(),
                      ),
                    ),
                    SizedBox(
                      height: MediaQuery.of(context).size.height / 6,
                      child: filteredData.isNotEmpty
                          ? ListView.builder(
                        scrollDirection: Axis.horizontal,
                        // physics: NeverScrollableScrollPhysics(),
                        itemCount: filteredData.length,
                        itemBuilder: (context, index) {
                          var item = filteredData[index];
                          return Padding(
                            padding: const EdgeInsets.symmetric(
                                horizontal: 10),
                            child: GestureDetector(
                              onTap: () {
                                Navigator.of(context).push(
                                    MaterialPageRoute(
                                        builder: (context) =>
                                            DetailPage(
                                                user: item)));
                              },
                              child: Container(
                                color: item['bg'],
                                child: Center(
                                  child: Padding(
                                    padding: const EdgeInsets
                                        .symmetric(
                                        horizontal: 20),
                                    child: Text(
                                        item["name"].toString()),
                                  ),
                                ),
                              ),
                            ),
                          );
                        },
                        // This next line does the trick.
                      )
                          : const Center(
                        child: Text(
                            "No records available for the selected category"),
                      ),
                    ),
                    customProductsList(
                        title: 'Popular Products',
                        dataList: product_data),
                    customProductsList(
                        title: 'Our Products', dataList: product_data),
                    customProductsList(
                        title: 'New Products', dataList: product_data)
                  ],
                ),
              ),
            )
          ]),
    );
  }
}

class DetailPage extends StatelessWidget {
  const DetailPage({Key? key, this.user}) : super(key: key);
  final dynamic user;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(user["name"]),
        ),
        body: Container(
          padding: EdgeInsets.all(8),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            // mainAxisAlignment: MainAxisAlignment.center,
            children: [
              CircleAvatar(child: Image.network(user["profilePic"]), minRadius: 60,),
              SizedBox(height: 10,),
              Text("${user["name"]}"),
            ],
          ),
        )
    );
  }
}

Upvotes: 1

Ravin Laheri
Ravin Laheri

Reputation: 822

   Chip(
        label: "label",
        backgroundColor: _selectedCategoryIndex == index ? Colors.blue : Colors.green,
   ),

do not forgot to change tappedCategory function replace your function with this,

 void tappedCategory(int index) {
    _selectedCategoryIndex = index;
    _selectedUserType = array[index];
    _filterData();
    setState(() {});
  }

Upvotes: 1

Tuan
Tuan

Reputation: 2433

You can use: <true/false expressions> ? <if true> : <if false>

highlight the chip that is selected

Add an backgroundColor to Chip. index == _selectedCategoryIndex will check that chip is selected or not by index then set the color you want. In this case, that ex mean If the chip is selected chip, colored it!

- child: Chip(label: Text(array[index])),
+ child: Chip(
+   label: Text(array[index]),
+   backgroundColor: index == _selectedCategoryIndex ? APP_COLOR.mainColor : null),
+ )

so a text message stating Not Available if there is nothing available, rather then leaving blank and

Check filteredData have data then render what you want. In this case, ex mean If the filtered list is EMPTY, then render the Text insteads.

Detailer:

- Container(
-   height: MediaQuery.of(context).size.height / 6,
-   child: ListView.builder(...),
- ),
+ Container(
+   height: MediaQuery.of(context).size.height / 6,
+   child: filteredData.isNotEmpty
+     ? ListView.builder(...)
+     : Text('YOUR FILTERED LIST IS EMPTY'),
+ ),

Upvotes: 1

Related Questions