How to show search results below my search bar? - flutter

I already have an app which has a search bar and can search and find the search results in the background. However, I don't know how to display it right below my search bar, or anywhere in the HomeScreen.
Please help me connect the two parts.
The current HomePage looks something like this,
import 'package:flutter/material.dart';
import 'dart:developer' as devtools show log;
...
class HomePage extends StatefulWidget {
const HomePage({super.key});
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
// Initial marker location
LatLng markerPoint = LatLng(12.9716, 77.5946);
final LocationService _locationService = getIt<LocationService>();
...
LatLng get currentMarkerPoint => markerPoint;
#override
Widget build(BuildContext context) {
return Stack(
children: [
FlutterMap(
...
SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// Here I have the card which contains the search bar
// I want the search results to be displayed right below this.
Card(
child: TextField(
decoration: const InputDecoration(
prefixIcon: Icon(Icons.location_on_outlined),
hintText: "Search for a location",
contentPadding: EdgeInsets.all(16.0),
),
onChanged: (text) async {
if (text.isEmpty || text.length < 3) {
return;
}
LatLng pos = await _locationService.currentLocation;
var locations = await _locationSearch
.searchNearCurrentPosition(text, pos);
},
),
),
],
),
),
),
],
);
}
}
I have managed to work around with some backend and managed to store my search results inside of a widget in a class named HomePageSearchListView which is defined as below
import 'package:flutter/material.dart';
import 'package:geoalarm/services/location_search/location_entities.dart';
import 'dart:developer' as devtools show log;
typedef LocationCallback = void Function(LocationEntity location);
class HomePageNotesListView extends StatelessWidget {
final List<LocationEntity> locations;
final LocationCallback onTap;
const HomePageNotesListView({
Key? key,
required this.locations,
required this.onTap,
}) : super(key: key);
#override
Widget build(BuildContext context) {
devtools.log(locations.length.toString());
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: locations.length,
itemBuilder: (context, index) {
final location = locations.elementAt(index);
devtools.log(location.country);
return ListTile(
title: Text(location.name),
subtitle:
Text("${location.state}, ${location.country}, ${location.point}"),
onTap: () => onTap(location),
);
},
);
}
}
The problem is that I do not know how to use this class that I made appear below the search bar in my homepage.
Help would be appreciated.

after a bit of research and help from another answer to this same question. (Which is now deleted) I have found solution to this problem.
You could just use the Search Delegate class which is an already pre implemented search UI for flutter except that you'd have to implement the results that you want to show and the suggestions you have to show.
A whole lot of customisation is not available but this should work for most apps which are struggling to implement a search screen.

Related

How to show the full image from a drawer in flutter

I'm trying to show the full image that has been clicked on from my drawer.
I have a liste of images that I display in my drawer and What I want is that when I click on a specific image, it closes my drawer and show the image on my screen in a kind of an image slider where I can switch images directly from the opened image.
here is my code where I extract my list of images from my asset folder :
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class GetImages extends StatefulWidget {
const GetImages({super.key});
#override
State<GetImages> createState() => _GetImagesState();
}
class _GetImagesState extends State<GetImages> {
List<String> imagePaths = [];
#override
void initState() {
_initImages();
super.initState();
}
Future _initImages() async {
final Map<String, dynamic> assets =
jsonDecode(await rootBundle.loadString('AssetManifest.json'));
setState(() {
imagePaths = assets.keys
.where((String key) => key.contains('photos/'))
.where((String key) => key.contains('.JPG'))
.toList();
});
}
#override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
return GridView.count(
crossAxisCount: constraints.maxWidth > 700 ? 4 : 2,
children: imagePaths
.map(
(path) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 17),
child: Image.asset(path),
),
)
.toList(),
);
});
}
}
And here is my code for my drawer :
import 'package:flutter/material.dart';
import 'package:myapp/widgets/get_images.dart';
import 'package:image_viewer/image_viewer.dart';
class SideBar extends StatelessWidget {
const SideBar({super.key, required this.title});
final String title;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(title)),
body: const Center(
child: Text('My Page!'),
),
drawer: Drawer(
child: InkWell(
child: GetImages(),
onTap: () {
//ImageViewer.showImageSlider(images: ["assets/photos/IMG_4100.JPG"]);
// montre la photo et ferme la sidebar
Navigator.pop(context);
},
),
),
);
}
}
Thanks in advance for your help :)
You could try this package that i've used before https://pub.dev/packages/lightbox seems like it does exactly what you are looking for.

Flutter: Help me search Algolia data on the app

I am working on a real estate app where I would like to display a list of properties, that is retrieved from the Algolia database, and search them from the search input field by typing the I.D of the properties. Like this
I have successfully linked/setup Firebase & Algolia. And I am able to display the properties on the screen, using infinite_scroll_pagination and algolia_helper_flutter packages.
The problem I am facing is I cannot search the houses by typing the I.D of the properties.
Please check out my code, tell me where I went wrong. Thank you.
Best,
class HousesListView extends StatefulWidget {
const HousesListView({Key? key}) : super(key: key);
#override
State<HousesListView> createState() => _HousesListViewState();
}
class _HousesListViewState extends State<HousesListView> {
// textController for search box input
final _searchTextController = TextEditingController();
// pageController from infinite_scroll_pagination package
final PagingController<int, MdlAlgoliaProperties> pagingController =
PagingController(firstPageKey: 0);
/// Component holding search filters from algolia_helper_flutter package
final _filterState = FilterState();
// search houses in Algolia Database
final _houseDatabase = HitsSearcher.create(
applicationID: AlgoliaCredentials.applicationID,
apiKey: AlgoliaCredentials.apiKey,
state: const SearchState(
indexName: AlgoliaCredentials.hitsIndex,
facetFilters: ['a2-propertyType: House']));
// stream and display list of properties on the screen
Stream<PropertiesPage> get displayPropertiesOnThePage =>
_houseDatabase.responses.map(PropertiesPage.fromResponse);
/// Get stream of search result, like the number of the result from the search box
Stream<SearchMetadata> get searchMetadata =>
_houseDatabase.responses.map(SearchMetadata.fromResponse);
#override
void initState() {
super.initState();
// listen to keystroke & query the results by the letters that user types in
_searchTextController
.addListener(() => _houseDatabase.query(_searchTextController.text));
// load properties on the page
displayPropertiesOnThePage.listen((properties) {
if (properties.pageKey == 0) pagingController.refresh();
pagingController.appendPage(
properties.alogliaPPT, properties.nextPageKey);
}).onError((error) => pagingController.error = error);
// error here!
// this loads the list of house successfully and properly when its enabled, but search does not work anymore
// but, when this disable, the search works, but it does not load the list of houses anymore
pagingController.addPageRequestListener((pageKey) =>
_houseDatabase.applyState((state) => state.copyWith(page: pageKey))); //<= error occur in this line
// connect database and filter state
_houseDatabase.connectFilterState(_filterState);
// pageController listens to filterState
_filterState.filters.listen((_) => pagingController.refresh());
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: appBarTitle(context, 'List of Houses'),
backgroundColor: ZayyanColorTheme.zayyanGrey,
endDrawer: const Drawer(
width: 350,
child: HouseFilter(),
),
body: Center(
child: Column(
children: [
SizedBox(
height: 44,
child: TextField(
controller: _searchTextController,
decoration: const InputDecoration(
border: InputBorder.none,
hintText: 'Enter a search term',
prefixIcon: Icon(Icons.search),
),
),
),
StreamBuilder<SearchMetadata>(
stream: searchMetadata,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const SizedBox.shrink();
}
return Padding(
padding: const EdgeInsets.all(8.0),
child: Text('${snapshot.data!.nbHits} hits'),
);
},
),
Expanded(
child: _hits(context),
),
],
),
),
);
}
Widget _hits(BuildContext context) {
return PropertyHitsListView(
pagingController: pagingController,
noItemsFound: (context) => const NoResultsView(),
onHitClick: (objectID) {
print(objectID);
},
);
}
#override
void dispose() {
_searchTextController.dispose();
_houseDatabase.dispose();
_filterState.dispose();
pagingController.dispose();
super.dispose();
}
}

flutter TextField use cause KeyboardListener alway show keyboard on event

using KeyboardListener to gain barcode from scanner, i can't resolve a incredibly stupid problem.
scanning first with keyboardListener work perfectly.
events are gained, barcode too, no virtual keyboard, perfect..
but if i use any Textfield, in the same screen or anywhere in the program, after that,
any event coming to keyboardListener show Virtual Keyboard, without any textfield or else in the screen.
it come to be a nightmare..
I WANT TO AVOID THE KEYBOARD SHOWING, without any input..
don't want to close keyboard, many way on stack overflow to do it.
Step to reproduce:
1:use Physical keyboard or HID to enter serialcode or else whith KeyboardListener
2: Tap on textfield, and write anything and valid text
3: normay, KeyboardListener regain control and get physical events, and the Keyboard show on each...and this is the problem..
youtube video to illustrate (52s)
strange thing. if you use square key to set app background and get foreground, problem disapear.. virtual keyboard dont show again on physical keyboard or HID use... until next textfield use..
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'KbdListener with TextField'),
);
}}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<FocusNode> ListFocusNode = [FocusNode(), FocusNode()];
DateTime whenlastchar = DateTime.now();
List<String> scanned4 = [];
String _receivedtext = "Scanned text here..";
final TextEditingController _myTextControler =
TextEditingController(text: "");
#override
void initState() {
ListFocusNode.first.requestFocus();
super.initState();
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
KeyboardListener(
key: const Key('KeyboardListener-files'),
focusNode: ListFocusNode.first,
autofocus: true,
onKeyEvent: (event) async {
var difference = DateTime.now().difference(whenlastchar);
whenlastchar = DateTime.now();
if (event.character != null) {
if (difference.inMilliseconds > 1000) {
scanned4.clear();
}
scanned4.add(event.character.toString());
if ((event.character == "\n") ||
(event.character == " ") ||
(event.character == 0x09)) {
String tempo =
scanned4.reduce((first, second) => first + second);
scanned4.clear();
tempo = tempo.trim();
// update
setState(() {
_receivedtext = tempo;
});
}
}
},
child: Column(
children: <Widget>[
Text(
_receivedtext,
style: Theme.of(context).textTheme.headlineSmall,
),
],
),
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
TextField(
controller: _myTextControler,
autofocus: false,
focusNode: ListFocusNode.last,
keyboardType: TextInputType.text,
style: const TextStyle(
fontSize: 20,
color: Colors.black,
fontWeight: FontWeight.w400,
),
textInputAction: TextInputAction.done,
onSubmitted: (value) {
print("textfield value: '$value'");
setState(() {
_receivedtext = value;
});
_myTextControler.clear();
FocusScope.of(context)
.requestFocus(ListFocusNode.first);
},
),
Row(children: [
TextButton(
child: const Text("KeyboardListener Focus"),
onPressed: () {
setState(() {
FocusScope.of(context)
.requestFocus(ListFocusNode.first);
});
},
),
]),
],
),
),
],
),
),
);
}
}
ok, so, there is no flutter software solution at this time.
its a google keyboard bug or flutter bug.. or both.
seem that the google keyboard don't dismiss from textfield, TextControler, focusnode or else. or flutter don't destroy callback to google keyboard. don't know.
But, trying other app keyboard, and its magical. its working.. normaly.. fluently.. as expected.
to be honest and complete, perhaps this replacement keyboard don't implement a callback or else.
but he work, the app work, my customers can use it fluently..
without changing any part of my code or flutter code..
the cost? just say to customer. 'install and use this keyboard..'
Did you try using https://pub.dev/packages/flutter_barcode_listener
This Library allows barcode scanning and addresses many problem arising from keyboard listener

Get cell value from table - flutter

I have created a table from an imported CSV file, I have set this table to be hidden as I don't want the user to actually see the table.
I have also created a custom widget to be reused several times throughout my app, it's just a container that displays some text. Here is the code for the table:
import 'package:flutter/material.dart';
import 'package:csv/csv.dart';
import 'package:flutter/services.dart' show rootBundle;
class RouteNameTable extends StatefulWidget {
const RouteNameTable({Key key}) : super(key: key);
#override
_RouteNameTableState createState() => _RouteNameTableState();
}
class _RouteNameTableState extends State<RouteNameTable> {
List<List<dynamic>> data = [];
void loadAsset() async {
final myData = await rootBundle.loadString("assets/routes.csv");
List<List<dynamic>> csvTable = const CsvToListConverter().convert(myData);
data = csvTable;
setState(() {});
}
#override
void initState() {
super.initState();
loadAsset();
}
#override
Widget build(BuildContext context) {
return Visibility(
visible: false,
child: SingleChildScrollView(
child: Table(
border: TableBorder.all(width: 1.0),
children: data.map((item) {
return TableRow(
children: item.map((row) {
return Container(
color: Colors.blueGrey,
child: Padding(
padding: const EdgeInsets.all(1.0),
child: Text(
row.toString(),
style: const TextStyle(fontSize: 20.0),
),
),
);
}).toList());
}).toList(),
),
),
);
}
}
The custom widget I created is just a container that displays a number, name and has a colour. When inserting the widget I use the following code
const RouteTemplate(
routeNumber: '33',
routeName: 'Corstorphine - Caversham - City - Wakari',
routeColor: Color(0xFFF067A6),
),
This works correctly. However, what I want to do is replace the text (such as '33') that I have typed with data from the table I created. It will still say 33 but instead of me typing it, it retrieves the first column in the second row as routeNumber, the second column in the second row as routeName and so on. I would like this as the CSV file may change, and instead of having to add/remove/change the route number, once the new CSV file is added it will do it automatically.
Thanks

Flutter oddly not reloading widget

I have been working with flutter just a while now but I have never experienced such a weird problem. basically I'm checking if there is a logged on username show them the main page and if not show them the signup page. after the user signs up (and logs in at the same time) I want to take him to my main page. even though I return a new Scaffold the mobile screen doesn't change at all. not with a hot load or anything. but after stopping the program and running it again (because the user is logged in) it automatically goes to my main page (which I want to do without having to stop the program and running it again. any ideas why this is happening couldn't find anything related to this.
import 'package:sociagrowapp/models/user.dart';
import 'package:sociagrowapp/Authenticate/SignIn.dart';
import 'package:sociagrowapp/HomePages/Home.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Wrapper extends StatefulWidget{
#override
createState() => _Wrapper();
}
class _Wrapper extends State<Wrapper> {
#override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
print(user);
// return either the Home or Authenticate widget
if (user == null){
print('Should Changed 3');
return Scaffold(
body: SignIn()
);
}
else {
print('Should Changed');
print('Should Changed2');
return PageData()
}
}
}
Just in case I will add the PagesData Code but I don't think it is related to that.
import 'package:flutter/material.dart';
import 'package:sociagrowapp/services/auth.dart';
int selectedbotnavi = 0;
class DailyTasks extends StatefulWidget
{
#override
createState() => _DailyTasks();
}
class _DailyTasks extends State<DailyTasks>
{
Widget build(BuildContext context)
{
return Center(
child: Text("15")
);
}
}
class Settings extends StatefulWidget
{
#override
createState() => _Settings();
}
class _Settings extends State<Settings>
{
String _httpdataretrieved;
Widget build(BuildContext context)
{
return Column(
children: <Widget>[
Container(width:MediaQuery.of(context).size.width,
child: Text('Your Account Username',style: TextStyle(fontWeight: FontWeight.w400),),
alignment: Alignment.center,
padding: EdgeInsetsDirectional.fromSTEB(0, 20, 0, 0),
),
Container(width:MediaQuery.of(context).size.width,
child: Text(' Important: Your Account must be public for SociaGrow. \n There are limited Features available to private Accounts',style: TextStyle(fontWeight: FontWeight.w900,fontSize:14),
),
alignment: Alignment.center,
padding: EdgeInsetsDirectional.fromSTEB(0, 5, 0, 20),
),
Container(child: TextField(
obscureText: true,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Username',
),
),
width: MediaQuery.of(context).size.width * 0.8,
alignment: Alignment.center,
padding: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 15),
),
Container(
child: RaisedButton(
child: Text('Change Username'),
),
)
],
);
}
}
List <Widget> Pages = [new DailyTasks(),new DailyTasks(),new DailyTasks()];
class PageData extends StatefulWidget
{
#override
createState() => _PageData();
}
class _PageData extends State<PageData>
{
void _changeselectbotnaviindex(int index)
{
selectedbotnavi = index;
setState(() {
});
}
final AuthService _auth = AuthService();
#override
Widget build(BuildContext context)
{
return Scaffold(
appBar: AppBar(title: Container(
child: Image.asset('assets/Logo.png',width: 100,height: 200,),
padding: EdgeInsetsDirectional.fromSTEB(0, 10, 0 , 0),
),
actions: <Widget>[
FlatButton(
child: Text('Sign out'),
onPressed: () async {
await this._auth.signOut();
},
),
],
),
body: Pages[selectedbotnavi],
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items :[
BottomNavigationBarItem(icon: Icon(Icons.timelapse),title:Text('Daily Tasks')),
BottomNavigationBarItem(icon: Icon(Icons.call_made),title:Text('Growth')),
BottomNavigationBarItem(icon: Icon(Icons.settings),title:Text('Settings')),],
currentIndex: selectedbotnavi,
onTap: _changeselectbotnaviindex,
selectedItemColor: Colors.amber[800],
unselectedItemColor: Colors.black,
showUnselectedLabels: true,
)
);
}
}
That is not the way you navigate to a new page in Flutter.
In Flutter, the way to navigate between pages is with Navigator, which is a widget that manages a set of child widgets with a stack discipline. That is, Navigator has everything ready for you to navigate between pages easily. When you create an app with MaterialApp, Flutter attaches a Navigator to the top of the widget tree for you under the hood. This way, you can access the Navigator in your widget tree via context, by calling Navigator.of(context).
In your case, when the user taps the sign up button in your sign up page, you should do something like:
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (_) => PageData()));
This way, your app will navigate to PageData when the user signs in.
Check out this Flutter.dev article on navigating pages for more details on the topic.
You have to call SetState() so your build method is called again.
You could add a VoidListener to your SignIn(onLogin:(){setState(() {});})