點燈坊

失くすものさえない今が強くなるチャンスよ

GestureDetector 取代 ListTile 的 ListView

Sam Xiao's Avatar 2024-10-31

ListView 一般都會搭配 ListTile,但 ListTile 自帶 Padding,且無法清除,最有效的方式是使用沒有自帶 Padding 的 GestureDetector 取代 ListTile

Version

Flutter 3.24

Flutter

gesture01

  • Android 與 iOS 都成功使用 GestureDetector 實現 ListView

GestureDetector

import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({super.key});

  void showSnackBar(
    BuildContext context,
    String message,
  ) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(message),
      ),
    );
  }

  
  Widget build(BuildContext context) {
    var appBar = AppBar(
      title: const Text('ListView GestureDetector'),
    );

    var listView = ListView(
      padding: EdgeInsets.zero,
      children: [
        GestureDetector(
          onTap: () => showSnackBar(context, 'Item 1'),
          child: Container(
            color: Colors.white,
            padding: EdgeInsets.zero,
            child: const Text(
              'Item 1',
              textAlign: TextAlign.left,
            ),
          ),
        ),
        GestureDetector(
          onTap: () => showSnackBar(context, 'Item 2'),
          child: Container(
            color: Colors.white,
            padding: EdgeInsets.zero,
            child: const Text(
              'Item 2',
              textAlign: TextAlign.left,
            ),
          ),
        ),
        GestureDetector(
          onTap: () => showSnackBar(context, 'Item 3'),
          child: Container(
            color: Colors.white,
            padding: EdgeInsets.zero,
            child: const Text(
              'Item 3',
              textAlign: TextAlign.left,
            ),
          ),
        ),
      ],
    );

    return Scaffold(
      appBar: appBar,
      body: listView,
    );
  }
}

Line 23

var listView = ListView(
  padding: EdgeInsets.zero,
  children: [
    GestureDetector(
      onTap: () => showSnackBar(context, 'Item 1'),
      child: Container(
        color: Colors.transparent,
        padding: EdgeInsets.zero,
        child: const Text(
          'Item 1',
          textAlign: TextAlign.left,
        ),
      ),
    ),
  ],
)
  • ListView:外層一樣使用 ListView
    • padding:可在 ListView 直接設定 padding
    • GestureDetector:使用 GestureDetector 取代 ListTile
      • ContainerGestureDetector 並沒有提供 padding,須由 Container 設定
        • color:設定項目的背景色
        • padding:設定項目的 padding
          • Text:設定項目顯示文字

Conclusion

  • 使用 GestureDetector 的優點是 padding 可完全自主,不再受 ListTile 預設 padding 所限制,可更精確地呈現 prototype 的 layout