【问题标题】:Flutter Visibility Toggle not working as expectedFlutter Visibility Toggle 未按预期工作
【发布时间】:2021-02-06 17:57:22
【问题描述】:

创建一个我想要执行 Flutter-FireBase 搜索的屏幕。但可见性切换无法按预期工作。
所需的切换行为:单击 TextForm 字段时,前缀图标和结果卡应该是可见的。单击前缀图标(后退箭头)时,结果列表(卡片)和前缀图标本身应该变得不可见并且 TextField 应该不聚焦。
实际行为:单击前缀图标时,结果集和前缀图标不要消失,前缀图标保留在那里,结果集变得不可见,但在 TextFormField 下方占据了一些空间

class AddAppointmentWidget extends StatefulWidget {
  @override
  _AddAppointmentWidgetState createState() => _AddAppointmentWidgetState();
}

class _AddAppointmentWidgetState extends State<AddAppointmentWidget> {
  bool searchbartapped = false;
  var queryResultSet = [];
  var tempSearchStore = [];

// Search Function
  initiateSearch(value) {
    //body
  }

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: [
        SizedBox(
          height: 15,
        ),
        Padding(
          padding: const EdgeInsets.all(18.0),
          child: Text('Search',
              style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold)),
        ),
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: Row(
            children: [
              Expanded(
                flex: 5,
                child: TextFormField(
                    style: TextStyle(color: Color(0xff2a2a2a), fontSize: 18),
                    keyboardType: TextInputType.name,
                    onChanged: (value) {
                      initiateSearch(value);
                    },
                    onTap: () {
                      setState(() {
                        searchbartapped = true;
                      });
                    },
                    cursorColor: Color(0xff2a2a2a),
                    cursorWidth: 1.5,
                    decoration: InputDecoration(
                        hintText: "Search by Name",
                        prefixIcon: Visibility(
                          visible: searchbartapped,
                          child: IconButton(
                              icon: Icon(Icons.arrow_back),
                              color: Colors.black54,
                              onPressed: () {
                                setState(() {
                                  searchbartapped = !searchbartapped;
                                  queryResultSet = [];
                                  tempSearchStore = [];
                                });
                                FocusScope.of(context).unfocus();
                              }),
                        ),
                        )),
              ),
            ],
          ),
        ),
        Visibility(
          visible: searchbartapped,
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: ListView(
                padding: EdgeInsets.all(5.0),
                primary: false,
                shrinkWrap: true,
                children: tempSearchStore.map((element) {
                  print(element['name']);
                  return buildResult(context, element);
                }).toList()),
          ),
        ),
      ],
    );
  }
}

注意 buildResult 小部件工作正常。 问题仅在于可见性切换

【问题讨论】:

    标签: flutter dart flutter-layout visibility


    【解决方案1】:

    问题:点击prefixIcon时:

    1. onPressed 被调用,将 searchbartapped 设置为 false 这就是你想要的。
    2. TextFormFieldonTap 方法也被调用(因为prefixIcon 在其中),将searchbartapped 设置为true

    所以你想要的是防止第二个事件发生。我试图阻止通知在树上冒泡,但我做不到。所以我最终做的是更多的手动操作,但效果也很好。

    解决方案: 添加一个变量(例如hideSearchTapped),在调用prefixIcon 时设置为true。然后当你的TextFormFieldonTap 方法被调用时,检查这个变量:

    • 如果hideSearchTapped为真,则设置为假
    • 像你一样更改searchbartapped

    这是一个工作示例:

    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    
    void main() async {
      runApp(
        MaterialApp(
          home: Scaffold(
            body: new AddAppointmentWidget(),
          ),
        ),
      );
    }
    
    class AddAppointmentWidget extends StatefulWidget {
      @override
      _AddAppointmentWidgetState createState() => _AddAppointmentWidgetState();
    }
    
    class _AddAppointmentWidgetState extends State<AddAppointmentWidget> {
      bool searchbartapped = false;
      bool hideSearchTapped = false;
      var queryResultSet = [];
      var tempSearchStore = [];
    
    // Search Function
      initiateSearch(value) {
        //body
      }
    
      @override
      Widget build(BuildContext context) {
        return ListView(
          children: [
            SizedBox(
              height: 15,
            ),
            Padding(
              padding: const EdgeInsets.all(18.0),
              child: Text('Search', style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold)),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Row(
                children: [
                  Expanded(
                    flex: 5,
                    child: TextFormField(
                        style: TextStyle(color: Color(0xff2a2a2a), fontSize: 18),
                        keyboardType: TextInputType.name,
                        onChanged: (value) {
                          initiateSearch(value);
                        },
                        onTap: () {
                          setState(() {
                            if (hideSearchTapped) {
                              hideSearchTapped = false;
                            } else {
                              searchbartapped = true;
                            }
                          });
                        },
                        cursorColor: Color(0xff2a2a2a),
                        cursorWidth: 1.5,
                        decoration: InputDecoration(
                          hintText: "Search by Name",
                          prefixIcon: Visibility(
                            visible: searchbartapped,
                            child: IconButton(
                                icon: Icon(Icons.arrow_back),
                                color: Colors.black54,
                                onPressed: () {
                                  hideSearchTapped = true;
                                  searchbartapped = !searchbartapped;
                                  queryResultSet = [];
                                  tempSearchStore = [];
                                  setState(() {
                                  });
                                  FocusScope.of(context).unfocus();
                                  return true;
                                }),
                          ),
                        )),
                  ),
                ],
              ),
            ),
            Visibility(
              visible: searchbartapped,
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: ListView(
                    padding: EdgeInsets.all(5.0),
                    primary: false,
                    shrinkWrap: true,
                    children: tempSearchStore.map((element) {
                      print(element['name']);
                    }).toList()),
              ),
            ),
          ],
        );
      }
    }
    

    注意:你应该use lowerCamelCase to name your variable。所以searchbartapped 会变成searchBarTapped

    【讨论】:

    • 非常感谢! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-30
    • 1970-01-01
    • 2021-07-10
    • 2020-03-05
    • 2021-06-04
    • 2022-01-24
    • 2015-05-11
    相关资源
    最近更新 更多