這篇“Flutter怎么實現自定義下拉選擇框”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Flutter怎么實現自定義下拉選擇框”文章吧。
先看效果圖:
關鍵點:彈出、收回動畫、狀態改變、選項聯動
思路: 我們可以看到一個完整的下拉框有頭部和具體的下拉選項兩部分組成,頭部又和下拉組進行了聯動, 把頭部當做1個數組,下方選項作為1個數組,兩個數組數量一致之間形成一個完整的下拉選擇框可以更好的控制聯動效果。
首先我們看彈出和收回,我們可以把他看作一個組件的高度由0逐漸擴大再逐漸縮小至0,只要我們對這個組件的高度用動畫來進行控制就可以實現,下方有一個黑色透明度漸變,這里我們根據上方彈窗的動畫來改變下方黑色陰影的變化即可。
關鍵代碼:
/// 下拉組件 @override Widget build(BuildContext context) { return Column( children: [ _MenuBuilder( animation: animation, // 這里顯示我們需要的具體下拉框選項內容 child: widget.children[widget.menuController.index], ), isShowShadow // 是否顯示下方黑色陰影 只有下拉彈出才顯示 這個地方我們就可以根據UI設計來進行高度自定義 ? Expanded( child: InkWell( child: AnimatedBuilder( animation: animation, builder: (context, child) { // 這里是下拉框下方陰影 點擊陰影隱藏下拉框 return Container( width: double.infinity, height: MediaQuery.of(context).size.height, color: Colors.black .withOpacity(animation.value / (widget.height * 3)), ); }), onTap: () { widget.menuController.hide(); }, )) : const SizedBox(), ], ); } class _MenuBuilder extends StatelessWidget { final Animation<double> animation; final Widget child; const _MenuBuilder({required this.animation, required this.child}); // 這里我們主要用動畫來控制下拉內容組件的高度 @override Widget build(BuildContext context) { return AnimatedBuilder( child: child, animation: animation, builder: (context, child) { return Container( color: Colors.white, height: animation.value, child: child, ); }); }
接下來我們看頭部設計,頭部設計稍微復雜一些,主要還是狀態的改變,選項之間的聯動,這里我們新建一個狀態控制器:主要來對頭部的一些狀態進行控制,比如點擊頭部按鈕之后的文字or顏色的改變,選擇完畢顏色的保存,重置顏色的恢復等一些狀態,下方控制器主要就是來控制頭部的一些狀態。
/// 菜單控制器 class MenuController extends ChangeNotifier { // 當前組件是否顯示 默認不顯示 針對整個菜單數組 bool isShow = false; // 顯示當前組件title的文本 共用 String title = ""; // 顯示哪個下拉框 int index = 0; // 選擇下拉框的的title 這個字段只有在真正選擇的時候才會改變 int titleIndex = 0; /// 更改Title changeTitle(int titleIndex, String? title) { this.titleIndex = titleIndex; this.title = title ?? ""; hide(); } // 顯示下拉 index 為下拉哪一個菜單的index show(int index) { this.index = index; if (!isShow) { isShow = true; } notifyListeners(); } // 隱藏 取消 hide() { isShow = false; notifyListeners(); } }
有了控制器我們還需要對頭部數據進行處理,首先我們的頭部在沒有選擇選項的時候會有一個默認的數組,這個是永遠不會改變的,所以這個數組一旦設置了就不能改變了,之后我們新建一個動態數組也就是當前顯示的數組,這個數組的默認值就是我們未選擇選項的默認值,這里我們需要監聽頭部狀態的改變來對顯示數組進行處理。
關鍵代碼:重點 主要針對頭部狀態改變的處理,這塊代碼搞清楚了,基本就OK了。
@override void initState() { super.initState(); // changeTitles就是我們的顯示數組 changeTitles.addAll(widget.titles); for (var i = 0; i < changeTitles.length; i++) { //_chindren 是我們的頭部組件數組 _children.add(searchFilter(changeTitles[i], i)); } widget.menuController.addListener(() { // 下拉 true 隱藏 false var isShow = widget.menuController.isShow; // 改變頭部狀態 setState(() { if (widget.menuController.title != "") { // 說明當前選擇了選項 賦值我選擇的選項 changeTitles[widget.menuController.titleIndex] = widget.menuController.title; } else { // 為空 說明當前的選項我清空了 賦值初始頭部數組的數據 changeTitles[widget.menuController.titleIndex] = widget.titles[widget.menuController.titleIndex]; } // currentIndex 當前選擇的index 默認-1 用來對比更新頭部文字和顏色 // 如果下拉 更新當前選項inedx 如果隱藏說明沒有選擇任何一個下拉框 置為-1 if (isShow && currentIndex < widget.titles.length) { currentIndex = widget.menuController.index; } else { currentIndex = -1; } // 每次下拉收回我們只需改變頭部數據即可 changeTitles 永遠都是顯示的數組 直接全部更新到組件即可 _children.clear(); for (var i = 0; i < changeTitles.length; i++) { _children.add(searchFilter(changeTitles[i], i)); } }); }); } // 這里就是一個簡單的Row數組 按照百分比排列 也可以自定義不同寬度 @override Widget build(BuildContext context) { return SizedBox( height: widget.headHeight ?? 45, child: Row(children: _children), ); }
主要對頭部文本內容以及顏色進行更新,如果當前選項=頭部中的選項||或者 選項賦值的名字不等于初始值我們就認為選中了此菜單,從而改變顏色。到這里基本邏輯就梳理清楚了,下拉框樣式這個可以自己根據自己的業務進行自定義。
Widget searchFilter(String name, int index) { TextStyle(color: currentIndex == index || widget.titles[index] != name ? widget.clickColor : widget.defaultColor), }
以上就是關于“Flutter怎么實現自定義下拉選擇框”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。