在平时各类各样的软件中都会有搜索栏方便各位进行信息的搜索,下面就用flutter撸一个搜索栏建议。git
这里关键点主要仍是key,主要用于获取当前TextFiled的位置。github
GlobalKey textFieldKey;
TextEditingController _searchController = TextEditingController();
FocusNode _searchFocus = FocusNode();
TextField(
key: textFieldKey,
controller: _searchController,
focusNode: _searchFocus,
cursorColor: Colors.black,
decoration: InputDecoration(
suffixIcon: !_searchFocus.hasFocus
? null
: _searchController.text.isEmpty
? null
: IconButton(
icon: Icon(
Icons.close,
color: Colors.black,
),
onPressed: () {},
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.black)))
)
复制代码
findOverLayPosition是根据key来获取当前TextFiled的位置,Positioned中的位置能够根据本身的需求进行调整,高度在这里我是根据获取到的内容条数来进行设置的。async
void findOverLayPosition() {
RenderBox renderBox = textFieldKey.currentContext.findRenderObject();
height = renderBox.size.height;
width = renderBox.size.width;
Offset offset = renderBox.localToGlobal(Offset.zero);
xPosition = offset.dx;
yPosition = offset.dy;
}
// 生成搜索建议
OverlayEntry _buildSearchSuggest() {
return OverlayEntry(builder: (context) {
return Positioned(
left: xPosition - 40.0,
width: width + 40.0,
top: yPosition + height + 10,
height: _keywords.length * height,
child: Material(
child: Container(
height: _keywords.length * height,
decoration: BoxDecoration(color: Colors.white, boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 5.0,
),
]),
child: ListView.builder(
padding: EdgeInsets.zero,
itemBuilder: (context, index) {
return InkWell(
onTap: () {
searchSuggest.remove();
searchSuggest = null;
search2detail(_keywords[index]);
},
child: SearchItem(
text: _keywords[index],
itemHeight: height,
isFirstItem: index == 0 ? true : false,
isLastItem:
index == _keywords.length - 1 ? true : false,
));
},
itemCount: _keywords.length)),
),
);
});
}
复制代码
在这里我是在TextField的ontap方法中获取TextField位置信息的,而后当TextField内容发生变化的时候就插入Overlay,在onSubmitted的时候把Overlay给移除。ide
OverlayEntry searchSuggest;
onTap: () {
findDropdownPosition();
setState(() {});
},
onChanged: (value) async {
if (value.isNotEmpty) {
if (searchSuggest != null) removeOverlay();
searchSuggest = _buildSearchSuggest();
OverlayState overlayState = Overlay.of(context);
overlayState.insert(searchSuggest);
else {
if (searchSuggest != null) removeOverlay();
}
setState(() {});
},
onSubmitted: (value) {
searchSuggest.remove();
searchSuggest = null;
}
复制代码
在实现点击删除按钮把TextFiled内容清除的时候出现了个问题ui
invalid text selection: TextSelection(baseOffset: 2, extentOffset: 2, affinity:TextAffinity.upstream, isDirectional: false) spa
解决方法: 只须要添加小延迟就行了,具体能够看这个issuecode
Future.delayed(Duration(microseconds: 20), () {
_searchController.clear();
_searchFocus.unfocus();
if (searchSuggest != null) removeOverlay();
});
复制代码
详细内容能够查看这里 代码地址cdn