EDIT: Im retarded, i figured it out
used the widget. to get access to the class variable
swapped out the Text("fsfd); for my list variable resulting in
child: Consumer<WidgetDataNotify>(
builder: (context,datatonotify,child){
print("value == ${datatonotify.value}");
return FuctionListSet[datatonotify.value];
},
child: Text("${provtest.value}"),
i've been following
Flutter provider state not updating in consumer widget
to try and understand the process along with the documentation and videos ect ect.
and i cannot figure out how to ensure im using the same instance of a provider across classes (dart files)
My program is composed of widgets and a radiolist that when it's clicked will update the provider to it's index value which then from a list in my main (thats wrapped) in a consumer will update depending on the interger affecting the list
provider file:
class WidgetDataNotify extends ChangeNotifier {
int value=0;
//int get grabvalue => value;
// Widget SelectedWidget=SingleButtonMovementFunction();
// Widget get pickedWidget =>SelectedWidget=FuctionListSet[value];
void UpdateWidgetList(int picker){
value = picker;
print("updated value to $value");
notifyListeners();
}
}
RadioList code: Problem here is i dont know how to communicate that provider value i've passed in
class RadioListBuilder extends StatefulWidget {
final int num;
static int value=0;
final WidgetDataNotify provider;
const RadioListBuilder({Key key, this.num,this.provider}) : super(key: key);
#override
RadioListBuilderState createState() {
return RadioListBuilderState();
}
}
class RadioListBuilderState extends State<RadioListBuilder> {
static int test;
int _value;
#override
Widget build(BuildContext context) {
return ListView.builder(
itemBuilder: (context, index) {
return Column(
children: [
Container(
height: 60,
width: MediaQuery.of(context).size.width,
color: Colors.brown[800],
child: RadioListTile(
selectedTileColor: Colors.amber,
activeColor: Colors.amber,
tileColor: Colors.black54,
value: index,
groupValue: _value,
onChanged: (x) => setState((){
_value = x;
///provider.UpdateWidgetList(x); /// providing the value to the provider
///ideally would call the function
Activated_Function_Selected=index;
print("Activated fuction is indexed at $Activated_Function_Selected and it's name is == ${FunctionList[index].characters}");
}),
title: Text("${FunctionList[index]}",style: TextStyle(color: Colors.white,fontSize: 18,),softWrap: true,maxLines: 2,),
),
),
Divider(color: Colors.black,height: 10,thickness: 10,),
],
);
},
itemCount: widget.num,
);
}
}
Start of my main function has this to ensure the context would be the same
#override
Widget build(BuildContext context) {
WidgetDataNotify provtest = Provider.of<WidgetDataNotify>(context,listen: true);
return Scaffold(
appBar: AppBar(
i pass this on into my radio list
Expanded(
flex:2 ,
child: Container(
color: Colors.deepPurple,
child: RadioListBuilder(num: FunctionList.length,provider: provtest,),
),
),
then i have my consumer listen out for it
Expanded(
flex: 3,
child: Container(
color: Colors.orangeAccent,
//
// child: Selector<WidgetDataNotify, int>(
// selector: (context,model) => model.value,
// builder: (context,value,child){
// print("accesed value==$value");
// return Center(
// child: FuctionListSet[value],
// );
// },
// child: Text("AAAAAAAAAAAAAAAAAAAAAAAAAAAA"),
// ),
child: Consumer<WidgetDataNotify>(
builder: (context,datatonotify,child){
print("value == ${datatonotify.value}");
testA=datatonotify.value;
print("test == $testA");
return Text("faf");
},
child: Text("${provtest.value}"),
),
),
//),),
),
Related
i'm trying to store a value coming from the selected choice chip in a variable called etatLabel, so I can send it alongside other values in a form. The problem is that once I first do the selection, the value gets stored successfully, but then the variable's value do not get settled to "" again. Which means if I hit the add button again it will add the value from the choice chip that was last selected.
here is my code:
String etatLabel = "";
class MyOptions extends StatefulWidget {
final ValueNotifier<String?> notifier;
const MyOptions({super.key, required this.notifier});
#override
State<MyOptions> createState() => _MyOptionsState();
}
class _MyOptionsState extends State<MyOptions> {
static const String failedString = "Echec";
int? _value;
List<String> items = ["Succés", failedString];
#override
Widget build(BuildContext context) {
return Column(
children: [
Wrap(
children: List<Widget>.generate(
items.length,
(int index) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: Container(
width: 100,
child: ChoiceChip(
backgroundColor: Colors.deepPurple,
selectedColor: _value == 1 ? Colors.red : Colors.green,
label: Align(
alignment: Alignment.center,
child: Text(
'${items[index]}',
style: TextStyle(color: Colors.white),
),
),
selected: _value == index,
onSelected: (bool selected) {
setState(() {
_value = selected ? index : null;
etatLabel = items[index];
});
widget.notifier.value = items[index];
},
),
),
);
},
).toList(),
),
],
);
}
}
I couldn't find a way to solve this, and I appreciate your suggestions/help.
I need help with flutter build management. My Goal is to rebuild my side navigation bar with the SmallSideMenu() or the opposite SideMenu().
Do you have an idea how I can trigger the Build process of my LargeView widget, so that it's rebuilt with the correspondent SideMenu?
The button is defined like this:
IconButton(
onPressed: () {
checkState();
},
icon: HeroIcon(
HeroIcons.arrowNarrowRight,
size: 16.0,
),
),
The value of the sideMenuOpen variable and function is set globally;
checkState() {
if (sideMenuOpen == true) {
sideMenuOpen = false;
} else {
sideMenuOpen = true;
}
}
the SideMenu is defined here.
class LargeView extends StatefulWidget {
const LargeView({
Key? key,
}) : super(key: key);
#override
State<LargeView> createState() => _LargeViewState();
}
class _LargeViewState extends State<LargeView> {
#override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(
child: SizedBox(
width: 100,
child: sideMenuOpen ? SideMenu() : SmallSideMenu(),
),
),
Expanded(
flex: 10,
child: Container(
width: double.infinity,
padding: const EdgeInsets.all(20.0),
color: greyColor,
child: Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15.0)),
child: localNavigator())),
),
)
],
);
}
}
make sideMenuOpen a state in stateful widget and use setState as
checkState() {
if (sideMenuOpen == true) {
setState((){
sideMenuOpen = false;
});
} else {
setState((){
sideMenuOpen = true;
});
}
}
if you want to keep state (open/close) of navigation bar globally for that use some state management like provider instead of using global function.
You can use ValueNotifier instead of single bool. And to update UI it can be used on ValueListenableBuilder.
final ValueNotifier<bool> sideMenuOpen = ValueNotifier(false);
And
child: SizedBox(
width: 100,
child: ValueListenableBuilder<bool>(
valueListenable: sideMenuOpen,
builder: (context, value, child) => value
? SideMenu(),
: SmallSideMenu(),
),
),
And change value like
sideMenuOpen.value = true;
I have an appBar with one icon, this icon has a number which have to be updated after I change somethings in the app. I was using notifyListeners(), but this command is cleaning a list I need so I have to update that number in appbar without notifyListeners().
I tried to call SetState but it doesn't worked.. is there a way to update only the app bar?
In provider which I include more items:
void setBadge() {
_number = number;
notifyListeners(); // this line I dropped out
}
App bar Icon widget:
class AppBarWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Consumer<Cart>(
child: IconButton(
icon: Icon(Icons.shopping_bag_outlined),
onPressed: () async {
Navigator.of(context).pushNamed(ROUTE_CART);
},
),
builder: (_, cart, child) {
return BagBadge(
child: child,
value: cart.isEmpty ? '' : cart.number.toString(),
);
},
);
}
}
BagBadge:
class BagBadge extends StatelessWidget {
final Widget child;
final String value;
BagBadge({
#required this.child,
#required this.value,
});
#override
Widget build(BuildContext context) {
return Stack(
alignment: Alignment.center,
children: <Widget>[
child,
if (value != '')
Positioned(
right: value.length < 4 ? 20 : 10,
top: 30,
child: Container(
padding: EdgeInsets.all(value.length < 4 ? 2 : 3),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Theme.of(context).accentColor
),
constraints: BoxConstraints(
minHeight: 16,
minWidth: 16,
),
child: Text(
value,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
)
],
);
}
}
Edit: this would work only if you use a stateful widget. With stateless widget the change won't be shown.
You can try something like this:
import 'package:flutter/material.dart';
class AppBarWidget extends StatefulWidget {
#override
_AppBarWidgetState createState() => _AppBarWidgetState();
}
class _AppBarWidgetState extends State<AppBarWidget> {
int _appBarValue = 0;
#override
Widget build(BuildContext context) {
return Consumer<Cart>(
child: IconButton(
icon: Icon(Icons.shopping_bag_outlined),
onPressed: () async {
Navigator.of(context).pushNamed(ROUTE_CART);
},
),
builder: (_, cart, child) {
return BagBadge(
child: child,
value: _appBarValue == 0 ? '' : '$appBarValue',
);
},
);
}
}
setAppBarValue(int value) {
setState(() { _appBarValue = value; });
}
}
Whenever you want to change the value, just call the setAppBarValue() function.
I am trying to create a search function in my app and I am getting many issues due to type conversions. The search is to be done in a ListView of many entries and for that I created a class named ListEntries.
This is the code of the screen that makes the search in this list of Entries:
import 'package:flutter/material.dart';
import 'listentries.dart';
class searchScreen extends StatefulWidget {
final String searchTerm;
searchScreen({this.searchTerm});
#override
_SearchScreenState createState() => new _SearchScreenState();
}
class _SearchScreenState extends State<searchScreen> {
#override
Widget build(BuildContext context) {
final widgetElements = new ListEntries(); // From listentries.dart
var searchedItems = widgetElements;
String entry;
entry = searchedItems.toString();
final duplicateItems = List<String>.generate(10000, (i) => "Item $i");
var items = List<String>();
void filterSearchResults(String query) {
List<ListEntries> dummySearchList = List<ListEntries>();
dummySearchList.addAll(searchedItems);
if (query.isNotEmpty) {
List<ListEntries> dummyListData = List<ListEntries>();
dummySearchList.forEach((item) {
if (item.contains(query)) {
dummyListData.add(item);
}
});
setState(() {
items.clear();
items.addAll(dummyListData);
});
return;
} else {
setState(() {
items.clear();
items.addAll(duplicateItems);
});
}
}
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
title: Text(
"Search your term",
style: TextStyle(fontSize: 20),
),
),
body: Container(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
onChanged: (value) {
filterSearchResults(value);
},
decoration: InputDecoration(
labelText: 'Search',
hintText: 'Search your term',
suffixIcon: Icon(Icons.search),
border: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(25.0)))),
)),
Expanded(
child: searchedItems,
),
],
),
),
// bottomNavigationBar: bannerAd,
);
}
}
The Type LisEntries is defined in this other file (listentries.dart):
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'destination.dart';
import 'package:insurance_dictionary/facebook_code.dart';
import 'dart:io';
class ListEntries extends StatefulWidget {
ListEntries({Key key}) : super(key: key);
#override
ListEntriesState createState() => ListEntriesState();
}
class ListEntriesState extends State<ListEntries> {
bool isFirstUse = true;
int numUses = 0;
int cycle = 5;
//static FutureBuilder<String> listOfEntries;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Center(
child: FutureBuilder(
future:
DefaultAssetBundle.of(context).loadString('assets/data.json'),
builder: (context, snapshot) {
var entries = json.decode(snapshot.data.toString());
//listOfEntries = entries;
return ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
var entrada = entries[index];
return Container(
margin: EdgeInsets.symmetric(vertical: 2.0),
color: Colors.transparent,
width: MediaQuery.of(context).size.width,
height: 60,
child: RaisedButton(
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
onPressed: () {
if ((isFirstUse) || (numUses % cycle == 0)) {
loadInterstitialAd();
sleep(Duration(milliseconds: 100));
showInterstitialAd();
isFirstUse = false;
numUses++;
} else {
numUses++;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Destination(
entry: entrada['Entry'],
definition: entrada['Definition'],
),
),
);
}
},
color: Colors.blue[900],
child: Text(
entrada['Entry'],
style: TextStyle(
color: Colors.white,
fontFamily: 'Raleway',
fontSize: 18.0,
),
),
),
);
},
itemCount: entries == null ? 0 : entries.length,
);
},
),
),
),
);
}
}
The errors that I am getting are located in these steps in the search_entries.dart file:
dummySearchList.addAll(searchedItems);
items.addAll(dummyListData);
Both errors say: "The argument type 'List' can't be assigned to the parameter type 'Iterable'."
There is another error in this step:
if (item.contains(query)) {...}
In this case, the error says: "The method 'contains' isn't defined for the type 'ListEntries'."
I have been fighting with this kind of errors for several days. Could you give a good advice?
Thanks.
See your declarations:
List<ListEntries> dummyListData = List<ListEntries>();
var items = List<String>();
Both of them are a List type but store different types: String and ListEntries
For second error, same problem with types. ListEntries is not an Iterable type but a Widget.
That happens because you are calling .contains directly on item which is an object of type (class) ListEntries. The method .contains should be used on an iterable. You can define any Iterable inside ListEntries and them call .contains in it:
item.myIterable.contains(query)
I have tried to retrieve data from a specific child from Firebase RTDB. The problem is that the following error appears (I don't use int):
Unhandled Exception: type 'String' is not a subtype of type 'int' of 'index'
The log says that the error appears here
DATA[individualKey]['name'],
DATA[individualKey]['picture'],
DATA[individualKey]['price'],
DATA[individualKey]['id'],
DATA[individualKey]['brand'],
DATA[individualKey]['category'],
// DATA[individualKey]['feature'],
// DATA[individualKey]['sale'],
// DATA[individualKey]['colors'],
// DATA[individualKey]['sizes'],
DATA[individualKey]['quantity'],
The code that I am going to show, I use it on another screen with minimal changes and it works
but in the current one that I use it doesn't work
class PostsDetails extends StatefulWidget {
final value2;
PostsDetails({Key key,#required this.value2}) : super(key : key);
#override
_PostsDetailsState createState() => _PostsDetailsState(value2);
}
class _PostsDetailsState extends State<PostsDetails> {
final value2;
_PostsDetailsState(this.value2);
List<Posts>postsList = [];
#override
void initState() {
// TODO: implement initState
super.initState();
DatabaseReference postsRef = FirebaseDatabase.instance.reference().child("Product").child("Shoes").child("Nike").child(value2);
postsRef.once().then((DataSnapshot snap)
{
var KEYS = snap.value.keys;
var DATA = snap.value;
postsList.clear();
for(var individualKey in KEYS)
{
Posts posts = new Posts
(
DATA[individualKey]['name'],
DATA[individualKey]['picture'],
DATA[individualKey]['price'],
DATA[individualKey]['id'],
DATA[individualKey]['brand'],
DATA[individualKey]['category'],
// DATA[individualKey]['feature'],
// DATA[individualKey]['sale'],
// DATA[individualKey]['colors'],
// DATA[individualKey]['sizes'],
DATA[individualKey]['quantity'],
);
postsList.add(posts);
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.1,
backgroundColor: Colors.red,
title: InkWell(
onTap: (){
Navigator.push(context, MaterialPageRoute(builder: (context)=> new HomePage()));
},
child: Text("SHOP APP")),
actions: <Widget>[
new IconButton(icon: Icon(Icons.search, color: Colors.white,), onPressed: (){}),
],
),
body: new ListView(
children: <Widget>[
new Container(
child: postsList.length == 0 ? new Text("No Available"):new ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: postsList.length,
itemBuilder: (_, index){
new Container(
height: 300.0,
child: GridTile(
child: Container(
color: Colors.white,
// child: Image.network(postsList[index].picture),
),
footer: new Container(
color: Colors.white70,
child: ListTile(
leading: new Text(postsList[index].name,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0),),
title: new Row(
children: <Widget>[
Expanded(
// child: new Text("\$"+postsList[index].price, style: TextStyle(fontWeight: FontWeight.bold, color: Colors.red),)
),
],
),
),
),
),
);
})
),
]
)
);
}
}
postslist.length retrieves 0.
final value2 its a child ID. I have verified that it is received well from the previous screen
and if value2 is not used, data will not be retrieved
Posts Class:
class Posts
{
String name;
String picture;
String price;
String id;
String brand;
String category;
String quantity;
// List<> colors;
// List<> sizes;
// bool feature;
// bool sale;
Posts(this.name, this.picture, this.price, this.id, this.category,this.brand,this.quantity);
}
How could it be solved or is there some way to retrieve a specific child? I know how to show a list but not of a specific child thanks
i fixed it, by some reason the code
postsList.length == 0 ? new Text("No Available"):
was the problem so i deleted it