Change background color of ListTile upon selection in Flutter

FlutterDartListviewFlutter LayoutBackground Color

Flutter Problem Overview


I've made a ListView in Flutter, but now I have some ListTiles in this ListView that can be selected. Upon selection, I want the background color to change to a color of my choice. I don't know how to do that. In the docs they mention that a ListTile has a property style. However, when I try to add that (as in third last line in the code below), this style property gets a squiggly red line underneath and the compiler tells me that The named parameter 'style' isn't defined.

Widget _buildRow(String string){
  return new ListTile(
    title: new Text(string),
    onTap: () => setState(() => toggleSelection(string)),
    selected: selectedFriends.contains(string),
    style: new ListTileTheme(selectedColor: Colors.white,),
  );
}

Flutter Solutions


Solution 1 - Flutter

I was able to change the background color of the ListTile using a BoxDecoration inside Container:

ListView (
    children: <Widget>[
        new Container (
            decoration: new BoxDecoration (
                color: Colors.red
            ),
            child: new ListTile (
                leading: const Icon(Icons.euro_symbol),
                title: Text('250,00')
            )
        )
    ]
)

Solution 2 - Flutter

Screenshot:

enter image description here


Short answer:
ListTile(
  tileColor: isSelected ? Colors.blue : null, 
)

Full Code:
// You can also use `Map` but for the sake of simplicity I'm using two separate `List`.
final List<int> _list = List.generate(20, (i) => i);
final List<bool> _selected = List.generate(20, (i) => false); // Fill it with false initially
  
Widget build(BuildContext context) {
  return Scaffold(
    body: ListView.builder(
      itemBuilder: (_, i) {
        return ListTile(
          tileColor: _selected[i] ? Colors.blue : null, // If current item is selected show blue color
          title: Text('Item ${_list[i]}'),
          onTap: () => setState(() => _selected[i] = !_selected[i]), // Reverse bool value
        );
      },
    ),
  );
}

Solution 3 - Flutter

If you also need an onTap listener with a ripple effect, you can use Ink:

ListView(
  children: [
    Ink(
      color: Colors.lightGreen,
      child: ListTile(
        title: Text('With lightGreen background'),
        onTap() { },
      ),
    ),
  ],
);

Ripple Effect

Solution 4 - Flutter

It's not ListTile that has the style property. But ListTileTheme. ListTileTheme is an inheritedWidget. And like others, it's used to pass down data (such as theme here).

To use it, you have to wrap any widget above your ListTile with a ListTileTheme containing the desired values.

ListTile will then theme itself depending on the closest ListTileTheme instance.

Solution 5 - Flutter

Wrap ListTile in an Ink.

Ink(
  color: isSelected ? Colors.blue : Colors.transparent,
  child: ListTile(title: Text('hello')),
)

Solution 6 - Flutter

This is no more pain!

Now you can use tileColor and selectedTileColor property of ListTile widget to achieve it.

Have a look at this Issue #61347 which got merged into master.

Solution 7 - Flutter

An easy way would be to store the initial index in a variable and then change the state of that variable whenever tapped.

   ListView.builder(
              shrinkWrap: true,
              itemCount: 4,
              itemBuilder: (context, index) {
                return Container( //I have used container for this example. [not mandatory]
                    color: tappedIndex == index ? Colors.blue : Colors.grey,
                    child: ListTile(
                        title: Center(
                      child: Text('${index + 1}'),
                    ),onTap:(){
                          setState((){
                            tappedIndex=index;
                          });
                        }));
              })

full code:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: MyWidget(),
    );
  }
}

class MyWidget extends StatefulWidget {
  @override
  MyWidgetState createState() => MyWidgetState();
}

class MyWidgetState extends State<MyWidget> {
  late int tappedIndex;

  @override
  void initState() {
    super.initState();
    tappedIndex = 0;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
          ListView.builder(
              shrinkWrap: true,
              itemCount: 4,
              itemBuilder: (context, index) {
                return Container(
                    color: tappedIndex == index ? Colors.blue : Colors.grey,
                    child: ListTile(
                        title: Center(
                      child: Text('${index + 1}'),
                    ),onTap:(){
                          setState((){
                            tappedIndex=index;
                          });
                        }));
              })
        ]));
  }
}

Dartpad link: https://dartpad.dev/250ff453b97cc79225e8a9c657dffc8a

Solution 8 - Flutter

I know that the original question has been answered, but I wanted to add how to set the color of ListTile while the tile is being pressed. The property you are looking for is called highlight color and it can be set by wrapping the ListTile in a Theme widget, like this:

Theme(
  data: ThemeData(
    highlightColor: Colors.red,
  ),
  child: ListTile(...),
  )
);

Note: if the Theme widget resets the font of text elements inside the ListTile, just set its fontFamily property to the same value You used in other places in your app.

Solution 9 - Flutter

Unfortunately, ListTile doesn't have background-color property. Hence, we have to simply wrap the ListTile widget into a Container/Card widget and then we can use its color property. Further, We have to provide SizedBox widget with some height to separate the same colored ListTiles.

I am sharing that worked for me :)

I hope it will definitely help you.

Screenshot: see how it works

            return 
              ListView(
                children: snapshot.data.documents.map((doc) {
                  return Column(children: [
                    Card(
                      color: Colors.grey[200],
                       child: ListTile(
                      leading: Icon(Icons.person),
                      title: Text(doc.data['coursename'], style: TextStyle(fontSize: 22),),
                      subtitle: Text('Price: ${doc.data['price']}'),
                      trailing: IconButton(
                        icon: Icon(Icons.delete),
                        onPressed: () async {
                          await Firestore.instance
                              .collection('courselist')
                              .document(doc.documentID)
                              .delete();
                        },
                      ),
                  ),
                    ),
                 SizedBox(height: 2,)
                  ],);
                }).toList(),[enter image description here][1]
              );

Solution 10 - Flutter

I have used as

ListTile(
                title: Text('Receipts'),
                leading: Icon(Icons.point_of_sale),
                tileColor: Colors.blue,
              ),  

Solution 11 - Flutter

There are two props: tileColor and selectedTileColor.

tileColor - when the tile/row is Not selected;

selectedTileColor - when the tile/row is selected

ListTile(
        selected: _isSelected,
        tileColor: Colors.blue,
        selectedTileColor: Colors.greenAccent,
)

Solution 12 - Flutter

I was able to change the Background Color of ListTile by making it a child of Container Widget and adding color to the Container Widget.

Here drawerItem is the model class which holds the isSelected value. Color of background depends on isSelected value.

Note: For unselected items keep the color Transparent so you will still get the ripple effect.

 for (var i = 0; i < drawerItems.length; i++) {
      var drawerItem = drawerItems[i];
      drawerOptions.add(new Container(
        color: drawerItem.isSelected
            ? Colors.orangeAccent
            : Colors.transparent,
        child: new ListTile(
          title: new Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[Text(drawerItem.title), drawerItem.count],
          ),
          leading: SvgPicture.asset(
            drawerItem.icon,
            width: 34,
            height: 34,
          ),
          onTap: () {
            _handleNavigation(i);
          },
          selected: drawerItem.isSelected,
        ),
      ));
    }

enter image description here

Solution 13 - Flutter

Your answer has been answered in Github.

Card(
  color: Colors.white,
  shape: ContinuousRectangleBorder(
    borderRadius: BorderRadius.zero,
  ),
  borderOnForeground: true,
  elevation: 0,
  margin: EdgeInsets.fromLTRB(0,0,0,0),
  child: ListTile(
    // ...
  ),
)

Solution 14 - Flutter

enter image description here>Make variable

        int slectedIndex;

>on tap

     onTap:(){
                      setState(() {
                      selectedIndex=index;
                     })

>Tile property

            color:selectedIndex==index?Colors.red :Colors.white,

>Same As in List View Builder

        ListView.builder(
                          itemCount: 10,
                          scrollDirection:Axis.vertical,
                          itemBuilder: (context,index)=>GestureDetector(
                            onTap:(){
                              setState(() {
                                selectedIndex=index;
                              });
                              
                            } ,
                            child: Container(
                              margin: EdgeInsets.all(8),
                              decoration: BoxDecoration(
                                borderRadius: BorderRadius.circular(5),
                                color:selectedIndex==index?Colors.red :Colors.white,
                              ),)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRobbertView Question on Stackoverflow
Solution 1 - FlutterBagataView Answer on Stackoverflow
Solution 2 - FlutterCopsOnRoadView Answer on Stackoverflow
Solution 3 - FlutterHerbert PoulView Answer on Stackoverflow
Solution 4 - FlutterRémi RousseletView Answer on Stackoverflow
Solution 5 - FlutterRustem KakimovView Answer on Stackoverflow
Solution 6 - FlutterBhavin DesaiView Answer on Stackoverflow
Solution 7 - FlutterritzView Answer on Stackoverflow
Solution 8 - FlutterAleksandarView Answer on Stackoverflow
Solution 9 - FlutterMilan KumarView Answer on Stackoverflow
Solution 10 - FlutterdhirajView Answer on Stackoverflow
Solution 11 - FluttervencedorView Answer on Stackoverflow
Solution 12 - FlutterSubir ChakrabortyView Answer on Stackoverflow
Solution 13 - FlutterNavid All GrayView Answer on Stackoverflow
Solution 14 - FlutterMuhammad NadeemView Answer on Stackoverflow