Created
March 21, 2020 00:57
-
-
Save loicgeek/903e2fe70d0daee3aefb6c42b3849cf3 to your computer and use it in GitHub Desktop.
This gist is a sample of Futurebuilder, search with highlighting
This file contains hidden or 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:flutter/material.dart'; | |
import 'dart:core'; | |
import 'dart:math'; | |
void main() { | |
runApp(MyApp()); | |
} | |
class MyApp extends StatelessWidget { | |
// This widget is the root of your application. | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
debugShowCheckedModeBanner: false, | |
title: 'Search Delegate example', | |
theme: ThemeData( | |
primaryColor: Colors.black, | |
), | |
//We are building our home according to how our app have started | |
home: HomePage()); | |
} | |
} | |
const chars = "abcdefghijklmnopqrstuvwxyz0123456789"; | |
String RandomString(int strlen) { | |
Random rnd = new Random(new DateTime.now().millisecondsSinceEpoch); | |
String result = ""; | |
for (var i = 0; i < strlen; i++) { | |
result += chars[rnd.nextInt(chars.length)]; | |
} | |
return result; | |
} | |
class HomePage extends StatefulWidget { | |
@override | |
_HomePageState createState() => _HomePageState(); | |
} | |
class _HomePageState extends State<HomePage> { | |
Future<List<Product>> productsFuture; | |
ProductRepository productRepo; | |
@override | |
initState(){ | |
super.initState(); | |
productRepo = new ProductRepository(); | |
productsFuture = productRepo.fetchAll(); | |
} | |
@override | |
Widget build(BuildContext context){ | |
return Scaffold( | |
backgroundColor:Colors.white, | |
appBar:AppBar( | |
title:Text('Home'), | |
elevation:0, | |
centerTitle:true, | |
actions:[ | |
IconButton(icon:Icon(Icons.search),onPressed:(){ | |
showSearch(context:context,delegate:MySearchDelegate(productRepo:this.productRepo)); | |
}), | |
] | |
), | |
body:MyFutureBuilder<List<Product>>( | |
future:productsFuture, | |
successWidget:(List<Product> products){ | |
return ListView.separated( | |
itemCount:products.length, | |
separatorBuilder:(context,index){ | |
return Divider(height:.1); | |
}, | |
itemBuilder:(BuildContext context,int index){ | |
Product p = products[index]; | |
return Padding( | |
padding:EdgeInsets.symmetric(horizontal:8,vertical:1), | |
child:Container( | |
padding:EdgeInsets.all(8), | |
decoration:BoxDecoration( | |
color:Colors.grey.withOpacity(.2),), | |
child:Column( | |
children:[ | |
Row(children:[ | |
Text(' ${p.name}',style:TextStyle(fontWeight: FontWeight.w600)), | |
]), | |
Container( | |
child:Text('${p.description}',),), | |
] | |
), | |
),); | |
}); | |
})); | |
} | |
} | |
class MySearchDelegate extends SearchDelegate{ | |
ProductRepository productRepo; | |
MySearchDelegate({this.productRepo}); | |
List<Widget> buildActions(BuildContext context){ | |
return [ | |
IconButton( | |
icon:Icon(Icons.cancel), | |
onPressed:(){ | |
this.query = ""; | |
} | |
), | |
]; | |
} | |
Widget buildResults(BuildContext context){ | |
if(query=='')return Container(); | |
return MyFutureBuilder<List<Product>>( | |
future:this.productRepo.searchProducts(this.query), | |
successWidget:(List<Product> products){ | |
return ListView.separated( | |
itemCount:products.length, | |
separatorBuilder:(context,index){ | |
return Divider(height:.1); | |
}, | |
itemBuilder:(BuildContext context,int index){ | |
Product p = products[index]; | |
return Padding( | |
padding:EdgeInsets.symmetric(horizontal:8,vertical:1), | |
child:Container( | |
padding:EdgeInsets.all(8), | |
decoration:BoxDecoration( | |
color:Colors.grey.withOpacity(.2),), | |
child:Column( | |
children:[ | |
Row(children:[ | |
Text(' ${p.name}',style:TextStyle(fontWeight: FontWeight.w600)), | |
]), | |
Container( | |
child:Text('${p.description}',),), | |
] | |
), | |
),); | |
}); | |
} | |
); | |
} | |
buildLeading(BuildContext context){ | |
return IconButton( | |
icon:Icon(Icons.arrow_back), | |
onPressed:(){ | |
this.close(context,null); | |
} | |
); | |
} | |
buildSuggestions(BuildContext context){ | |
if(query=='')return Container(); | |
return MyFutureBuilder<List<Product>>( | |
future:this.productRepo.searchProducts(this.query), | |
successWidget:(List<Product> products){ | |
return ListView.separated( | |
itemCount:products.length, | |
separatorBuilder:(context,index){ | |
return Divider(height:.1); | |
}, | |
itemBuilder:(BuildContext context,int index){ | |
Product p = products[index]; | |
return Padding( | |
padding:EdgeInsets.symmetric(horizontal:8,vertical:1), | |
child:Container( | |
padding:EdgeInsets.all(8), | |
decoration:BoxDecoration( | |
color:Colors.grey.withOpacity(.2),), | |
child:Column( | |
children:[ | |
Row(children:[ | |
buildMatch(query,p.name,context), | |
]), | |
Container( | |
child: buildMatch(query,p.description,context),), | |
] | |
), | |
),); | |
}); | |
} | |
); | |
} | |
} | |
buildMatch(String query, String found,BuildContext context){ | |
var tabs = found.toLowerCase().split(query.toLowerCase()); | |
List<TextSpan> list=[]; | |
for(var i =0;i<tabs.length;i++){ | |
if(i%2==1){ | |
list.add(TextSpan(text:query,style:TextStyle(color:Colors.green,fontWeight: FontWeight.w600,fontSize:15))); | |
} | |
list.add(TextSpan(text:tabs[i])); | |
} | |
return RichText( | |
text: TextSpan( | |
style:TextStyle(color:Colors.black), | |
children:list | |
), | |
); | |
} | |
//Common widget | |
class MyFutureBuilder<T> extends StatelessWidget{ | |
final Future future; | |
Widget Function(dynamic error) errorWidget; | |
Widget Function(T data) successWidget; | |
MyFutureBuilder({ | |
this.future, | |
this.errorWidget, | |
this.successWidget, | |
}); | |
@override | |
build(BuildContext context){ | |
return FutureBuilder<T>( | |
future:this.future, | |
builder:(BuildContext context,AsyncSnapshot snapshotData){ | |
switch(snapshotData.connectionState){ | |
case ConnectionState.active: | |
case ConnectionState.waiting: | |
return Center(child:Container(child:CircularProgressIndicator())); | |
case ConnectionState.none: | |
return Center(child:Text('Check Your Internet Connection')); | |
break; | |
case ConnectionState.done: | |
if(snapshotData.hasError){ | |
return this.errorWidget!=null?this.errorWidget(snapshotData.error):Center(child:Text('${snapshotData.error}')); | |
}else{ | |
return this.successWidget(snapshotData.data); | |
} | |
break; | |
default: | |
return Container(); | |
} | |
}); | |
} | |
} | |
// Repository file | |
class Product{ | |
final int id; | |
final String name; | |
final String description; | |
final int price; | |
Product({this.id,this.name,this.description,this.price}); | |
toString(){ | |
return ''' | |
$id: $name | |
'''; | |
} | |
} | |
class ProductRepository { | |
final List<Product> products = List.generate(20,(int index){ | |
return Product(id:index,name:"Product $index",description:RandomString(100),price:index*20); | |
}); | |
Future<List<Product>> fetchAll(){ | |
return Future.delayed(Duration(seconds:2),(){ | |
return products; | |
}); | |
} | |
Future<List<Product>> searchProducts(String query){ | |
return Future.delayed(Duration(seconds:1),(){ | |
return products.where((p){ | |
return (p.name.toLowerCase().contains(query.toLowerCase()) || p.description.toLowerCase().contains(query.toLowerCase())); | |
}).toList(); | |
}); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment