直接上图了
因为是刚接触Flutter不久,所以里面有很多嵌套不是很合理,还有几个地方其实可以抽出来公用一个,需要的话可以自行优化。这里主要看具体功能就好了
智能排序
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class DropDownMenuRouteLayout extends SingleChildLayoutDelegate {
final Rect position;
final double menuHeight;
DropDownMenuRouteLayout({this.position, this.menuHeight});
@override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
// TODO: implement getConstraintsForChild
return BoxConstraints.loose(Size(position.right - position.left, 150));
}
@override
Offset getPositionForChild(Size size, Size childSize) {
// TODO: implement getPositionForChild
return Offset(0, position.bottom);
}
@override
bool shouldRelayout(SingleChildLayoutDelegate oldDelegate) {
// TODO: implement shouldRelayout
return true;
}
}
class DropDownMenuRoute extends PopupRoute {
final Rect position;
final double menuHeight;
Function(int) rightClick;
int pos = 0;
DropDownMenuRoute({this.position, this.menuHeight,this.pos,this.rightClick});
@override
// TODO: implement barrierColor
Color get barrierColor => null;
@override
// TODO: implement barrierDismissible
bool get barrierDismissible => true;
@override
// TODO: implement barrierLabel
String get barrierLabel => null;
@override
Widget buildPage(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
final size = MediaQuery.of(context).size;
// TODO: implement buildPage
return CustomSingleChildLayout(
delegate:
DropDownMenuRouteLayout(position: position, menuHeight: menuHeight),
child: SizeTransition(
sizeFactor: Tween<double>(begin: 0.0, end: 1.0).animate(animation),
child: Container(
color: Colors.white,
width: size.width,
alignment: Alignment.centerLeft,
child: Column(
children: [
GestureDetector(
onTap: () {
setState(() {
pos = 0;
Navigator.of(context).pop();
rightClick(0);
});
},
child: Container(
padding: EdgeInsets.only(top: 20, left: 20),
child: Text(
'智能排序',
style: TextStyle(
fontSize: 14,
color:
pos == 0 ? Color(0xff00D28C) : Color(0xff9A9A9A),
decoration: TextDecoration.none,
fontWeight: FontWeight.w400),
),
)),
GestureDetector(
onTap: () {
setState(() {
pos = 1;
Navigator.of(context).pop();
rightClick(1);
});
},
child: Container(
padding: EdgeInsets.only(top: 20, left: 20),
child: Text(
'离我最近',
style: TextStyle(
fontSize: 14,
color:
pos == 1 ? Color(0xff00D28C) : Color(0xff9A9A9A),
decoration: TextDecoration.none,
fontWeight: FontWeight.w400),
),
)),
GestureDetector(
onTap: () {
setState(() {
Navigator.of(context).pop();
rightClick(2);
});
},
child: Container(
padding: EdgeInsets.only(top: 20, left: 20),
child: Text(
'价格最低',
style: TextStyle(
fontSize: 14,
color: pos == 2 ? Color(0xff00D28C) : Color(0xff9A9A9A),
decoration: TextDecoration.none,
fontWeight: FontWeight.w400),
),
),
),
],
),
),
),
);
}
@override
// TODO: implement transitionDuration
Duration get transitionDuration => Duration(milliseconds: 300);
}
位置区域
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class PositionSite extends SingleChildLayoutDelegate {
final Rect position;
final double menuHeight;
PositionSite({this.position, this.menuHeight});
@override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
// TODO: implement getConstraintsForChild
return BoxConstraints.loose(Size(position.right - position.left, 400));
}
@override
Offset getPositionForChild(Size size, Size childSize) {
// TODO: implement getPositionForChild
return Offset(0, position.bottom);
}
@override
bool shouldRelayout(SingleChildLayoutDelegate oldDelegate) {
// TODO: implement shouldRelayout
return true;
}
}
class PositionSiteDropDownMenuRoute extends PopupRoute {
final Rect position;
final double menuHeight;
Function(int) rightClick;
int pos = 0;
PositionSiteDropDownMenuRoute(
{this.position, this.menuHeight, this.pos, this.rightClick});
@override
// TODO: implement barrierColor
Color get barrierColor => null;
@override
// TODO: implement barrierDismissible
bool get barrierDismissible => true;
@override
// TODO: implement barrierLabel
String get barrierLabel => null;
@override
Widget buildPage(BuildContext context, Animation<double> animation,Animation<double> secondaryAnimation) {
// TODO: implement buildPage
return CustomSingleChildLayout(
delegate: PositionSite(position: position, menuHeight: menuHeight),
child: SizeTransition(
sizeFactor: Tween<double>(begin: 0.0, end: 1.0).animate(animation),
child: PopRoute(rightClick),
),
);
}
@override
Duration get transitionDuration => Duration(milliseconds: 300);
}
class PopRoute extends StatefulWidget{
final Function(int) rightClick;
PopRoute(this.rightClick);
@override
State<StatefulWidget> createState() {
return new _PopRoute(rightClick);
}
}
class _PopRoute extends State<PopRoute>{
Function(int) rightClick;
_PopRoute(this.rightClick);
List<String> _datas = []; //一级分类集合
List<String> articles = []; //二级分类集合
int index = 0; //一级分类下标
Color textColor = Color(0xff00D28C); //字体颜色
@override
Widget build(BuildContext context) {
_datas.clear();
_datas.add('附近');
_datas.add('行政区域');
articles.add('附近');
articles.add('1Km');
articles.add('2Km');
articles.add('3Km');
articles.add('4Km');
articles.add('5Km');
articles.add('6Km');
final size = MediaQuery.of(context).size;
return Container(
width: size.width,
alignment: Alignment.centerLeft,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
flex: 2,
child: Container(
color: Colors.white,
child: ListView.builder(
itemCount: _datas.length,
itemBuilder: (BuildContext context, int position) {
return GestureDetector(
child: Container(
alignment: Alignment.topLeft,
margin: EdgeInsets.only(left: 10),
padding: EdgeInsets.symmetric(
vertical: 10, horizontal: 10),
child: Text(
_datas[position],
style: TextStyle(
color: index == position
? textColor
: Color(0xff9A9A9A),
fontWeight: index == position
? FontWeight.w600
: FontWeight.w400,
fontSize: 16,
decoration: TextDecoration.none),
),
),
onTap: () {
setState(() {
index = position; //记录选中的下标
});
},
);
},
),
),
),
Expanded(
flex: 5,
child: Container(
color: Colors.white,
child: getChip(index),
)),
],
),
);
}
Widget getChip(int i) {
articles.clear();
if(index == 0){
articles.add('附近');
articles.add('6Km');
articles.add('6Km');
articles.add('3Km');
articles.add('4Km');
articles.add('5Km');
articles.add('6Km');
}else{
articles.add('上海');
articles.add('北京');
articles.add('江苏');
}
return ListView(
children: <Widget>[
Container(
alignment: Alignment.topLeft,
padding: const EdgeInsets.all(10),
child: Wrap(
spacing: 20.0, //两个widget之间横向的间隔
direction: Axis.vertical, //方向
alignment: WrapAlignment.start, //内容排序方式
children: List<Widget>.generate(
articles.length,
(int index) {
return GestureDetector(
onTap: () {
Navigator.of(context).pop();
},
child: Text(
articles[index],
style: TextStyle(
fontSize: 16,
color: Color(0xff9A9A9A),
decoration: TextDecoration.none,
fontWeight: FontWeight.w400),
),
);
},
).toList(),
), //传入一级分类下标
),
],
);
}
}
综合筛选
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class PositionSite extends SingleChildLayoutDelegate {
final Rect position;
final double menuHeight;
PositionSite({this.position, this.menuHeight});
@override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
// TODO: implement getConstraintsForChild
return BoxConstraints.loose(Size(position.right - position.left, 400));
}
@override
Offset getPositionForChild(Size size, Size childSize) {
// TODO: implement getPositionForChild
return Offset(0, position.bottom);
}
@override
bool shouldRelayout(SingleChildLayoutDelegate oldDelegate) {
// TODO: implement shouldRelayout
return true;
}
}
class ComprehensiveSite extends PopupRoute {
final Rect position;
final double menuHeight;
ComprehensiveSite({this.position, this.menuHeight});
@override
// TODO: implement barrierColor
Color get barrierColor => null;
@override
// TODO: implement barrierDismissible
bool get barrierDismissible => true;
@override
// TODO: implement barrierLabel
String get barrierLabel => null;
@override
Widget buildPage(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
// TODO: implement buildPage
return CustomSingleChildLayout(
delegate: PositionSite(position: position, menuHeight: menuHeight),
child: SizeTransition(
sizeFactor: Tween<double>(begin: 0.0, end: 1.0).animate(animation),
child: PopRoute(),
),
);
}
@override
// TODO: implement transitionDuration
Duration get transitionDuration => Duration(milliseconds: 300);
}
class PopRoute extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return _PopRoute();
}
}
class _PopRoute extends State<PopRoute> {
//直流
bool isSelectDc = false;
//交流
bool isSelectAc = false;
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
var minPower = TextEditingController();
var maxPower = TextEditingController();
minPower.text = '1';
maxPower.text = '360';
return Container(
width: size.width,
color: Colors.white,
alignment: Alignment.centerLeft,
child: Column(
children: <Widget>[
Container(
width: size.width,
margin: EdgeInsets.symmetric(vertical: 20, horizontal: 25),
child: Text(
'充电类型',
style: TextStyle(
color: Color(0xff00D28C),
decoration: TextDecoration.none,
fontSize: 16,
fontWeight: FontWeight.w500),
)),
Container(
width: size.width,
child: Row(
children: [
Expanded(
flex: 1,
child: Container(
padding: EdgeInsets.only(left: 15, right: 10),
child: RaisedButton.icon(
onPressed: () {
setState(() {
isSelectDc ? isSelectDc = false : isSelectDc = true;
});
},
icon: Image.asset('images/icon_dc_nor.png'),
label: Text('直流'),
elevation: 1,
color:
!isSelectDc ? Color(0xffF4F4F4) : Color(0xff00D28C),
),
),
),
Expanded(
flex: 1,
child: Container(
padding: EdgeInsets.only(right: 15, left: 10),
child: RaisedButton.icon(
onPressed: () {
setState(() {
isSelectAc ? isSelectAc = false : isSelectAc = true;
});
},
icon: Image.asset('images/icon_ac_nor.png'),
label: Text('交流'),
color:
!isSelectAc ? Color(0xffF4F4F4) : Color(0xff00D28C),
elevation: 1,
),
),
),
],
),
),
Container(
width: size.width,
margin: EdgeInsets.symmetric(vertical: 20, horizontal: 25),
child: Text(
'充电功率(kw)',
style: TextStyle(
color: Color(0xff00D28C),
decoration: TextDecoration.none,
fontSize: 16,
fontWeight: FontWeight.w500),
)),
Container(
width: size.width,
child: Row(
children: [
Expanded(
flex: 1,
child: Container(
padding: EdgeInsets.only(left: 15, right: 10),
child: FlatButton(
onPressed: () {},
child: ConstrainedBox(
constraints: BoxConstraints(
maxHeight: 25,
),
child: TextField(
textAlign: TextAlign.center,
controller: minPower,
decoration: InputDecoration(
border: InputBorder.none,
),
),
),
color: Color(0xffF4F4F4),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30)),
),
),
),
Container(
child: Text(
'-',
style: TextStyle(
fontWeight: FontWeight.w100,
color: Colors.black,
decoration: TextDecoration.none),
),
),
Expanded(
flex: 1,
child: Container(
padding: EdgeInsets.only(left: 15, right: 10),
child: FlatButton(
onPressed: () {},
child: ConstrainedBox(
constraints: BoxConstraints(
maxHeight: 25
),
child: TextField(
textAlign: TextAlign.center,
controller: maxPower,
decoration: InputDecoration(
border: InputBorder.none,
),
),
),
color: Color(0xffF4F4F4),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30)),
),
),
),
],
),
),
Container(
padding: EdgeInsets.only(top: 100),
child: Row(
children: [
Expanded(
flex: 1,
child: Container(
padding: EdgeInsets.only(left: 15, right: 10),
child: RaisedButton(
onPressed: () {
setState(() {
minPower.text = "1";
maxPower.text = "360";
});
},
child: Text('重置'),
elevation: 1,
color: Color(0xffF4F4F4),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30)),
),
),
),
Expanded(
flex: 1,
child: Container(
padding: EdgeInsets.only(left: 15, right: 10),
child: RaisedButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('应用'),
elevation: 1,
textColor: Color(0xffFFFFFF),
color: Color(0xff00D28C),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30)),
),
),
),
],
),
)
],
),
);
}
}
具体使用(部分使用代码
GestureDetector(
onTap: () {
RenderBox renderBox =
_globalKey.currentContext.findRenderObject();
Rect box =
renderBox.localToGlobal(Offset.zero) & renderBox.size;
Navigator.push(
context,
DropDownMenuRoute(
position: box,
menuHeight: 300,
pos: pos,
rightClick: (pos) {
this.pos = pos;
}));
},
child: Row(
children: <Widget>[Text('智能排序'), Icon(Icons.expand_more)],
),
),
GestureDetector(
onTap: () {
RenderBox renderBox =
_globalKey.currentContext.findRenderObject();
Rect box =
renderBox.localToGlobal(Offset.zero) & renderBox.size;
Navigator.push(
context,
PositionSiteDropDownMenuRoute(
position: box,
menuHeight: 300,
pos: pos,
rightClick: (pos) {}));
},
child: Container(
child: Row(
children: <Widget>[
Text('位置区域'),
Icon(Icons.expand_more)
],
),
),
),
GestureDetector(
onTap: () {
RenderBox renderBox =
_globalKey.currentContext.findRenderObject();
Rect box =
renderBox.localToGlobal(Offset.zero) & renderBox.size;
Navigator.push(
context,
ComprehensiveSite(
position: box,
menuHeight: 300,
));
},
child: Row(
children: <Widget>[Text('综合筛选'), Icon(Icons.expand_more)],
),
)