iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 13
1
Mobile Development

iOS Developer Learning Flutter系列 第 13

iOS Developer Learning Flutter. Lesson12 還是~列表(輸入與折疊)

  • 分享至 

  • xImage
  •  

Today Preview

1. 如果有用戶輸入的情況, 如何不讓資料跑掉?

原本我以為如果是用children方式建立的ListView
TextField上的資料不會跑掉
實驗之後發現還是會像這樣不見(只有在焦點上的欄位會保留)

所以我們還是來實作一下如何在scroll後資料還能顯示
核心重點還是要自己keep user input
流程如下:

  1. 監聽textField的onChanged
  2. 只要輸入的值改變就存起來(Flutter是給整個欄位的text, 不是這次輸入的text⚠️⚠️⚠️)
  3. 為textField新增TextEditingController
  4. 顯示的時候就透過controller把text塞回textField

上菜~

class LessonPageListViewTextField extends StatefulWidget {
  @override
  _LessonPageListViewTextFieldState createState() => _LessonPageListViewTextFieldState();
}

class _LessonPageListViewTextFieldState extends State<LessonPageListViewTextField> {

  final textFieldValues = List.generate(30, (index) => "");

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: textFieldValues.length,
      itemBuilder: (ctx, idx) => TextFieldTile("${(idx + 1) * 2}", textFieldValues[idx], (text) {
        setState(() {
          textFieldValues[idx] = text;
        });
      }),
    );
  }
}

class TextFieldTile extends StatelessWidget {

  String title = "";
  String value = "";
  void Function(String) changeCallBack;
  TextFieldTile(this.title, this.value, this.changeCallBack);

  TextEditingController get fieldController => TextEditingController(text: value);

  @override
  Widget build(BuildContext context) {

    return Container(
      child: Row(children: [
        Expanded(
          child: Container(
            padding: EdgeInsets.only(left: 8),
            child: Text(title),
          ),
        ),
        Container(
          padding: EdgeInsets.only(right: 8),
          width: 150,
          child: TextField(
            controller: fieldController,
            textAlign: TextAlign.right,
            onChanged: (text) {
              changeCallBack(text);
          }),
        )
      ])
    );
  }
}

2. 如何做出展開/收合的效果?

我以前還聽過這種效果有個有趣的名字
叫做手風琴XD
像以前如果我在iOS做
通常是透過header來處理開關並reloadData☘️☘️☘️
或是要炫一點就用套件XD

Flutter的話
人家已經有提供ExpansionTile了
介紹一下
很簡單
就跟ListTile差不多
多了幾個屬性

  1. children就是展開要看到哪些widget
  2. initiallyExpanded一開始是要關還是要開(預設為collapsed, false)
  3. trailing就是那個會轉的icon
  4. 也有提供onExpansionChanged

下一道菜~

class LessonPageListViewExpansion extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    Widget _getTile(Group group, double level) {

       final paddingText = Padding(
         padding: EdgeInsets.only(left: level * 16),
         child: Text(group.title),
       );

       if (group.subGroups.isEmpty) {
         print("${group.title} have no children");
         return ListTile(
           title: paddingText
         );
       } else {
         print("${group.title} have children");
         return ExpansionTile(
           key: PageStorageKey<Group>(group),
           title: paddingText,
           children: group.subGroups.map((element) => _getTile(element, level + 1)).toList(),
         );
       }
    }

    return ListView.builder(
      itemCount: groups.length,
      itemBuilder: (ctx, idx) {
        final group = groups[idx];
        return _getTile(group, 0);
    });
  }
}

3. 推薦:Flutter Catalog

這個專案是目前App Stroe上面
少數看到比較完整用Flutter做的示範用App
github上也有開源
大家可以去看看


下集預告:還是列表(多選與側滑)

最後提供一下github.com/mark33699/IDLF


上一篇
iOS Developer Learning Flutter. Lesson11 又是列表(置頂與刷新)
下一篇
iOS Developer Learning Flutter. Lesson13 裁判~可以讓人列完又列這樣的嗎? (多選與側滑)
系列文
iOS Developer Learning Flutter30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言