Change background color of ListTile upon selection in Flutter

101,573

Solution 1

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 2

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

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 4

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 5

Wrap ListTile in an Ink.

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

Related videos on Youtube

Robbert
Author by

Robbert

I like high-level languages.

Updated on January 04, 2022

Comments

  • Robbert
    Robbert over 2 years

    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,),
      );
    }
    
  • ThinkDigital
    ThinkDigital over 5 years
    Unfortunately, ListTileTheme doesn't have a backgroundColor property, just a selectedColor property. this.dense = false, this.style = ListTileStyle.list, this.selectedColor, this.iconColor, this.textColor, this.contentPadding, Edit: RIP Formatting
  • Herbert Poul
    Herbert Poul over 5 years
    @Augusto do you care about being more specific what is not working? It certainly does for me..
  • Augusto
    Augusto over 5 years
    I've copied and paste your code, and when I click on item the color not is showed...
  • Herbert Poul
    Herbert Poul over 5 years
    @Augusto what do you mean? the color should ALWAYS be visible. On tap only the ripple effect should be added. SO what exactly is your problem.
  • Augusto
    Augusto over 5 years
    If I was wrong I'll remove my comment. I want show ripple effect when user click on the option, I've copied it and not happens. I don't want put color, just effect.
  • Herbert Poul
    Herbert Poul over 5 years
    @Augusto the ListTile already includes a InkWell, which is the only thing you need for a ripple effect. So if you have no ripple effect in a ListTile with an onTap handler. you are doing something very strange. (The Ink widget from my class is only required if you want a background color, because when using e.g. Container with color the ripple effect would be drawn below that color, and hence not being visible). If you don't change your background color, and have a onTap in your ListTile or InkWell you should have a ripple effect.
  • Vijay Kumar Kanta
    Vijay Kumar Kanta about 5 years
    The color property of Container() will suffice too.
  • temirbek
    temirbek about 5 years
    ripple effect is lost
  • congle
    congle about 5 years
    I think this is the best solution because It not only change background color for ListTile, but also keep ripple effect when tap on the ListTile
  • Joan P.S
    Joan P.S almost 5 years
    Remember at least on of the ancestors need to be a Material widget, otherwise this will not work
  • Billy Mahmood
    Billy Mahmood over 4 years
    this is the marked correct answer, however, am still not sure how to change the background colour.
  • oyalhi
    oyalhi over 4 years
    There is no need to wrap it with Ink widget. As soon as you add onTap listener, the tile should show the ripple effect as expected.
  • Herbert Poul
    Herbert Poul over 4 years
    @oyalhi not if you have a decoratedbox or container with background color.
  • anonymous-dev
    anonymous-dev about 4 years
    I think this is actually a better answer since Ink communicates well that it will give the child widget a color.
  • Rustem Kakimov
    Rustem Kakimov about 4 years
    Also, Ink paints below the material splash effects, while Container paints above :)
  • anonymous-dev
    anonymous-dev about 4 years
    I did try this but I noticed that when using Ink and a scrollable listview the ink stays visible even when the element is out of the view area. I decided to go with a container instead because of that reason.
  • Tomek Polański
    Tomek Polański almost 4 years
    The downside of this is that you won't have any splash or hover effects. To fix it just wrap the tile with Theme and override focusColor
  • Awnage
    Awnage almost 4 years
    This should be the accepted answer if you are running the master branch. The stable and beta Flutter branches do not support this as of July 29, 2020.
  • sɐunıɔןɐqɐp
    sɐunıɔןɐqɐp over 3 years
    From Review: Can you also please provide the explanation along with this code? Links may get broken, and your answer may get difficult to understand in the future.
  • Richardd
    Richardd over 3 years
    How to select only one at the time and deselect the previous selected?
  • CopsOnRoad
    CopsOnRoad over 3 years
    @Richardd Create a variable int selectedIndex = -1, and then check if (index == selectedIndex) approach. If you didn't get that, please ask a separate questions, I'll answer it.
  • Richardd
    Richardd over 3 years
    I tried to implement your idea, but I think I did not understood it well. Can you have a look in this post stackoverflow.com/questions/64655361/… Thanks
  • CopsOnRoad
    CopsOnRoad over 3 years
    @Richardd I was about to write the answer now, but just saw someone else already did that and he used the same approach I mentioned :)
  • Zahra
    Zahra over 3 years
    This not a correct answer based on old questions requirements
  • Gyuri Majercsik
    Gyuri Majercsik about 3 years
    The only problem I encounter that the splash is removed using tileColor. Otherwise it is the best answer.