Created
August 24, 2021 10:32
-
-
Save ngtrphuong/84aec297ebc802c3cfb55b6942b39716 to your computer and use it in GitHub Desktop.
DropDownSearch with border in popupitems display
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:dio/dio.dart'; | |
import 'package:dropdown_search/dropdown_search.dart'; | |
import 'package:flutter/cupertino.dart'; | |
import 'package:flutter/material.dart'; | |
import 'user_model.dart'; | |
void main() => runApp(MyApp()); | |
class MyApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'dropdownSearch Demo', | |
//enable this line if you want test Dark Mode | |
//theme: ThemeData.dark(), | |
home: MyHomePage(), | |
); | |
} | |
} | |
class MyHomePage extends StatefulWidget { | |
@override | |
_MyHomePageState createState() => _MyHomePageState(); | |
} | |
class _MyHomePageState extends State<MyHomePage> { | |
final _formKey = GlobalKey<FormState>(); | |
final _openDropDownProgKey = GlobalKey<DropdownSearchState<String>>(); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar(title: Text("DropdownSearch Demo")), | |
body: Padding( | |
padding: const EdgeInsets.all(25), | |
child: Form( | |
key: _formKey, | |
autovalidateMode: AutovalidateMode.onUserInteraction, | |
child: ListView( | |
padding: EdgeInsets.all(4), | |
children: <Widget>[ | |
Divider(), | |
///show favorites on top list | |
DropdownSearch<UserModel>( | |
showSelectedItems: true, | |
showSearchBox: true, | |
compareFn: (i, s) => i?.isEqual(s) ?? false, | |
label: "Person with favorite option", | |
onFind: (filter) => getData(filter), | |
onChanged: (data) { | |
print(data); | |
}, | |
dropdownBuilder: _customDropDownExample, | |
popupItemBuilder: _customPopupItemBuilderExample2, | |
showFavoriteItems: true, | |
favoriteItemsAlignment: MainAxisAlignment.start, | |
favoriteItems: (items) { | |
return items.where((e) => e.name.contains("Mrs")).toList(); | |
}, | |
favoriteItemBuilder: (context, item) { | |
return Container( | |
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 6), | |
decoration: BoxDecoration( | |
border: Border.all(color: Colors.grey), | |
borderRadius: BorderRadius.circular(10), | |
color: Colors.grey[100]), | |
child: Text( | |
"${item.name}", | |
textAlign: TextAlign.center, | |
style: TextStyle(color: Colors.red), | |
), | |
); | |
}, | |
), | |
Divider(), | |
///merge online and offline data in the same list and set custom max Height | |
DropdownSearch<UserModel>( | |
items: [ | |
UserModel(name: "Offline name1", id: "999"), | |
UserModel(name: "Offline name2", id: "0101") | |
], | |
maxHeight: 300, | |
onFind: (String? filter) => getData(filter), | |
label: "choose a user", | |
onChanged: print, | |
showSearchBox: true, | |
), | |
Divider(), | |
], | |
), | |
), | |
), | |
); | |
} | |
Widget _customDropDownExample(BuildContext context, UserModel? item) { | |
if (item == null) { | |
return Container(); | |
} | |
return Container( | |
padding: const EdgeInsets.fromLTRB(0,8.0,0,6.0), | |
decoration: const BoxDecoration( | |
border: Border(top:BorderSide(color:Colors.grey,width:1)) | |
), | |
child: (item.avatar == null) | |
? ListTile( | |
contentPadding: EdgeInsets.all(0), | |
leading: CircleAvatar(), | |
title: Text("No item selected"), | |
) | |
: ListTile( | |
contentPadding: EdgeInsets.all(0), | |
leading: CircleAvatar( | |
// this does not work - throws 404 error | |
// backgroundImage: NetworkImage(item.avatar ?? ''), | |
), | |
title: Text(item.name), | |
subtitle: Text( | |
item.createdAt.toString(), | |
), | |
), | |
); | |
} | |
Widget _customPopupItemBuilderExample( | |
BuildContext context, UserModel? item, bool isSelected) { | |
return Container( | |
margin: EdgeInsets.symmetric(horizontal: 8), | |
decoration: !isSelected | |
? null | |
: BoxDecoration( | |
border: Border.all(color: Theme.of(context).primaryColor), | |
borderRadius: BorderRadius.circular(5), | |
color: Colors.white, | |
), | |
child: ListTile( | |
selected: isSelected, | |
title: Text(item?.name ?? ''), | |
subtitle: Text(item?.createdAt?.toString() ?? ''), | |
leading: CircleAvatar( | |
// this does not work - throws 404 error | |
// backgroundImage: NetworkImage(item.avatar ?? ''), | |
), | |
), | |
); | |
} | |
Widget _customPopupItemBuilderExample2( | |
BuildContext context, UserModel? item, bool isSelected) { | |
return Container( | |
padding: const EdgeInsets.fromLTRB(0,8.0,0,6.0), | |
decoration: const BoxDecoration( | |
border: Border(top:BorderSide(color:Colors.grey,width:1)) | |
), | |
margin: EdgeInsets.symmetric(horizontal: 8), | |
//decoration: !isSelected | |
// ? null | |
// : BoxDecoration( | |
// border: Border.all(color: Theme.of(context).primaryColor), | |
// borderRadius: BorderRadius.circular(5), | |
// color: Colors.white, | |
// ), | |
child: ListTile( | |
selected: isSelected, | |
title: Text(item?.name ?? ''), | |
subtitle: Text(item?.createdAt?.toString() ?? ''), | |
leading: CircleAvatar( | |
// this does not work - throws 404 error | |
// backgroundImage: NetworkImage(item.avatar ?? ''), | |
), | |
), | |
); | |
} | |
Future<List<UserModel>> getData(filter) async { | |
var response = await Dio().get( | |
"https://5d85ccfb1e61af001471bf60.mockapi.io/user", | |
queryParameters: {"filter": filter}, | |
); | |
final data = response.data; | |
if (data != null) { | |
return UserModel.fromJsonList(data); | |
} | |
return []; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class UserModel { | |
final String id; | |
final DateTime? createdAt; | |
final String name; | |
final String? avatar; | |
UserModel( | |
{required this.id, this.createdAt, required this.name, this.avatar}); | |
factory UserModel.fromJson(Map<String, dynamic> json) { | |
return UserModel( | |
id: json["id"], | |
createdAt: | |
json["createdAt"] == null ? null : DateTime.parse(json["createdAt"]), | |
name: json["name"], | |
avatar: json["avatar"], | |
); | |
} | |
static List<UserModel> fromJsonList(List list) { | |
return list.map((item) => UserModel.fromJson(item)).toList(); | |
} | |
///this method will prevent the override of toString | |
String userAsString() { | |
return '#${this.id} ${this.name}'; | |
} | |
///this method will prevent the override of toString | |
bool? userFilterByCreationDate(String filter) { | |
return this.createdAt?.toString().contains(filter); | |
} | |
///custom comparing function to check if two users are equal | |
bool isEqual(UserModel? model) { | |
return this.id == model?.id; | |
} | |
@override | |
String toString() => name; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment