Skip to content

Instantly share code, notes, and snippets.

@ngtrphuong
Created August 24, 2021 10:32
Show Gist options
  • Save ngtrphuong/84aec297ebc802c3cfb55b6942b39716 to your computer and use it in GitHub Desktop.
Save ngtrphuong/84aec297ebc802c3cfb55b6942b39716 to your computer and use it in GitHub Desktop.
DropDownSearch with border in popupitems display
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 [];
}
}
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