+ Autocomplete (prototype)

This commit is contained in:
2020-10-12 19:51:53 +02:00
parent 4dfd1c5e4a
commit e025484cab
6 changed files with 160 additions and 42 deletions

View File

@@ -5,6 +5,7 @@
In most cases you can leave this as-is, but you if you want to provide 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 additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. --> FlutterApplication and put your custom class here. -->
<uses-permission android:name="android.permission.INTERNET" />
<application <application
android:name="io.flutter.app.FlutterApplication" android:name="io.flutter.app.FlutterApplication"
android:label="menui_mobile" android:label="menui_mobile"

View File

@@ -1,4 +1,7 @@
import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class RestaurantCard extends StatelessWidget { class RestaurantCard extends StatelessWidget {
RestaurantCard( RestaurantCard(
@@ -68,24 +71,108 @@ class MenuiSearchBar extends StatefulWidget {
class MenuiSearchBarState extends State<MenuiSearchBar> { class MenuiSearchBarState extends State<MenuiSearchBar> {
final _formKey = GlobalKey<FormState>(); final _formKey = GlobalKey<FormState>();
var suggestions = <String>[];
bool suggestionsOpen = false;
final LayerLink layerLink = LayerLink();
OverlayEntry _overlayEntry;
Future<void> fetchAutocomplete(text) async {
final response = await http.get(
'https://menui.azurewebsites.net/search/autocomplete?string=$text');
final cities = jsonDecode(response.body)['cities'];
final restaurants = jsonDecode(response.body)['restaurants'];
final List<String> result = [...cities, ...restaurants];
setState(() {
suggestions = result;
});
if (!suggestionsOpen && result.isNotEmpty) {
setState(() {
suggestionsOpen = true;
});
_overlayEntry = _createOverlayEntry();
Overlay.of(context).insert(_overlayEntry);
}
print(suggestions);
}
void hideSuggestions() {
if (suggestionsOpen) {
_overlayEntry.remove();
setState(() {
suggestionsOpen = false;
});
}
}
OverlayEntry _createOverlayEntry() {
RenderBox renderBox = context.findRenderObject();
var size = renderBox.size;
return OverlayEntry(
builder: (context) => GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
hideSuggestions();
},
child: Align(
alignment: Alignment.topCenter,
child: Stack(
children: [
Positioned(
width: size.width,
child: CompositedTransformFollower(
offset: Offset(0.0, size.height + 5.0),
link: layerLink,
showWhenUnlinked: false,
child: Material(
color: Colors.grey[800],
elevation: 4.0,
child: ConstrainedBox(
constraints: new BoxConstraints(maxHeight: 200),
child: ListView.builder(
padding: EdgeInsets.zero,
shrinkWrap: true,
itemCount: suggestions.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(
suggestions[index],
style: TextStyle(color: Colors.orange),
),
);
}),
),
),
),
)
],
))));
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Form( return Form(
key: _formKey, key: _formKey,
child: CompositedTransformTarget(
link: layerLink,
child: Column( child: Column(
children: <Widget>[ children: <Widget>[
Padding( Padding(
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(12),
child: TextFormField( child: TextFormField(
onChanged: (text) => fetchAutocomplete(text),
style: TextStyle(color: Colors.orange), style: TextStyle(color: Colors.orange),
decoration: InputDecoration( decoration: InputDecoration(
hintStyle: TextStyle(color: Colors.grey), hintStyle: TextStyle(color: Colors.grey),
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey, width: 1.0), borderSide:
BorderSide(color: Colors.grey, width: 1.0),
borderRadius: BorderRadius.circular(12)), borderRadius: BorderRadius.circular(12)),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.orange, width: 2.0), borderSide:
BorderSide(color: Colors.orange, width: 2.0),
borderRadius: BorderRadius.circular(12)), borderRadius: BorderRadius.circular(12)),
hintText: 'Wyszukaj miasto lub nazwę restauracji.', hintText: 'Wyszukaj miasto lub nazwę restauracji.',
suffixIcon: Icon( suffixIcon: Icon(
@@ -103,6 +190,6 @@ class MenuiSearchBarState extends State<MenuiSearchBar> {
), ),
], ],
), ),
); ));
} }
} }

1
lib/dataTypes.dart Normal file
View File

@@ -0,0 +1 @@

View File

@@ -8,7 +8,14 @@ void main() {
class App extends StatelessWidget { class App extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp( return GestureDetector(
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.focusedChild.unfocus();
}
},
child: MaterialApp(
title: 'Menui', title: 'Menui',
theme: ThemeData( theme: ThemeData(
primarySwatch: Colors.orange, primarySwatch: Colors.orange,
@@ -18,7 +25,7 @@ class App extends StatelessWidget {
visualDensity: VisualDensity.adaptivePlatformDensity, visualDensity: VisualDensity.adaptivePlatformDensity,
), ),
home: HomePage(title: 'Menui - food guide'), home: HomePage(title: 'Menui - food guide'),
); ));
} }
} }

View File

@@ -67,6 +67,20 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
http:
dependency: "direct main"
description:
name: http
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.2"
http_parser:
dependency: transitive
description:
name: http_parser
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.4"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
@@ -88,6 +102,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.0-nullsafety.1" version: "1.8.0-nullsafety.1"
pedantic:
dependency: transitive
description:
name: pedantic
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.2"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter

View File

@@ -21,6 +21,7 @@ environment:
sdk: ">=2.7.0 <3.0.0" sdk: ">=2.7.0 <3.0.0"
dependencies: dependencies:
http: ^0.12.2
flutter: flutter:
sdk: flutter sdk: flutter