Why ColorScheme from ThemeData doesn't work in ListView.builder/separated (Flutter)?

31 Views Asked by At

I'm using themes with light and dark color schemas in Flutter mobile app. It works fine in all Widgets except a ListWiev.separated. My code:

ListView.separated(
  itemCount: itemsList.length,
  separatorBuilder: (BuildContext context, int index) =>
      const SizedBox(
        height: 4.0,
      ),
  itemBuilder: (BuildContext context, int index) {
    return InkWell(
      onTap: () {
        Provider.of<PlayerManager>(context, listen: false)
            .play(index: index);
      },
      child: SizedBox(
        height: 48,
        child: Card(
          color: index.isEven
              ? Theme.of(context).colorScheme.surfaceVariant
              : null,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Padding(
                padding: const EdgeInsets.only(left: 6.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: [
                    Text(
                      itemsList[index]
                          .number
                          .toString()
                          .padLeft(3),
                      style: Theme.of(context)
                          .textTheme
                          .displaySmall!
                          .copyWith(
                              color: Theme.of(context)
                                  .colorScheme
                                  .onSurfaceVariant),
                    ),
                    const SizedBox(
                      width: 16,
                    ),
                    SizedBox(
                      width: 282,
                      child: Text(itemsList[index].name,
                          overflow: TextOverflow.ellipsis,
                          maxLines: 1,
                          style: Theme.of(context)
                              .textTheme
                              .displaySmall!
                              .copyWith(
                                  color: Theme.of(context)
                                      .colorScheme
                                      .onSurfaceVariant)),
                    ),
                    const SizedBox(
                      width: 8,
                    ),
                  ],
                ),
              ),
              Provider.of<PlayerManager>(context)
                              .buttonState ==
                          ButtonState.playing &&
                      Provider.of<PlayerManager>(context)
                              .currentItemIndex ==
                          index
                  ? Padding(
                      padding:
                          const EdgeInsets.only(right: 2.0),
                      child: MyAnimatedIcon(
                        icon: Icons.play_circle,
                        color: Theme.of(context)
                            .colorScheme
                            .primary,
                        backgroundColor: Theme.of(context)
                            .colorScheme
                            .primary
                            .withOpacity(0.7),
                        iconSize: 28,
                        animationMagnifier: 1.14,
                      ),
                    )
                  : Padding(
                      padding:
                          const EdgeInsets.only(right: 8.0),
                      child: Icon(
                        Icons.play_arrow,
                        size: 24,
                        color: Theme.of(context)
                            .colorScheme
                            .onSurfaceVariant,
                      ),
                    ),
            ],
          ),
        ),
      ),
    );
  }),

So, I tried with Provider:

Provider.of<ProfileManager>(context).darkMode ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.secondary

In fact, I needed something that returned the same color scheme regardless of whether dark mod was enabled, but both variants didn't work. Interestingly, the above code worked when I abandoned the color scheme and used specific colors e.g.:

Provider.of<ProfileManager>(context).darkMode ? Colors.yellow : Colors.blue

But this means giving up all the advantages of Color Scheme. I finally found the best solution: extract all the code from ItemBuilder into a separate widget:

ListView.separated(
  itemCount: itemsList.length,
  separatorBuilder: (BuildContext context, int index) =>
      const SizedBox(
        height: 4.0,
      ),
  itemBuilder: (BuildContext context, int index) {
    return ListItem(
      item: itemsList[index],
      index: index,
    );
  }),

And now, in my widget ItemsList, everything works as expected. I can use ColorScheme, e.g.:

color: Theme.of(context).colorScheme.onSurfaceVariant),

and a color changes when I change the theme from dark to light. But why does it work this way? Why doesn't ColorScheme work directly in ListView?

EDIT: I need to clarify what it means for me that it doesn't work. The ListView has good colors on the first rendering, and does not change after changing the theme.

0

There are 0 best solutions below