I'm writing a really simple app in Flutter, but I have a problem with state management.
Here's the video of what I have. Link: https://streamable.com/ir3ztr
The video shows my application, but when I switch a screen using Bottom Navigation Bar, the data loads again and again from the API. I don't want that. I want the once downloaded data to be saved in RAM and not being downloaded again from the API. Is that possible? I heard about Provider, but I don't know how to use that in my case.
Is there anyone who can help me?
My code:
World
import 'package:flutter/material.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter_placeholder_textlines/flutter_placeholder_textlines.dart';
import '../../models/world.dart';
import '../../data/world_service.dart';
class WorldScreenAndroid extends StatefulWidget {
#override
_WorldScreenAndroidState createState() => _WorldScreenAndroidState();
}
class _WorldScreenAndroidState extends State<WorldScreenAndroid> {
Future<World> futureWorld;
#override
void initState() {
super.initState();
futureWorld = fetchWorld();
}
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(8.0),
child: FutureBuilder<World> (
future: futureWorld,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView(
children: [
Card(
child: ListTile(
leading: Icon(Icons.public),
title: Text('coronavirus_cases').tr(context: context),
subtitle: Text(NumberFormat('#,###,###', 'en_US').format(snapshot.data.cases).toString())
),
),
Card(
child: ListTile(
leading: Icon(Icons.public),
title: Text('deaths').tr(context: context),
subtitle: Text(NumberFormat('#,###,###', 'en_US').format(snapshot.data.deaths).toString())
),
),
Card(
child: ListTile(
leading: Icon(Icons.public),
title: Text('recovered').tr(context: context),
subtitle: Text(NumberFormat('#,###,###', 'en_US').format(snapshot.data.recovered).toString())
),
)
],
);
}
return ListView(
children: [
Card(
child: ListTile(
leading: Icon(Icons.public),
title: Text('coronavirus_cases').tr(context: context),
subtitle: PlaceholderLines(
count: 1,
animate: true,
color: Colors.grey,
minWidth: 0.10,
maxWidth: 0.50,
),
),
),
Card(
child: ListTile(
leading: Icon(Icons.public),
title: Text('deaths').tr(context: context),
subtitle: PlaceholderLines(
count: 1,
animate: true,
color: Colors.grey,
minWidth: 0.10,
maxWidth: 0.50,
),
),
),
Card(
child: ListTile(
leading: Icon(Icons.public),
title: Text('recovered').tr(context: context),
subtitle: PlaceholderLines(
count: 1,
animate: true,
color: Colors.grey,
minWidth: 0.10,
maxWidth: 0.50,
),
),
)
],
);
},
)
);
}
}
Countries
import 'package:flutter/material.dart';
import 'package:easy_localization/easy_localization.dart';
import '../../models/country.dart';
import '../../data/countries_service.dart';
class CountriesScreenAndroid extends StatefulWidget {
#override
_CountriesScreenAndroidState createState() => _CountriesScreenAndroidState();
}
class _CountriesScreenAndroidState extends State<CountriesScreenAndroid> {
Future<List<Country>> futureCountries;
#override
void initState() {
super.initState();
futureCountries = fetchCountries();
}
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(8.0),
child: FutureBuilder(
future: futureCountries,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
children: [
TextField(),
SizedBox(height: 10.0),
Expanded(
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
final List<String> _countriesAllArgs = [
NumberFormat('#,###,###', 'en_US').format(snapshot.data[index].cases),
NumberFormat('#,###,###', 'en_US').format(snapshot.data[index].todayCases),
NumberFormat('#,###,###', 'en_US').format(snapshot.data[index].active),
NumberFormat('#,###,###', 'en_US').format(snapshot.data[index].deaths),
NumberFormat('#,###,###', 'en_US').format(snapshot.data[index].todayDeaths),
NumberFormat('#,###,###', 'en_US').format(snapshot.data[index].recovered),
NumberFormat('#,###,###', 'en_US').format(snapshot.data[index].critical)
];
return Card(
child: Padding(
padding: EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
snapshot.data[index].country,
style: TextStyle(
fontSize: 18.0,
color: Colors.grey[600],
),
),
SizedBox(height: 6.0),
Text(
'countries_all',
style: TextStyle(
fontSize: 14.0,
color: Colors.grey[800],
),
).tr(args: _countriesAllArgs),
],
),
)
);
}
),
)
],
);
}
return Center(
child: CircularProgressIndicator(),
);
},
)
);
}
}
Make sure to keep the loaded data in a parent widget, not in the widget your switching.
Have you considered using the BLOC framework?
In that case, you could nicely sepearte Business Logic from UI code and keep the loaded data in the bloc.
In detail have a blocProvider on top, wrapping your app.
https://bloclibrary.dev/#/flutterbloccoreconcepts?id=blocprovider
Alternatively, but be carefull with the handling though, you can just create an object, anywhere outside of any widget, and access it from anywhere.
class Data {
List<String> stringsLoadedFromWeb;
}
Data data = Data();
// from anywhere else, where you import the above file
data.stringsLoadedFromWeb = ...
Related
I am new to programming and while i was trying to create a small TODO app, i was able to save the data into cloud firestore but the problems ocurred when i tried to retrieve the data using Streambuilder. I was following old tutorials before null safety , so i suspect that issues are regarding the null safety.
The code works without any errors in android studio but the data from firestore can't be retrieved.
The code is as follows:
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class AddTODOlist extends StatelessWidget {
static String id = 'add_todolist';
final TextEditingController _controller = TextEditingController();
void _addUser(){
FirebaseFirestore.instance.collection("Todos").add({"title" : _controller.text});
_controller.text = "";
}
Widget _buildList(QuerySnapshot? snapshot){
return ListView.builder(
itemCount: snapshot!.docs.length,
itemBuilder: (context, index){
final doc = snapshot.docs[index];
final map = (doc.data()as dynamic)['title'];
return ListTile(
title: Text(map,style: TextStyle(color: Colors.black),),
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Loan System',),
centerTitle: true,
),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Row(
children: [
Expanded(
child: TextField(
controller: _controller,
decoration: InputDecoration(
hintText: 'Add new user',
),
),
),
TextButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(Colors.blue),
),
onPressed:(){
_addUser();
},
child: Text('Add',
style: TextStyle(
color: Colors.white,
),),
),
],
),
StreamBuilder<QuerySnapshot?>(
stream: FirebaseFirestore.instance.collection('todos').snapshots(),
builder: (context, snapshot){
if(!snapshot.hasData) return LinearProgressIndicator();
else {
return Expanded(
child: _buildList(snapshot.data),
);
}
}
),
],
),
),
),
);
}
}
You have an error in the spelling of the collection name. Remember that Firestore is case sensitive
Todos vs todos
FirebaseFirestore.instance.collection("Todos").add({"title" : _controller.text});
and here:
stream: FirebaseFirestore.instance.collection('todos').snapshots(),
Let me know if this does not help
I implement to add to cart functionality items added into cart successfully but the number of count in the cart badge is not updated when I reload dart page than the number of count updates.can anyone help me?
I implement to add to cart functionality items added into cart successfully but the number of count in the cart badge is not updated when I reload dart page than the number of count updates.can anyone help me?
This is my Homepage.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:badges/badges.dart';
import 'package:hospital/BestDeatProducts/best_deal_product_page.dart';
import 'package:hospital/CartPage/pages/cartPage.dart';
import 'package:hospital/Drawer/dropdown_menu.dart';
import 'package:hospital/FirstSection/carousel.dart';
import 'package:hospital/Drawer/drawercontent.dart';
import 'package:hospital/FloatingActionButton/ConsultWithDoctor/consult_with_doctor.dart';
import 'package:hospital/MedicineCateory/medicine_category_page.dart';
import 'package:hospital/SecondSection/second_page.dart';
import 'package:hospital/ThirdSection/third_page.dart';
import 'package:hospital/TrendingProducts/trending_product_page.dart';
import 'package:hospital/constant.dart';
import 'package:hospital/customApiVariable.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'No Internet/connectivity_provider.dart';
import 'No Internet/no_internet.dart';
import 'package:http/http.dart' as http;
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
SharedPreferences loginData;
// late String username;
Future getUsername() async {
loginData = await SharedPreferences.getInstance();
setState(() {
// print("uname" + uname.toString());
print("dddpppuu1 : responceData_un" +
loginData.getString('responceData_un').toString());
print("dddpppuu2 : responceData_ue" +
loginData.getString('responceData_ue').toString());
print("dddpppuu3 : responceData_status" +
loginData.getString('responceData_status').toString());
String responceData_uid =
loginData.getString('responceData_uid').toString();
fetchData(responceData_uid);
});
}
var response;
var addToCartApi;
#override
void initState() {
// TODO: implement initState
//
super.initState();
Provider.of<ConnectivityProvider>(context, listen: false).startMonitering();
// for loading
getUsername();
}
fetchData(String argResponceData_uid) async {
var api = Uri.parse(
'$ecommerceBaseUrl/addToCartApi.php?a2rTokenKey=$a2rTokenKey&action=addToCartList&uid=${argResponceData_uid}');
print('cartpage' + api.toString());
response = await http.get(api);
print("Carousel" + response.body);
addToCartApi = jsonDecode(response.body);
print('addToCartApi' + addToCartApi['total'].toString());
print('totalPriceAfterOffer' + totalPriceAfterOffer.toString());
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: kGreen,
title: Text(
"BK Arogyam",
style: TextStyle(fontStyle: FontStyle.italic),
),
actions: [
response != null
? Badge(
position: BadgePosition.topEnd(top: 3, end: 18),
animationDuration: Duration(milliseconds: 300),
animationType: BadgeAnimationType.slide,
badgeContent: Text(
addToCartApi['total']['num'].toString(),
style: TextStyle(color: Colors.white),
),
child: IconButton(
icon: Icon(Icons.shopping_cart),
padding: EdgeInsets.only(right: 30.0),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Cartpage()),
);
}),
)
: IconButton(
icon: Icon(Icons.shopping_cart),
// onPressed: () => print("open cart"),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Cartpage()),
);
},
),
DropDownMenu(),
],
),
floatingActionButton: FloatingActionButton(
backgroundColor: kGreen,
onPressed: () => Navigator.push(context,
MaterialPageRoute(builder: (context) => ConsultWithDoctor())),
tooltip: 'Consult With Doctor',
child: Container(
child: Image(
image: AssetImage(
"assets/icons/cwd.png",
),
color: Colors.white,
width: 40,
height: 40,
),
),
),
drawer: Drawer(
child: DrawerContent(),
),
body: pageUI());
}
Widget pageUI() {
return Consumer<ConnectivityProvider>(
builder: (consumerContext, model, child) {
if (model.isOnline != null) {
return model.isOnline
? ListView(
children: [
Carousel(),
SizedBox(
height: 10.0,
),
MedicineCategoryPage(),
SizedBox(
height: 10.0,
),
SecondPage(),
SizedBox(
height: 10.0,
),
ThirdPage(),
SizedBox(
height: 10.0,
),
TrendingProductPage(),
SizedBox(
height: 16.0,
),
BestDealProductPage(),
SizedBox(
height: 10.0,
),
],
)
: NoInternet();
}
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
},
);
}
}
You can use the change notifier provide by provider package.
And watch the video on how to use, exactly for ur use case search YouTube change notifier provider by the growing developer
Hope it helps š
You can use provider(provider: ^5.0.0) or Getx(get: ^4.1.4) to handle this kind of case.
There are lots of examples are available for GetX and Provider.
If you don't want to use any of them, Then store your cart/badge count to tempCartCount variable(Example: int cartCount = 0) and set it to the badge count instead of "addToCartApi['total']['num'].toString()" , Make sure to setState on update/addCart Item.
Here I provide a simple example of how to update count on appBar.
if you want to change from any other screen make cartCount to global otherwise you can set it local/private.
import 'package:badges/badges.dart';
import 'package:flutter/material.dart';
class UpdateCountExample extends StatefulWidget {
#override
_UpdateCountExampleState createState() => _UpdateCountExampleState();
}
int cartCount = 0;
class _UpdateCountExampleState extends State<UpdateCountExample> {
List<String> cartArray = [];
#override
void initState() {
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
setState(() {
cartCount = 0;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("App Bar"),
actions: [
Padding(
padding: const EdgeInsets.only(right: 18.0, top: 5.0),
child: Badge(
badgeContent: Text(cartCount.toString()),
child: Icon(Icons.add_shopping_cart),
),
)
],
),
body: Container(
alignment: Alignment.center,
padding: EdgeInsets.all(20),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"Add item in cart",
textAlign: TextAlign.center,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18, decoration: TextDecoration.none, color: Colors.black),
),
SizedBox(
height: 20,
),
InkWell(
onTap: () {
setState(() {
cartArray.add("value ${cartArray.length}");
cartCount = cartArray.length;
});
},
child: Container(
padding: const EdgeInsets.all(10.0),
color: Colors.amber,
child: Text(
"Add Item",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 15, decoration: TextDecoration.none, color: Colors.black),
),
),
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: cartArray.length,
itemBuilder: (context, index) {
return Text(
cartArray[index],
style: TextStyle(fontSize: 20, color: Colors.black),
);
}),
)
],
),
),
);
}
}
I have used StreamBuilder to update cart items instantly.
You can use the code from this post
How to use Streambuilder in flutter
I am able to fetch data from API and I can show it in the List View, but i want to show the first card as the latest updated data.
I tried to use the Reverse property of List View Builder, it some how solve my problem but gave rise to another problem. Now i need to scroll upward in order to see latest updated data.
Help me through it
I just want to show the latest updated data at the top and then scroll down to see another data.
Please Help Me.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class PromotersDetails extends StatefulWidget {
final String url,title;
PromotersDetails({Key key, #required this.url, #required this.title}) : super(key: key);
#override
_PromotersDetailsState createState() => _PromotersDetailsState(url,title);
}
class _PromotersDetailsState extends State<PromotersDetails> {
fetchSelfies() async {
var url1;
url1 = await http.get(Uri.parse(
url));
var res = json.decode(url1.body);
print(res);
return json.decode(url1.body)['selfies'];
}
String url,title;
_PromotersDetailsState(this.url, this.title);
#override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width * 0.6;
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
centerTitle: false,
title: Text(
title,
style: TextStyle(fontSize: 25.0, color: Colors.white),
),
elevation: 0.0,
backgroundColor: Colors.green,
),
body: FutureBuilder(
future: fetchSelfies(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasError) {
return Center(
child: Text(snapshot.error.toString()),
);
}
if (snapshot.hasData) {
return ListView.builder( **// List View Builder**
reverse: false,
cacheExtent: 10000.00,
itemCount: snapshot.data.length,
padding: EdgeInsets.all(8),
itemBuilder: (BuildContext context, int index) {
return Row(
children: [
Container(
height: 120,
alignment: Alignment.center,
child: Container(
height: 120,
width: 120,
child: Card(
child: Image.network(snapshot.data[index]['image']),
),
),
),
Expanded(
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 10,
),
Row(
children: [
Text(
"Time: ",
style: TextStyle(color: Colors.black),
),
Text(
snapshot.data[index]['time'],
style: TextStyle(color: Color(0xff868597)),
),
],
),
Container(
height: 50,
child: Text(
snapshot.data[index]['location'],
style: TextStyle(color: Color(0xff868597)),
),
),
],
),
),
),
],
);
},
);
}
return Center(
child: CircularProgressIndicator(),
);
})
);
}
}
If you just need to sort the API response backwards, you can use the reverse property of ListView.
ListView.builder(
reverse: true,
...
),
If the way you're populating the ListView is by appending new data, then it's better to store the data on a List then do sort/reversed. Though the sorting should be best done at the backend instead of passing the burden to the client app.
How can I disable a button, in this case a FAB(Floating Action Button), and prevent the user adding more items to the list because he is exceeding the limit and showing a message? I'm using a FutureBuilder and a ListView.builder, after the user adds 3 item to the list, I want to disable the FAB and prevent the user to add more items to the list and showing some sort of notification/message/floating over button message to the user that he is exceeding the limit of 3 items per list. Here is the code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'screens/add_items_screen.dart';
import 'components/items_list.dart';
class ItemScreen extends StatelessWidget {
static const String id = 'item_screen';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
iconTheme: IconThemeData(
color: Colors.grey[600],
),
),
/// I want to disable this button after the limit of 3 items in the list view
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.grey,
child: Icon(Icons.add),
onPressed: () {
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) => SingleChildScrollView(
child: Container(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: AddItemScreen(),
)));
},
),
body: SafeArea(
child: SingleChildScrollView(
child: Container(
padding: EdgeInsets.all(20.0),
color: Colors.grey[100],
child: Container(
height: 800,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Item List Display',
style: TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.w700,
),
),
SizedBox(
height: 20.0,
),
Expanded(
child: Column(
children: [
/// Here is where the items are rendered as a list
Expanded(child: ItemList()),
],
),
),
],
),
),
),
),
),
);
}
}
The Item list component:
import 'package:flutter/material.dart';
import 'common/api/api_caller.dart';
import 'utilities/item_api_helper.dart';
import 'models/item.dart';
import 'stores/item_store.dart';
import 'dart:async';
import 'package:provider/provider.dart';
class ItemList extends StatefulWidget {
#override
_ItemList createState() => _ItemList();
}
class _ItemList extends State<ItemList> {
Future<HTTPResponse<List<ItemData>>> _getItemList() async {
var _itemData = await APICaller.instance.getItems();
var provider = Provider.of<ItemDatStore>(context, listen: false);
provider.setItemList(_itemData.data, notify: false);
return _itemData;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: FutureBuilder<HTTPResponse<List<ItemData>>>(
future: _getItemList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Consumer<ItemDataStore>(
builder: (context, itemData, child) {
return ListView.builder(
itemCount: itemData.itemList.length,
itemBuilder: (context, index) {
ItemData items =
itemData.getItemByIndex(index);
return Card(
child: Container(
padding: EdgeInsets.all(10.0),
child: Text('items.title'),
),
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return Container();
},
),
),
);
}
}
I've tried using an if statement where I can define if(itemData.itemList.length <3) it should return those three items, else {Text('Item limit of 3 is exceeded')} but I'm not sure if this is the right way or if I defined it right since I put it in the Item List component and I need to put it in the Item Screen. Thanks in advance for you help!
You can wrap your Floating action button with Visibility it hides and not woking anymore :)
Visibility(
visible: items.length > 3,
child : FAB here,
),
You can disable the FAB like this
onPressed: items.length < 3? addItemToList : null;
and addItemToList is
void addItemToList(){
// Do Something here
}
I am new to flutter and I have a program that shows several cards and I have a question about how to make a card finder, I am using this code:
_card(
String phrase,
) {
return SliverToBoxAdapter(
child: Card(
margin: EdgeInsets.only(right: 50, left: 50, top: 20),
child: InkWell(
onTap: () {},
child: Column(children: <Widget>[
SizedBox(height: 15.0),
Padding(
padding: EdgeInsets.only(left: 15, right: 15),
child: Text(
phrase,
style: TextStyle(
fontFamily: 'Circular',
fontSize: 17.0,
color: Colors.grey[800]),
),
),
SizedBox(height: 15.0),
]),
),
),
);
}
and I use this to make the various cards:
return Scaffold(
body: Stack(children: [
CustomScrollView(physics: BouncingScrollPhysics(), slivers: <Widget>[
_card('Abrir'),
_card('Alzar'),
_card('Aprender'),
_card('Caer'),
_card('Cerrar'),
_card('Cocinar'),
_card('Correr'),
_card('Cortar'),
_card('EnseƱar'),
_card('Estar'),
_card('Hay'),
_card('Levantarse'),
_card('Mirar'),
_card('Oler'),
_card('Saltar'),
_card('Sentar'),
_card('Ser'),
_card('Tocar'),
_card('Tomar'),
_card('Tropezar'),
]),
]),
);
I really appreciate any help, thanks
Here is a solution using:
hooks_riverpod for State Management
fuzzy for fuzzy search
Full source code for easy copy-paste
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:fuzzy/fuzzy.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
void main() {
runApp(
ProviderScope(
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: HomePage(),
),
),
);
}
class HomePage extends HookWidget {
#override
Widget build(BuildContext context) {
final phrases = useProvider(filteredPhrasesProvider);
return Scaffold(
body: ListView(
physics: BouncingScrollPhysics(),
children: [
TextField(
autofocus: true,
textAlignVertical: TextAlignVertical.center,
decoration: InputDecoration(
prefixIcon: Icon(Icons.search),
hintText: 'Search',
),
onChanged: (value) =>
context.read(searchTermsProvider).state = value,
),
...phrases.map((phrase) => _Card(phrase: phrase)).toList(),
],
),
);
}
}
class _Card extends StatelessWidget {
final String phrase;
const _Card({
Key key,
this.phrase,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Card(
margin: EdgeInsets.all(10.0),
child: InkWell(
onTap: () {},
child: Padding(
padding: EdgeInsets.all(15.0),
child: Text(
phrase,
style: TextStyle(
fontFamily: 'Circular',
fontSize: 17.0,
color: Colors.grey[800],
),
),
),
),
);
}
}
final searchTermsProvider = StateProvider<String>((ref) => '');
final phrasesProvider = Provider<List<String>>(
(ref) => [
'Abrir',
'Alzar',
'Aprender',
'Caer',
'Cerrar',
'Cocinar',
'Correr',
'Cortar',
'EnseƱar',
'Estar',
'Hay',
'Levantarse',
'Mirar',
'Oler',
'Saltar',
'Sentar',
'Ser',
'Tocar',
'Tomar',
'Tropezar',
],
);
final filteredPhrasesProvider = Provider<List<String>>((ref) {
final phrases = ref.watch(phrasesProvider);
final searchTerms = ref.watch(searchTermsProvider).state;
return searchTerms.isEmpty
? phrases
: Fuzzy<String>(phrases, options: FuzzyOptions(threshold: .4))
.search(searchTerms)
.map((result) => result.item)
.toList();
});
First you must change the logic of your code, create a List and then create the cards, so that the search engine works with the list
Create list:
final List<String> actions = ["Abrir", "Alzar", "EnseƱar", "Sentar", "Mirar"];
Next, use List.generate or List.builder to create cards in the slivers
return Scaffold(
body: Stack(children: [
CustomScrollView(
physics: BouncingScrollPhysics(),
slivers: List.generate(actions.length, (i) => _cards(actions[i])
),
]),
);
Finally in your seacher, use this logic, the "contains" is optional, you can change the logic in the if
void search(String data) {
for(int i = 0; i < actions.length; i++) {
if(actions[i].contains(data)) {
print(actions[i]);
// In your case show card or add in another list to show after
}
}
}