去年今日此門中,人面桃花相映紅
人面不知何處去,桃花依舊笑春風數組
支持左右滑動
支持拖拽結束後停留在固定位置
邊界處理ide
拖拽條封裝成了一個widget:HousePriceui
注意:ColorUtil
是一個第三方顏色插件,須要安裝:flutter_color_plugin
spa
class HousePrice extends StatefulWidget { @override _HousePriceState createState() => _HousePriceState(); } class _HousePriceState extends State<HousePrice> { String _leftPrice = '0'; String _rightPrice = '不限'; double _leftImageMargin = 20; double _rightImageMargin = 20; double _leftBlackLineW = 0; // 左邊黑線的寬度 double _rightBlackLineW = 0; // 右邊黑線的寬度 int _leftImageCurrentIndex = 0; // 左邊選中的價格索引 int _rightImageCurrentIndex = 0; // 右邊選中的價格索引 @override Widget build(BuildContext context) { final screenWidth = MediaQuery.of(context).size.width; return Container( color: Colors.white, child: Column( children: <Widget>[ _priceRangeBlock(), SizedBox(height: 10,), _priceBlock(_leftPrice, _rightPrice), SizedBox(height: 10,), Stack( children: <Widget>[ _lineBlock(context, screenWidth), _leftImageBlock(context, screenWidth), _rightImageBlock(context, screenWidth), ], ), SizedBox(height: 10,), _priceBottomBlock(context) ], ), ); } /* * title模塊 * */ _priceRangeBlock() { return Row( children: <Widget>[ SizedBox( width: 20, ), Text( '價格範圍', style: TextStyle( fontSize: 15, color: ColorUtil.color('#212121'), fontFamily: 'PingFangSC-Semibold', fontWeight: FontWeight.bold, ), ), ], ); } /* * 價格區間 * leftPrice:選中的起始價格 * rightPrice: 選中的最大價格 * */ _priceBlock(String leftPrice, String rightPrice) { return Row( children: <Widget>[ SizedBox( width: 20, ), Text( '$leftPrice-$rightPrice', style: TextStyle( fontSize: 12, color: ColorUtil.color('#757575'), fontFamily: 'PingFangSC-Regular', ), ), ], ); } /* * 橫線視圖模塊,包括黃色橫線和黑色橫線 * */ _lineBlock(BuildContext context, double screenWidth) { return Row( children: <Widget>[ SizedBox( width: 20, ), Stack( children: <Widget>[ Container(// 黃色橫線 color: Colors.white, height: 30, width: screenWidth - 40, alignment: Alignment.center, child: Container( color: ColorUtil.color('#FED836'), height: 4, width: screenWidth - 40, ), ), Positioned(// 左邊黑色橫線 left: 0, top: 13, child:Container( height: 4, width: _leftBlackLineW, decoration: BoxDecoration( color: Colors.white, border: Border(left: BorderSide(color: Colors.black, width: 1), top: BorderSide(color: Colors.black, width: 1), bottom: BorderSide(color: Colors.black, width: 1)) ), ) ), Positioned(// 右邊黑色橫線 right: 0, top: 13, child:Container( height: 4, width: _rightBlackLineW, decoration: BoxDecoration( color: Colors.white, border: Border(right: BorderSide(color: Colors.black, width: 1), top: BorderSide(color: Colors.black, width: 1), bottom: BorderSide(color: Colors.black, width: 1)) ), ) ), ], ), ], ); } /* * 左邊image滑塊,使用到:_imageItem * */ _leftImageBlock(BuildContext context, double screenWidth) { double singleW = (screenWidth-40)/6; return Positioned( left: _leftImageMargin, top: 0, child: GestureDetector( child: _imageItem(), //水平方向移動 onHorizontalDragUpdate: (DragUpdateDetails details) { print('拖拽中'); if(_leftImageMargin < 20) {//處理左邊邊界 _leftImageMargin = 20; _leftBlackLineW = 2; } else if (((screenWidth-(_rightImageMargin+30))-(_leftImageMargin+30))<(singleW-45)) {// 處理兩球相遇狀況 _leftImageMargin = screenWidth-(_rightImageMargin+singleW+15); _leftBlackLineW = _leftImageMargin-20; } else { _leftImageMargin += details.delta.dx; _leftBlackLineW = _leftImageMargin-20 >= 0 ? _leftImageMargin-20 : 2; } setState(() {});// 刷新UI }, onHorizontalDragEnd: (DragEndDetails details) { double singleW = (screenWidth-40)/6; double _leftImageMarginFlag = _leftImageMargin; print('拖拽結束'); if(_leftImageMarginFlag <singleW/2) { _leftImageMargin = 20; _leftBlackLineW = 2; _leftImageCurrentIndex = 0; _leftPrice = '¥0'; } else if (_leftImageMarginFlag <singleW*1.5) { _leftImageMargin = singleW+5; _leftBlackLineW = _leftImageMargin; _leftImageCurrentIndex = 1; _leftPrice = '¥200'; } else if (_leftImageMarginFlag < singleW*2.5) { _leftImageMargin = singleW*2+5; _leftBlackLineW = _leftImageMargin; _leftImageCurrentIndex = 2; _leftPrice = '¥300'; } else if (_leftImageMarginFlag < singleW*3.5) { _leftImageMargin = singleW*3+5; _leftBlackLineW = _leftImageMargin; _leftImageCurrentIndex = 3; _leftPrice = '¥400'; } else if (_leftImageMarginFlag < singleW*4.5) { _leftImageMargin = singleW*4+5; _leftBlackLineW = _leftImageMargin; _leftImageCurrentIndex = 4; _leftPrice = '¥500'; } else if (_leftImageMarginFlag < singleW*5.5) { _leftImageMargin = singleW*5+5; _leftBlackLineW = _leftImageMargin; _leftImageCurrentIndex = 5; _leftPrice = '¥600'; } else { } print('選中第$_leftImageCurrentIndex個'); setState(() {});// 刷新UI }, ) ); } /* * 右邊image滑塊,使用到:_imageItem * */ _rightImageBlock(BuildContext context, double screenWidth) { double singleW = (screenWidth-40)/6; return Positioned( right: _rightImageMargin, top: 0, child: GestureDetector( child: _imageItem(), //水平方向移動 onHorizontalDragUpdate: (DragUpdateDetails details) { print(_rightImageMargin); if(_rightImageMargin < 20) {//處理右邊邊界 _rightImageMargin = 20; _rightBlackLineW = 2; } else if(((screenWidth-(_rightImageMargin+30))-(_leftImageMargin+30))<(singleW-45)) { // 處理兩球相遇狀況 _rightImageMargin = screenWidth-(_leftImageMargin+15+singleW); _rightBlackLineW = _rightImageMargin-20; } else { _rightImageMargin -= details.delta.dx; _rightBlackLineW = _rightImageMargin-20 >= 0 ? _rightImageMargin-20 : 2; } setState(() {}); // 刷新UI }, onHorizontalDragEnd: (DragEndDetails details){ double singleW = (screenWidth-40)/6; double _rightImageMarginFlag = _rightImageMargin; print('拖拽結束'); if(_rightImageMarginFlag <singleW/2) { _rightImageMargin = 20; _rightBlackLineW = 2; _rightImageCurrentIndex = 0; _rightPrice = '不限'; } else if (_rightImageMarginFlag <singleW*1.5) { _rightImageMargin = singleW+5; _rightBlackLineW = _rightImageMargin; _rightImageCurrentIndex = 1; _rightPrice = '¥600'; } else if (_rightImageMarginFlag < singleW*2.5) { _rightImageMargin = singleW*2+5; _rightBlackLineW = _rightImageMargin; _rightImageCurrentIndex = 2; _rightPrice = '¥500'; } else if (_rightImageMarginFlag < singleW*3.5) { _rightImageMargin = singleW*3+5; _rightBlackLineW = _rightImageMargin; _rightImageCurrentIndex = 3; _rightPrice = '¥400'; } else if (_rightImageMarginFlag < singleW*4.5) { _rightImageMargin = singleW*4+5; _rightBlackLineW = _rightImageMargin; _rightImageCurrentIndex = 4; _rightPrice = '¥300'; } else if (_rightImageMarginFlag < singleW*5.5) { _rightImageMargin = singleW*5+5; _rightBlackLineW = _rightImageMargin; _rightImageCurrentIndex = 5; _rightPrice = '¥200'; } print('選中第$_rightImageCurrentIndex個'); setState(() {});// 刷新UI }, ), ); } // 滑塊的image _imageItem(){ return Image.asset( 'assets/images/house_price_sliding.png', width: 30, height: 30, ); } /* * 底部價格大模塊,使用到:_priceItem,_priceTitleList * */ _priceBottomBlock(BuildContext context) { final screenWidth = MediaQuery.of(context).size.width; final singleW = (screenWidth-40)/6; double margin = 14.5; return Stack( children: <Widget>[ Container( color: Colors.white, height: 17, width: screenWidth-40, ), Positioned( left: 7.5, top: 0, child: _priceItem(_priceTitleList[0]), ), Positioned( left: singleW-margin, top: 0, child: _priceItem(_priceTitleList[1]), ), Positioned( left: singleW*2-margin, top: 0, child: _priceItem(_priceTitleList[2]), ), Positioned( left: singleW*3-margin, top: 0, child: _priceItem(_priceTitleList[3]), ), Positioned( left: singleW*4-margin, top: 0, child: _priceItem(_priceTitleList[4]), ), Positioned( left: singleW*5-margin, top: 0, child: _priceItem(_priceTitleList[5]), ), Positioned( right: 3, bottom: 1, child: _priceItem(_priceTitleList[6]), ), ], ); } /* * 底部價格每一個item * */ _priceItem(String title) { return Text( title, style: TextStyle( color: ColorUtil.color('#212121'), fontFamily: 'PingFangSC-Regular', fontSize: 12, ), ); } /* * 價格選擇的數組 * */ List<String> _priceTitleList = <String>['¥0', '¥200', '¥300', '¥400', '¥500', '¥600', '不限']; }