Skip to content

Instantly share code, notes, and snippets.

@PlugFox
Last active August 18, 2022 10:57
Show Gist options
  • Save PlugFox/1e011d3b3737d59697e09bc6e59f422f to your computer and use it in GitHub Desktop.
Save PlugFox/1e011d3b3737d59697e09bc6e59f422f to your computer and use it in GitHub Desktop.
Filter example pass controller through constructor
/*
* Filter example pass controller through constructor
* https://gist.github.com/PlugFox/1e011d3b3737d59697e09bc6e59f422f
* https://dartpad.dev/1e011d3b3737d59697e09bc6e59f422f
* Matiunin Mikhail <plugfox@gmail.com>, 19 May 2022
*/
import 'dart:async';
import 'dart:math' as math;
import 'package:flutter/material.dart';
void main() => runZonedGuarded<Future<void>>(() async {
runApp(const App());
}, (error, stackTrace) {
print('Error: $error, stackTrace: $stackTrace');
});
/// {@template app}
/// App widget
/// {@endtemplate}
class App extends StatelessWidget {
/// {@macro app}
const App({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) => const MaterialApp(
title: 'Filter example',
debugShowCheckedModeBanner: false,
home: HomeScreen(),
);
} // App
// --- Home screen with filter --- //
/// {@template main}
/// HomeScreen widget
/// {@endtemplate}
class HomeScreen extends StatefulWidget {
/// {@macro main}
const HomeScreen({
Key? key,
}) : super(key: key);
@override
State<HomeScreen> createState() => _HomeScreenState();
} // HomeScreen
/// State for widget HomeScreen
class _HomeScreenState extends State<HomeScreen> {
static final math.Random _rnd = math.Random();
static const int _kMax = 100;
final List<int> _sourceList =
Iterable<int>.generate(_kMax, (_) => _rnd.nextInt(_kMax))
.toList(growable: false);
final ValueNotifier<Filter> _filterController =
ValueNotifier<Filter>(const Filter());
@override
void dispose() {
_filterController.dispose();
super.dispose();
}
/// Open filter dialog
Future<void> _openFilter(BuildContext context) => showDialog<Filter?>(
context: context,
builder: (context) => FilterDialog(controller: _filterController),
);
bool _applyFilter(int data, Filter filter) {
if (data.isEven && filter.even) {
return true;
} else if (data.isOdd && filter.odd) {
return true;
}
return false;
}
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Home Screen'),
actions: <Widget>[
// Filter button:
CircleAvatar(
radius: 20,
child: IconButton(
onPressed: () => _openFilter(context),
icon: const Icon(Icons.filter_list),
),
),
const SizedBox(width: 14),
],
),
// Body content:
body: SafeArea(
child: ValueListenableBuilder<Filter>(
valueListenable: _filterController,
builder: (context, filter, _) {
final list = _sourceList
.where((element) => _applyFilter(element, filter))
.toList(growable: false);
return ListView.builder(
itemCount: list.length,
itemBuilder: (context, index) => ListTile(
title: Text(
list[index].toString(),
),
subtitle: Text(
list[index].isEven ? 'even' : 'odd',
),
),
);
},
),
),
);
} // _HomeScreenState
/// Filter result
@immutable
class Filter {
/// Filter result
const Filter({
this.even = true,
this.odd = true,
});
/// Show even numbers
final bool even;
/// Show odd numbers
final bool odd;
}
/// {@template filter_dialog}
/// FilterDialog widget
/// {@endtemplate}
class FilterDialog extends StatefulWidget {
/// {@macro filter_dialog}
const FilterDialog({
required this.controller,
Key? key,
}) : super(key: key);
final ValueNotifier<Filter> controller;
@override
State<FilterDialog> createState() => _FilterDialogState();
} // FilterDialog
/// State for widget FilterDialog
class _FilterDialogState extends State<FilterDialog> {
bool _even = true;
bool _odd = true;
@override
void initState() {
super.initState();
_even = widget.controller.value.even;
_odd = widget.controller.value.odd;
}
void _cancel(BuildContext context) => Navigator.pop(context, null);
void _accept(BuildContext context) {
widget.controller.value = Filter(even: _even, odd: _odd);
Navigator.pop(context, null);
}
@override
Widget build(BuildContext context) => SimpleDialog(
title: const Text('Filter dialog'),
children: <Widget>[
StatefulBuilder(
builder: (context, setState) => CheckboxListTile(
title: const Text('Even'),
value: _even,
onChanged: (value) => setState(
() => _even = value ?? false,
),
),
),
StatefulBuilder(
builder: (context, setState) => CheckboxListTile(
title: const Text('Odd'),
value: _odd,
onChanged: (value) => setState(
() => _odd = value ?? false,
),
),
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
OutlinedButton(
onPressed: () => _cancel(context),
child: const Text('Cancel'),
),
ElevatedButton(
onPressed: () => _accept(context),
child: const Text('Accept'),
),
],
)
],
);
} // _FilterDialogState
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment