點燈坊

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

ListView 使用 Getter 動態 Filter

Sam Xiao's Avatar 2024-12-18

要實現 ListView 動態 filter,ListView 可直接綁 Getter,當 Keyword 改變時自動觸發 Getter

Version

Flutter 3.24.5

Flutter

filter01

  • Android 與 iOS 都成功使用 ListViewGetter 實現動態 Filter

ListView

import 'package:flutter/material.dart';

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

  
  State<Home> createState() => _Home();
}

class _Home extends State<Home> {
  final List<String> _allItems = [
    'Apple',
    'Banana',
    'Cherry',
    'Date',
    'Elderberry',
    'Fig',
    'Grapes'
  ];

  var _keyword = '';

  List<String> get _filteredItems => _allItems
      .where((item) => item.toLowerCase().contains(_keyword.toLowerCase()))
      .toList();

  
  Widget build(BuildContext context) {
    var appBar = AppBar(
      title: Text(
        'Filter List',
      ),
    );

    var textField = Padding(
      padding: const EdgeInsets.all(8.0),
      child: TextField(
        decoration: InputDecoration(
          hintText: 'Enter Keyword to Filter',
          border: OutlineInputBorder(
            borderRadius: BorderRadius.circular(8.0),
          ),
        ),
        onChanged: (value) => setState(() => _keyword = value),
      ),
    );

    var listView = Expanded(
      child: ListView.builder(
        itemCount: _filteredItems.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text(
              _filteredItems[index],
            ),
          );
        },
      ),
    );

    var body = Column(
      children: [
        textField,
        listView,
      ],
    );

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

Line 11

final List<String> _allItems = [
  'Apple',
  'Banana',
  'Cherry',
  'Date',
  'Elderberry',
  'Fig',
  'Grapes'
];
  • _allItemsListView 的原始資料,實務上會來自 API

Line 21

var _keyword = '';
  • _keyword:綁定 TextField 的 state

Line 23

List<String> get _filteredItems => _allItems
  .where((item) => item.toLowerCase().contains(_keyword.toLowerCase()))
  .toList();
  • get:綁定 ListViewGetter,雖然看起來像 function,但可視為 state 使用,當其內的 state 改變時,Getter 會自動更新,UI 也會自動 render

Line 48

var listView = Expanded(
  child: ListView.builder(
    itemCount: _filteredItems.length,
    itemBuilder: (context, index) {
      return ListTile(
        title: Text(
          _filteredItems[index],
        ),
      );
    },
  ),
);
  • ListView:顯示動態 filter 的資掉
  • itemCount:將 Getter 綁定到 ListView
  • itemBuilder():由 Getter 建立 ListTile

Line 35

var textField = Padding(
  padding: const EdgeInsets.all(8.0),
  child: TextField(
    decoration: InputDecoration(
      hintText: 'Enter Keyword to Filter',
      border: OutlineInputBorder(
        borderRadius: BorderRadius.circular(8.0),
      ),
    ),
    onChanged: (value) => setState(() => _keyword = value),
  ),
);
  • TextField:輸入 keyword 供 filter
  • onChanged():將 TextField 綁定到 _keyword state

Conclusion

  • Dart 的 Getter 可視為 Vue 的 Computed 使用,當 Getter 內的 state 改變時,Getter 會自動更新,UI 也會自動 render