-
Notifications
You must be signed in to change notification settings - Fork 352
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
aalhamali
committed
Aug 30, 2018
0 parents
commit 364a71a
Showing
71 changed files
with
3,460 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
.DS_Store | ||
.dart_tool/ | ||
|
||
.packages | ||
.pub/ | ||
|
||
build/ | ||
ios/.generated/ | ||
ios/Flutter/Generated.xcconfig | ||
ios/Runner/GeneratedPluginRegistrant.* | ||
|
||
.idea | ||
pubspec.lock | ||
flutter_typeahead |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
## 0.1.0 - TODO: Add release date. | ||
|
||
* TODO: Describe initial release. |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
BSD 2-Clause License | ||
|
||
Copyright (c) 2018, AbdulRahmanAlHamali | ||
All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions are met: | ||
|
||
* Redistributions of source code must retain the above copyright notice, this | ||
list of conditions and the following disclaimer. | ||
|
||
* Redistributions in binary form must reproduce the above copyright notice, | ||
this list of conditions and the following disclaimer in the documentation | ||
and/or other materials provided with the distribution. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
# Flutter TypeAhead | ||
A TypeAhead widget for Flutter, where you can show suggestions to | ||
users as they type | ||
|
||
<img src="https://raw.githubusercontent.com/AbdulRahmanAlHamali/flutter_typeahead/master/flutter_typeahead.gif"> | ||
|
||
## Features | ||
* Shows suggestions in an overlay that floats on top of other widgets | ||
* Allows you to specify what the suggestions will look like through a | ||
builder function | ||
* Allows you to specify what happens when the user taps a suggestion | ||
* Accepts all the parameters that traditional `TextFields` accept, like | ||
decoration, custom `TextEditingController`, text styling, etc. | ||
* Provides two versions, a normal version and a [FormField](https://docs.flutter.io/flutter/widgets/FormField-class.html) | ||
version that accepts validation, submitting, etc. | ||
* Provides high customizability; you can customize the suggestion box decoration, | ||
the loading bar, the animation, the debounce duration, etc. | ||
|
||
## Installation | ||
See the [installation instructions on pub](https://pub.dartlang.org/packages/flutter_typeahead#-installing-tab-). | ||
|
||
## Usage examples | ||
After you import the package: | ||
```dart | ||
import 'package:flutter_typeahead/flutter_typeahead.dart'; | ||
``` | ||
|
||
You can then use it as follows: | ||
```dart | ||
TypeAheadField( | ||
autofocus: true, | ||
style: DefaultTextStyle.of(context).style.copyWith( | ||
fontStyle: FontStyle.italic | ||
), | ||
decoration: InputDecoration( | ||
border: OutlineInputBorder() | ||
), | ||
suggestionsCallback: (pattern) async { | ||
return 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) | ||
)); | ||
}, | ||
) | ||
``` | ||
In the code above, the `autfocus`, `style` and `decoration` are the same as | ||
those of `TextField`, and are not mandatory. | ||
|
||
The `suggestionCallback` is called with the search string that the user | ||
types, and is expected to return a `List` of data, either synchronously or | ||
asynchronously. In this example, we call some function called | ||
`BackendService.getSuggestions` and provide it with the search pattern | ||
|
||
The `itemBuilder` is called to build a widget for each suggestion. | ||
In this example, we build a simple `ListTile` that shows the name and the | ||
price of the item. Please note that you shouldn't provide an `onTap` | ||
callback here. The TypeAhead widget takes care of that. | ||
|
||
The `onSuggestionSelected` is a callback that provides us with the | ||
suggestion that the user tapped. In this example, when the user taps a | ||
suggestion, we navigate to a page that shows us the information of the | ||
tapped product. | ||
|
||
Here's another example, where we use the TypeAheadFormField inside a `Form`: | ||
```dart | ||
final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); | ||
final TextEditingController _typeAheadController = TextEditingController(); | ||
String _selectedCity; | ||
... | ||
.. | ||
. | ||
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}') | ||
)); | ||
} | ||
}, | ||
) | ||
], | ||
), | ||
), | ||
) | ||
``` | ||
Here, we are assigning to the `controller` property a | ||
`TextEditingController` that we called `_typeAheadController`. We use this | ||
controller in the `onSuggestionSelected` callback to set the value of the | ||
`TextField` to the selected suggestion. | ||
|
||
The `validator` callback can be used like any `FormField.validator` function. | ||
In our example, it checks whether a value has been entered, and displays an | ||
error message if not. The `onSaved` callback is used to save the value of | ||
the field to the `_selectedCity` member variable | ||
|
||
The `transitionBuilder` allows us to customize the animation of the | ||
suggestion box. In this example, we are just returning the suggestionBox | ||
immediately, meaning that we don't want any animation. | ||
|
||
## Customizations | ||
TypeAhead widgets consist of a `TextField` and a suggestion box that shows | ||
as the user types. Both are highly customizable | ||
|
||
### Customizing the TextField | ||
You can customize the field with all the usual customizations available for | ||
`TextField` in Flutter. Examples include: decoration, style, controller, | ||
focusNode, autofocus, enabled, etc. | ||
|
||
### Customizing the Suggestions Box | ||
TypeAhead provides default configurations for the suggestions box. You can, | ||
however, override most of them. | ||
|
||
#### Customizing the loader, the error and the "no items found" message | ||
You can use the loadingBuilder, errorBuilder and noItemsFoundBuilder to | ||
customize their corresponding widgets. For example, to show a custom error | ||
widget: | ||
```dart | ||
errorBuilder: (BuildContext context, Object error) => | ||
Text( | ||
'$error', | ||
style: TextStyle( | ||
color: Theme.of(context).errorColor | ||
) | ||
) | ||
``` | ||
#### Customizing the animation | ||
You can customize the suggestion box animation through 3 parameters: the | ||
`animationDuration`, the `animationStart`, and the `transitionBuilder`. The | ||
`animationDuration` specifies how long the animation should take, while the | ||
`animationStart` specified what point (between 0.0 and 1.0) the animation | ||
should start from. The `transitionBuilder` accepts the `suggestionsBox` and | ||
`animationController` as parameters, and should return a widget that uses | ||
the `animationController` to animate the display of the `suggestionsBox`. | ||
For example: | ||
```dart | ||
transitionBuilder: (context, suggestionsBox, animationController) => | ||
FadeTransition( | ||
child: suggestionsBox, | ||
opacity: CurvedAnimation( | ||
parent: animationController, | ||
curve: Curves.fastOutSlowIn | ||
), | ||
) | ||
``` | ||
In order to fully remove the animation, this callback should simply return | ||
the `suggestionsBox`. This callback could also be used to wrap the | ||
`suggestionsBox` with any desired widgets, not necessarily for animation. | ||
|
||
#### Customizing the debounce duration | ||
The suggestion box does not fire for each character the user types. Instead, | ||
we wait until the user is idle for a duration of time, and then we call the | ||
`suggestionsCallback`. The duration defaults to 300 milliseconds, but can be | ||
configured using the `debounceDuration` parameter | ||
|
||
#### Customizing the decoration of the suggestions box | ||
You can also customize the decoration of the suggestions box. For example, | ||
to give it a blue border, you can write: | ||
```dart | ||
decoration: BoxDecoration( | ||
border: Border.all( | ||
color: Colors.blue | ||
) | ||
) | ||
``` |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
.DS_Store | ||
.dart_tool/ | ||
|
||
.packages | ||
.pub/ | ||
|
||
build/ | ||
|
||
.flutter-plugins |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# This file tracks properties of this Flutter project. | ||
# Used by Flutter tool to assess capabilities and perform upgrades etc. | ||
# | ||
# This file should be version controlled and should not be manually edited. | ||
|
||
version: | ||
revision: c7ea3ca377e909469c68f2ab878a5bc53d3cf66b | ||
channel: beta |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# example | ||
|
||
A usage example of flutter_typeahead | ||
|
||
## Getting Started | ||
|
||
For help getting started with Flutter, view our online | ||
[documentation](https://flutter.io/). |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
*.iml | ||
*.class | ||
.gradle | ||
/local.properties | ||
/.idea/workspace.xml | ||
/.idea/libraries | ||
.DS_Store | ||
/build | ||
/captures | ||
GeneratedPluginRegistrant.java |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
def localProperties = new Properties() | ||
def localPropertiesFile = rootProject.file('local.properties') | ||
if (localPropertiesFile.exists()) { | ||
localPropertiesFile.withReader('UTF-8') { reader -> | ||
localProperties.load(reader) | ||
} | ||
} | ||
|
||
def flutterRoot = localProperties.getProperty('flutter.sdk') | ||
if (flutterRoot == null) { | ||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") | ||
} | ||
|
||
apply plugin: 'com.android.application' | ||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" | ||
|
||
android { | ||
compileSdkVersion 27 | ||
|
||
lintOptions { | ||
disable 'InvalidPackage' | ||
} | ||
|
||
defaultConfig { | ||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). | ||
applicationId "aalhamali.example" | ||
minSdkVersion 16 | ||
targetSdkVersion 27 | ||
versionCode 1 | ||
versionName "1.0" | ||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" | ||
} | ||
|
||
buildTypes { | ||
release { | ||
// TODO: Add your own signing config for the release build. | ||
// Signing with the debug keys for now, so `flutter run --release` works. | ||
signingConfig signingConfigs.debug | ||
} | ||
} | ||
} | ||
|
||
flutter { | ||
source '../..' | ||
} | ||
|
||
dependencies { | ||
testImplementation 'junit:junit:4.12' | ||
androidTestImplementation 'com.android.support.test:runner:1.0.1' | ||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||
package="aalhamali.example"> | ||
|
||
<!-- The INTERNET permission is required for development. Specifically, | ||
flutter needs it to communicate with the running application | ||
to allow setting breakpoints, to provide hot reload, etc. | ||
--> | ||
<uses-permission android:name="android.permission.INTERNET"/> | ||
|
||
<!-- io.flutter.app.FlutterApplication is an android.app.Application that | ||
calls FlutterMain.startInitialization(this); in its onCreate method. | ||
In most cases you can leave this as-is, but you if you want to provide | ||
additional functionality it is fine to subclass or reimplement | ||
FlutterApplication and put your custom class here. --> | ||
<application | ||
android:name="io.flutter.app.FlutterApplication" | ||
android:label="example" | ||
android:icon="@mipmap/ic_launcher"> | ||
<activity | ||
android:name=".MainActivity" | ||
android:launchMode="singleTop" | ||
android:theme="@style/LaunchTheme" | ||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density" | ||
android:hardwareAccelerated="true" | ||
android:windowSoftInputMode="adjustResize"> | ||
<!-- This keeps the window background of the activity showing | ||
until Flutter renders its first frame. It can be removed if | ||
there is no splash screen (such as the default splash screen | ||
defined in @style/LaunchTheme). --> | ||
<meta-data | ||
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame" | ||
android:value="true" /> | ||
<intent-filter> | ||
<action android:name="android.intent.action.MAIN"/> | ||
<category android:name="android.intent.category.LAUNCHER"/> | ||
</intent-filter> | ||
</activity> | ||
</application> | ||
</manifest> |
Oops, something went wrong.