flutter_typeahead 0.1.0 flutter_typeahead: ^0.1.0 copied to clipboard
A highly customizable typeahead text input field
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'flutter_typeahead demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
title: TabBar(
tabs: [
Tab(
text: 'Example 1: Navigation',
),
Tab(
text: 'Example 2: Form'
)
]
),
),
body: TabBarView(
children: [
NavigationExample(),
FormExample()
]
)
),
);
}
}
class NavigationExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(32.0),
child: Column(
children: <Widget>[
Text(
'What are you looking for?'
),
SizedBox(height: 10.0,),
TypeAheadField(
autofocus: true,
style: DefaultTextStyle.of(context).style.copyWith(
fontStyle: FontStyle.italic
),
decoration: InputDecoration(
border: OutlineInputBorder()
),
suggestionsCallback: (pattern) async {
return await BackendService.getSuggestions(pattern);
},
itemBuilder: (context, suggestion) {
return ListTile(
leading: Icon(Icons.shopping_cart),
title: Text(suggestion['name']),
subtitle: Text('\$${suggestion['price']}'),
);
},
onSuggestionSelected: (suggestion) {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => ProductPage(product: suggestion)
));
},
),
],
),
);
}
}
class FormExample extends StatefulWidget {
@override
_FormExampleState createState() => _FormExampleState();
}
class _FormExampleState extends State<FormExample> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final TextEditingController _typeAheadController = TextEditingController();
String _selectedCity;
@override
Widget build(BuildContext context) {
return Form(
key: this._formKey,
child: Padding(
padding: EdgeInsets.all(32.0),
child: Column(
children: <Widget>[
Text(
'What is your favorite city?'
),
TypeAheadFormField(
controller: this._typeAheadController,
decoration: InputDecoration(
labelText: 'City'
),
suggestionsCallback: (pattern) {
return CitiesService.getSuggestions(pattern);
},
itemBuilder: (context, suggestion) {
return ListTile(
title: Text(suggestion),
);
},
transitionBuilder: (context, suggestionsBox, controller) {
return suggestionsBox;
},
onSuggestionSelected: (suggestion) {
this._typeAheadController.text = suggestion;
},
validator: (value) {
if (value.isEmpty) {
return 'Please select a city';
}
},
onSaved: (value) => this._selectedCity = value,
),
SizedBox(height: 10.0,),
RaisedButton(
child: Text('Submit'),
onPressed: () {
if (this._formKey.currentState.validate()) {
this._formKey.currentState.save();
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('Your Favorite City is ${this._selectedCity}')
));
}
},
)
],
),
),
);
}
}
class ProductPage extends StatelessWidget {
final Map<String, dynamic> product;
ProductPage({this.product});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(50.0),
child: Column(
children: [
Text(
this.product['name'],
style: Theme.of(context).textTheme.headline,
),
Text(
this.product['price'].toString() + ' USD',
style: Theme.of(context).textTheme.subhead,
)
],
),
),
);
}
}
class BackendService {
static Future<List> getSuggestions(String query) async {
await Future.delayed(Duration(seconds: 1));
return List.generate(3, (index) {
return {
'name': query + index.toString(),
'price': Random().nextInt(100)
};
});
}
}
class CitiesService {
static final cities = [
'Beirut',
'Damascus',
'San Fransisco',
'Rome',
'Los Angeles',
'Madrid',
'Bali',
'Barcelona',
'Paris',
'Bucharest'
];
static getSuggestions(String query) {
final cities = CitiesService.cities;
cities.sort((a, b) {
return CitiesService._distance(query, a) - CitiesService._distance(query, b);
});
return cities.take(4).toList();
}
// source: https://github.com/kseo/edit_distance/blob/master/lib/src/levenshtein.dart
static int _distance(String s1, String s2) {
if (s1 == s2) {
return 0;
}
if (s1.length == 0) {
return s2.length;
}
if (s2.length == 0) {
return s1.length;
}
List<int> v0 = new List<int>(s2.length + 1);
List<int> v1 = new List<int>(s2.length + 1);
List<int> vtemp;
for (var i = 0; i < v0.length; i++) {
v0[i] = i;
}
for (var i = 0; i < s1.length; i++) {
v1[0] = i + 1;
for (var j = 0; j < s2.length; j++) {
int cost = 1;
if (s1.codeUnitAt(i) == s2.codeUnitAt(j)) {
cost = 0;
}
v1[j + 1] = min(v1[j] + 1, min(v0[j + 1] + 1, v0[j] + cost));
}
vtemp = v0;
v0 = v1;
v1 = vtemp;
}
return v0[s2.length];
}
}