在平時各類各樣的軟件中都會有搜索欄方便各位進行信息的搜索,下面就用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