caduandrade / tabbed_view

Widget inspired by the classic Desktop-style tab component.
MIT License
49 stars 16 forks source link

ListView tile colors not displayed correctly #17

Closed raygray closed 1 year ago

raygray commented 1 year ago

When a ListView is used as tab content, list tile colors are not displayed correctly (in fact, not at all) - for example, no list tile gets ListTile.selectedTileColor when selected. On the other hand, the selection color somehow appears below the content border.

image

Demo code (replace your example/main.dart with this) displays a non-tabbed ListView on the left and a tabbed one on the right:

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

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

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

class TabbedViewExamplePage extends StatefulWidget {
  @override
  _TabbedViewExamplePageState createState() => _TabbedViewExamplePageState();
}

class _TabbedViewExamplePageState extends State<TabbedViewExamplePage> {
  late TabbedViewController _controller;

  @override
  void initState() {
    super.initState();
    List<TabData> tabs = [];

    tabs.add(TabData(
        text: 'Tab 1',
        content: listView));
    tabs.add(TabData(
        text: 'Tab 2',
        content: Padding(child: Text('Hello again'), padding: EdgeInsets.all(8))));

    _controller = TabbedViewController(tabs);
  }

  @override
  Widget build(BuildContext context) {
    TabbedView tabbedView = TabbedView(controller: _controller);
    Widget w = TabbedViewTheme(child: tabbedView, data: TabbedViewThemeData.mobile());
    return Scaffold(
        body: Row(
          children: [
            Expanded(child: listView),  // <== not tabbed
            Expanded(child: Container(child: w, padding: EdgeInsets.all(32))), // <== tabbed
          ],
        ));
  }

  Widget get listView {
    return ListView.builder(
      itemCount: 50,
      itemExtent: 100,
      itemBuilder: (context, index) {
        return ListTile(
          selected: index % 2 == 0,
          title: Text('$index'),
          tileColor: Colors.yellow,
          selectedTileColor: Colors.orange, // Selection color
        );
      },
    );
  }
}
caduandrade commented 1 year ago

Hi @raygray !

When you think you've seen everything in the world... :smile: I'll try to find out how this could be happening. The problem only occurs when using ListTile. I'll try to find out why this happens.

caduandrade commented 1 year ago

Hi @raygray!

I found the "problem" in https://api.flutter.dev/flutter/material/ListTile-class.html:

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

The widget for the tab content builds a Container, so that's exactly what happens according to the documentation.

You can build your ListView using the Material as the documentation suggests:

  Widget get listView {
    return Material(
        child: ListView.builder(
      itemCount: 50,
      itemExtent: 100,
      itemBuilder: (context, index) {
        return ListTile(
          selected: index % 2 == 0,
          title: Text('$index'),
          tileColor: Colors.yellow,
          selectedTileColor: Colors.orange, // Selection color
        );
      },
    ));
  }