// Copyright 2014 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'package:flutter/material.dart'; /// Flutter code sample for [ListTile] selection in a [ListView] or [GridView]. void main() => runApp(const ListViewExampleApp()); class ListViewExampleApp extends StatelessWidget { const ListViewExampleApp({super.key}); @override Widget build(BuildContext context) { return const MaterialApp(home: ListTileSelectExample()); } } class ListTileSelectExample extends StatefulWidget { const ListTileSelectExample({super.key}); @override ListTileSelectExampleState createState() => ListTileSelectExampleState(); } class ListTileSelectExampleState extends State { bool isSelectionMode = false; final int listLength = 30; late List _selected; bool _selectAll = false; bool _isGridMode = false; @override void initState() { super.initState(); initializeSelection(); } void initializeSelection() { _selected = List.generate(listLength, (_) => false); } @override void dispose() { _selected.clear(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('ListTile selection'), leading: isSelectionMode ? IconButton( icon: const Icon(Icons.close), onPressed: () { setState(() { isSelectionMode = false; }); initializeSelection(); }, ) : const SizedBox(), actions: [ if (_isGridMode) IconButton( icon: const Icon(Icons.grid_on), onPressed: () { setState(() { _isGridMode = false; }); }, ) else IconButton( icon: const Icon(Icons.list), onPressed: () { setState(() { _isGridMode = true; }); }, ), if (isSelectionMode) TextButton( child: !_selectAll ? const Text( 'select all', style: TextStyle(color: Colors.white), ) : const Text( 'unselect all', style: TextStyle(color: Colors.white), ), onPressed: () { _selectAll = !_selectAll; setState(() { _selected = List.generate( listLength, (_) => _selectAll, ); }); }, ), ], ), body: _isGridMode ? GridBuilder( isSelectionMode: isSelectionMode, selectedList: _selected, onSelectionChange: (bool x) { setState(() { isSelectionMode = x; }); }, ) : ListBuilder( isSelectionMode: isSelectionMode, selectedList: _selected, onSelectionChange: (bool x) { setState(() { isSelectionMode = x; }); }, ), ); } } class GridBuilder extends StatefulWidget { const GridBuilder({ super.key, required this.selectedList, required this.isSelectionMode, required this.onSelectionChange, }); final bool isSelectionMode; final ValueChanged? onSelectionChange; final List selectedList; @override GridBuilderState createState() => GridBuilderState(); } class GridBuilderState extends State { void _toggle(int index) { if (widget.isSelectionMode) { setState(() { widget.selectedList[index] = !widget.selectedList[index]; }); } } @override Widget build(BuildContext context) { return GridView.builder( itemCount: widget.selectedList.length, gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, ), itemBuilder: (_, int index) { return InkWell( onTap: () => _toggle(index), onLongPress: () { if (!widget.isSelectionMode) { setState(() { widget.selectedList[index] = true; }); widget.onSelectionChange!(true); } }, child: GridTile( child: Container( child: widget.isSelectionMode ? Checkbox( onChanged: (bool? x) => _toggle(index), value: widget.selectedList[index], ) : const Icon(Icons.image), ), ), ); }, ); } } class ListBuilder extends StatefulWidget { const ListBuilder({ super.key, required this.selectedList, required this.isSelectionMode, required this.onSelectionChange, }); final bool isSelectionMode; final List selectedList; final ValueChanged? onSelectionChange; @override State createState() => _ListBuilderState(); } class _ListBuilderState extends State { void _toggle(int index) { if (widget.isSelectionMode) { setState(() { widget.selectedList[index] = !widget.selectedList[index]; }); } } @override Widget build(BuildContext context) { return ListView.builder( itemCount: widget.selectedList.length, itemBuilder: (_, int index) { return ListTile( onTap: () => _toggle(index), onLongPress: () { if (!widget.isSelectionMode) { setState(() { widget.selectedList[index] = true; }); widget.onSelectionChange!(true); } }, trailing: widget.isSelectionMode ? Checkbox( value: widget.selectedList[index], onChanged: (bool? x) => _toggle(index), ) : const SizedBox.shrink(), title: Text('item $index'), ); }, ); } }