Flutter TextField 自动匹配补全
作者:互联网
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