ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Flutter TextField 自动匹配补全

2021-07-01 15:59:37  阅读:249  来源: 互联网

标签:textFormOverlayEntry return 补全 int list length TextField com Flutter


Flutter中TextField本身并不支持自动匹配功能,因此需要我们自定义实现该功能。

首先考虑如何在TextField下方一个显示匹配选项的对话框,可以选择overlay实现该功能同时搭配CompositedTransformFollower是悬浮框跟随TextField,具体实现如下:

  var userName = TextEditingController();
  var passWord = TextEditingController();
  String inputTip = "";
  CommentFunction fuc = CommentFunction(); //调用公共函数
  OverlayEntry textFormOverlayEntry = new OverlayEntry(
    builder: (context) {
      return Container();
    },
  );
  bool overlayIsFirstVis = true; //账号匹配overlay是否第一次显示
  LayerLink layerLink = new LayerLink(); //overlay跟随

/**创建匹配选择悬浮框**/
 OverlayEntry createAccountOverly() {
    OverlayEntry overlayEntry = new OverlayEntry(builder: (context) {
      return new Positioned(
        width: 230,
        child: new CompositedTransformFollower(
          offset: Offset(5, 31),
          link: layerLink,
          child: new Material(
            child: new Container(
              constraints: BoxConstraints(maxHeight: 180),
              child: ListView.builder(
                shrinkWrap: true,
                itemCount: matchListData.length,
                itemBuilder: (context, index) {
                  return matchListData[index];
                },
              ),
            ),
          ),
        ),
      );
    });
    return overlayEntry;
  }

/**匹配选项**/
List<ListTile> matchListData = [];
  List getMatchData(String str) {
    List<String> list = [];
    int index = 0;
    for (int i = 0; i < str.length; ++i) {
      if (str[i] == '@') index = i;
    }
    String substr = str.substring(index);
    if (substr.length == str.length) {
      list = [
        "@163.com",
        "@126.com",
        "@qq.com",
        "@gmail.com",
        "@yeah.net",
        "@sina.com",
        "@139.com",
        "@188.cn",
      ];
      for (int i = 0; i < list.length; ++i) list[i] = str + list[i];
    } else if (substr.length == 1) {
      list = [
        "163.com",
        "126.com",
        "qq.com",
        "gmail.com",
        "yeah.net",
        "sina.com",
        "139.com",
        "189.cn",
      ];
      for (int i = 0; i < list.length; ++i) list[i] = str + list[i];
    } else if (substr.length > 1) {
      List tempList = [
        "@163.com",
        "@126.com",
        "@qq.com",
        "@gmail.com",
        "@yeah.net",
        "@sina.com",
        "@139.com",
        "@189.cn",
      ];
      list.clear();
      for (int i = 0; i < tempList.length; ++i) {
        if (isChildStr(substr, tempList[i])) {
          list.add(tempList[i]);
        }
      }
      String preStr = str.substring(0, index);
      for (int i = 0; i < list.length; ++i) list[i] = preStr + list[i];
    }
    matchListData.clear();
    for (int i = 0; i < list.length; ++i) {
      matchListData.add(ListTile(
        dense: true,
        hoverColor: Colors.black12,
        title: Text(list[i]),
        onTap: () {
          userName.text = list[i];
          textFormOverlayEntry.remove();
          overlayIsFirstVis = true;
        },
      ));
    }
    return matchListData;
  }

 bool isChildStr(String str1, String str2) {
    for (int i = 1; i < str1.length; ++i) {
      if (str1[i] != str2[i]) return false;
    }
    return true;
  }
/**输入框 */
  Widget inputAccountContainer() {
    return Container(
      height: 30,
      width: 240,
      child: TextField(
          controller: userName,
          textAlign: TextAlign.justify,
          cursorColor: Colors.black38,
          obscureText: false,
          cursorWidth: 1,
          decoration: InputDecoration(
            hintText: "163/QQ/Gmail/等",
            contentPadding: const EdgeInsets.only(
                top: 8.0, left: 2, right: -15.0, bottom: 0),
            border: OutlineInputBorder(
                borderRadius: BorderRadius.circular(0),
                borderSide: BorderSide(color: Colors.black26, width: 0)),
            enabledBorder: OutlineInputBorder(
              //选中时边框颜色
              borderRadius: BorderRadius.circular(0),
              borderSide: BorderSide(color: Colors.black26),
            ),
            focusedBorder: OutlineInputBorder(
              //失焦时边框颜色
              borderRadius: BorderRadius.circular(0),
              borderSide: BorderSide(color: Colors.black26),
            ),
          ),
          onChanged: (value) {
            matchAccounntState();
          }),
    );
  }

 /**账号匹配 */
  void matchAccounntState() {
    inputTip = "";
    getMatchData(userName.text);
    if (userName.text.length != 0) {
      if (overlayIsFirstVis) {
        textFormOverlayEntry = createAccountOverly();
        overlayIsFirstVis = false;
        Overlay.of(context)?.insert(textFormOverlayEntry);
      } else {
        textFormOverlayEntry.remove();
        textFormOverlayEntry = createAccountOverly();
        Overlay.of(context)?.insert(textFormOverlayEntry);
      }
    } else {
      textFormOverlayEntry.remove();
      overlayIsFirstVis = true;
    }
    setState(() {});
  }

最终的实现效果:

标签:textFormOverlayEntry,return,补全,int,list,length,TextField,com,Flutter
来源: https://blog.csdn.net/flutter_learner/article/details/118387883

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有