Home > OS >  ListTile's SelectedTileColor is not working
ListTile's SelectedTileColor is not working

Time:03-01

I have a ListView that contains ListTiles that change color when selected. However, in the code below when there is an intermediate Container or SizedBox between the ListView and the Scaffold, SelectedTileColor does not work. I followed this issue and I wrapped my ListView with Ink and still does not work.

In the code below, if you remove the intermediate BottomPanel widget by replacing BottomPanel in line 20 with VehicleTypePanel then it will work. What is going wrong? why is BottomPanel preventing SelectedTileColor to take place?

https://dartpad.dev/?id=ddb60a7657ddb0cc30b4bdd0d86754cd


import 'package:flutter/material.dart';
import 'dart:math';

const Color darkBlue = Color.fromARGB(255, 18, 32, 47);

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(
        scaffoldBackgroundColor: darkBlue,
      ),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: BottomPanel(),
        ),
      ),
    );
  }
}

class BottomPanel extends StatelessWidget {
  BottomPanel({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final mediaQuery = MediaQuery.of(context);

    return SizedBox(
      child: DecoratedBox(
        decoration: BoxDecoration(
            color: Theme.of(context).scaffoldBackgroundColor,
            boxShadow: [
              BoxShadow(
                  color: Colors.black.withOpacity(0.1),
                  blurRadius: 10,
                  spreadRadius: 5)
            ]),
        child: AnimatedSwitcher(
            duration: const Duration(milliseconds: 300),
            child: VehicleTypePanel(),
            layoutBuilder: (currentChild, previousChildren) => Stack(
                  children: [
                    ...previousChildren,
                    if (currentChild != null) currentChild,
                  ],
                )),
      ),
      height: mediaQuery.size.height,
      width: mediaQuery.size.width,
    );
  }
}

List<Map<String, String>> vehicles = [
  {"type": "car", 'seats': '4', 'image': 'assets/car.jpeg'},
];

class VehicleTypePanel extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        const VehicleItem(
            type: "car",
            seats: "4",
            image: 'assets/car.jpeg',
            index: 0,
            selectedIndex: 0),
        const Divider(),
        const VehicleItem(
            type: "van",
            seats: "6",
            image: 'assets/van.jpeg',
            index: 1,
            selectedIndex: 0),
        const Divider(),
        //drop down textbutton with icon
        FractionallySizedBox(widthFactor: .8, child: PaymentMethod()),
        const SizedBox(height: 10),
        FractionallySizedBox(
          widthFactor: .8, // means 100%, you can change this to 0.8 (80%)
          child: ElevatedButton(
            style: ElevatedButton.styleFrom(
              fixedSize: const Size.fromHeight(50),
              elevation: 4,
              shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(50)),
            ),
            onPressed: () {},
            child: const Text('Select Vehicle'),
          ),
        ),
      ],
    );
  }
}

class PaymentMethod extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.start,
      children: [
        const Icon(Icons.person),
        const SizedBox(width: 10),
        Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            RichText(
              text: const TextSpan(
                children: [
                  TextSpan(
                    style: TextStyle(color: Colors.black),
                    text: "Payment Method",
                  ),
                  WidgetSpan(
                    alignment: PlaceholderAlignment.middle,
                    child: Icon(Icons.arrow_drop_down, size: 18),
                  ),
                ],
              ),
            ),
            const Text("Cash"),
          ],
        ),
      ],
    );
  }
}

class VehicleItem extends StatelessWidget {
  final String type;
  final String seats;
  final String image;
  final int index;
  final int selectedIndex;
  //final Function(GooglePlace, bool) onPlaceSelected;
  const VehicleItem(
      {Key? key,
      required this.type,
      required this.seats,
      required this.image,
      required this.index,
      required this.selectedIndex})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListTile(
      onTap: () {},
      selected: index == selectedIndex,
      selectedTileColor: Colors.amber,
      selectedColor: Colors.deepOrange,
      title: Text(type),
      subtitle: RichText(
        text: TextSpan(
          style: const TextStyle(color: Colors.deepOrange),
          children: [
            const WidgetSpan(
              alignment: PlaceholderAlignment.middle,
              child: Icon(Icons.person, size: 18),
            ),
            TextSpan(
              text: "$seats seats",
            ),
          ],
        ),
      ),
      trailing: const Text("10\$"),
    );
  }
}


CodePudding user response:

In the ListTile documentation,

The tileColor, selectedTileColor, focusColor, and hoverColor are not painted by the list tile itself but by the material widget ancestor. This generally has no effect. However, if an opaque widget, like Container(color: Colors.white), is included in between the ListTile and its Material ancestor, then the opaque widget will obscure the material widget and its background tileColor, etc. If this a problem, one can wrap a material widget around the list tile

So just replace VehicleTypePanel() with Material(type: MaterialType.transparency, child: VehicleTypePanel()).

  • Related