I created a method below to loop through my list because I don't want to write again and again of these few lines but the parameter I pass to the Text widget and also value argument are error and it said Invalid constant value. How can I achieve this? I'm new to flutter. Please help me.
PopupMenuItem _createMenuItems(final String a) {
return const PopupMenuItem(
value: a,
child: Text(a),
);
}
Have your tried simply returning PopupMenuItem without const modifier like below?
PopupMenuItem _createMenuItems(final String a) {
return PopupMenuItem(
value: a,
child: Text(a),
);
}
Related
I want to make an editable TextWidget in flutter but I don't really know how to go around it, I did some research, but still can't find a good solution.
Here's my sample code below.
I have a variable called
int qty = 1;
and so I called the variable in TextWidget
Column(
children: [
Text(
"${qty}",
style: TextStyle(),
)
],
),
I want to have these features that make user tab on the value to change it if they want, upon tap, a pop-up dialog will show to give the user the ability to change the existing value to whatever the user wants.
Please if anyone knows how, please help.
You will need a statfull widget to call setState and make the UI update with the new value stored in your qty variable. (I'am assuming that you are not using any state managment).
I wrote a possible solution for what you need.
Let look into some considerations:
Text will show whatever is in the qty as long we call setState after (or do it inside) we change the value of qty.
You need some widget to detect your tap. If you want to the text be 'clicable' then it should be wraped inside that widget.
The onTap/onPress call back of that widget should show a new widget. For this you can use the already made showDialog() and pass it a Dialog Widget. in here you will put your ui for that.
In some point of that UI you need to introduce the new value. So you can use a simple TextField that will save the introduced value, where you can assign it to qty, without forgetting to call setState! Note that it deal with strings, so you neet to do an int.parse() ou double.parse accordingly to you qty var type.
And I think that's it.
The could be other ways of doing it. This is a good and simple approach for your need.
I wrote a piece of code to help or somelse how is trying to do it:
InkWell(
// can be gesture detector, button, etc
onTap: () => showDialog(
context: context,
builder: (context) => Dialog(
child: Container(
color:
Colors.white60, // change it accordingly to you
height: 80, // change it accordingly to you
width: 200, // change it accordingly to you
child: Column(
children: [
const Text('Change your value here'),
TextField(
decoration:
InputDecoration(hintText: qty.toString()),
onChanged: (insertValue) => setState(() {
qty = int.parse(insertValue);
}),
// you can use other callBack function (like onComplete,
// onSaved), wich is more eficient than calling setState eveytime,
// but you have to do the needed adtaptions. Like onSave
// needs a key to call the save function. is easy just google it.
),
],
)),
)),
child: Text(
"${qty}",
),
),
What you are probably looking is a DropdownButton.
You would have something like this:
int qty = 1;
List<int> listOfValues = [1,2,3,4];
and then in your column you would have
DropdownButton<int>(
// This are the list of items that will appear in your dropdown menu.
// items is all the options you want your users to be able to select from,
// and it take a list of `DropdownMenuItem`. So instead of creating a `DropdownMenuItem`
// for each of the items in `listOfValues`, we iterate through it and return
// a `DropdownMenuItem`
items: listOfValues
.map((item) => DropdownMenuItem<int>(
value: item,
child: Text('$item'),
))
.toList(),
value: qty,
onChanged: (value) {
if (value != null) {
setState(() {
qty = value;
});
}
},
),
For more information on DropDownButton, check the following links:
https://api.flutter.dev/flutter/material/DropdownButton-class.html
https://www.youtube.com/watch?v=K8Y7sWZ7Q3s
Note: In a scenario where you want to increase the quantity of an item, like in a shopping cart, maybe having a button increment qty by 1 would be better.
InkWell tile({String? date}) {
return InkWell(
child: SizedBox(
height: 40,
child: ListTile(
title: Text(
date?? 'Null',
style: const TextStyle(fontSize: 16),
),
),
),
I have a tappable List Tile with the title variable 'date' which I will assign later, so I am going to pass this to another file as shown now:
randomParameter: anotherFile(tile()), // might be an error idk
inside file where tile widget will be imported to:
anotherFile(required InkWell tile){
const String today = 'Today';
const String tmrw = 'Tomorrow';
const String week = 'Next Week';
ExpansionTile(children: [tile(date: today), tile(date: tmrw), tile(date: week)]) };////Error!
Error: The expression doesn't evaluate to a function, so it can't be
invoked. The method 'call' isn't defined for the class 'InkWell'.
change anotherFile(required InkWell tile){ to anotherFile(required InkWell Function(string) tile){
The error says that another file doesnt evaluate to a function
For example a function will look like
void someFunction()
{
}
In this case you are adding an expansion tile to a parameter which i assume you are trying to return an ExpansionTile
If you wish to return a widget then you can try writing it like
Widget anotherFile(required InkWell tile){
return ExpansionTile();
}
Now this method will return a wodget of type expansion tile
I'm developing an app and my current task is to implement localization for several languages. Now that I've translated most of it, I need to create a button that I would nest in the app bar that would drop down and offer the different languages.
To that extent, I've followed this tutorial : https://www.youtube.com/watch?v=yX0nNHz1sFo&list=PLyHn8N5MSsgEfPAxCytQDPATDlHwpP5rE&index=3.
Now, since I plan on reusing this button for different pages, I created its own class, so far for good. But when comes time to add the onChanged property that would call the function responsible for language switching, it doesn't work. In fact, I can't call any function at all.
Here's the code snippet:
class LanguageButton extends StatelessWidget {
void changeLanguage(Language lang) {
print(lang.languageCode); //placeHolder
}
Widget build(BuildContext context) {
return DropdownButton(
underline: SizedBox(),
onChanged: (Language lang) {
changeLanguage(lang);
},
icon: Icon(
Icons.language,
color: Colors.white,
),
items: Language.languageList()
.map<DropdownMenuItem<Language>>((lang) => DropdownMenuItem(
value: lang,
child: Row(children: [
Text(lang.flag),
Text(lang.language),
])))
.toList(),
);
}
}
Which returns the error The argument type 'void Function(Language)' can't be assigned to the parameter type 'void Function(Language?)?'..
I've tried replacing by onChanged: ()=>print('hello') but it's still not working with a similar error message.
Any help is appreciated!
The onChanged method of a DropdownButton (see the documentation) is a ValueChanged<T?>?. That means it can itself be null (for example if you don't set it at all), but if you set it, you need to set it to a method with the signature void Function(T?). Your method does not confirm to that signature, because it does not allow nulls.
Change yourmethod to:
void changeLanguage(Language? lang) {
and either pass it directly:
onChanged: changeLanguage,
or make the anonymous method have a nullable parameter, too:
onChanged: (Language? lang) {
changeLanguage(lang);
},
I have been trying to get an clear explanation for what : means in dart.
As far as I can tell it seems so be some kind of operator , but I can't get a clear cut explanation of what exactly it does.
I understand that it gets used to so assign stuff to other stuff , but I am unsure of the specifics.
I have tried googling it , no luck.
I have tried searching through the dart documentation.
https://dart.dev/guides/language/language-tour#operators
I know that it gets used as part of conditional expressions like here:
https://dart.dev/guides/language/language-tour#conditional-expressions
Here are examples of how it gets used:
Example 1 :
class someBloc extends Bloc<someEvent, someState> {
someBloc() : super(someState.initial());
}
Example 2 :
class someClass {
final String requestType;
final String name;
factory someClass.fromJson(Map<String, dynamic> json) {
return SomeClass(
requestType: json['Type'],
name: json['Name']);
}
}
In examples 1 & 2:
The : is used to set a named parameter. For example, let's say I want to create a Card widget. The card widget optionally takes a named parameter called elevation. Therefore, I can do this:
Card(
elevation: 4.0,
)
Another way : is used is for writing quick conditional expressions.
final String isMyListEmpty = myList.isEmpty ?? 'Yes, the list is empty' : 'No, the list is not empty';
In this example, our condition is myList.isEmpty. If this condition is true, the first expression after ?? is returned. Else, if the condition is false, the expression after the : is returned.
It's just an assignment operator. You assign a value to a widget property. For example, Container widget has many properties, like color or height:
Container(
margin: const EdgeInsets.all(10.0),
color: Colors.amber[600],
width: 48.0,
height: 48.0,
),
I'm new to Flutter and am working through the intro course on Udacity. In one of the tasks, I was trying to follow the code and I can't make much sense of it. Here's the code from the solution of the project (I've cut and paste the parts that matter, and also legal disclaimer I do not own any of this code, it's from the sample Flutter Udacity project):
Widget build(BuildContext context) {
final input = Padding(
padding: _padding,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextField(...),
_createDropdown(_fromValue.name, _updateFromConversion),
],
),
);
}
void _updateFromConversion(dynamic unitName) {
setState(() {
_fromValue = _getUnit(unitName);
});
if (_inputValue != null) {
_updateConversion();
}
}
Widget _createDropdown(String currentValue, ValueChanged<dynamic> onChanged) {
return Container(
margin: EdgeInsets.only(top: 16.0),
decoration: BoxDecoration(...),
padding: EdgeInsets.symmetric(vertical: 8.0),
child: Theme(...),
child: DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: DropdownButton(
value: currentValue,
items: _unitMenuItems,
onChanged: onChanged,
style: Theme.of(context).textTheme.title,
),
),
),
),
);
}
Here's where I'm stuck. _updateFromConversion requires an input parameter unitName. But when they call it, in _createDropdown, they don't pass any. So how does _updateFromConversion know what unitName is? Also, is _updateFromConversion executed before _createDropdown, or is it executed when the "onChanged" property of DropdownButton is set?
Second question: they're passing that function with return type void into _createDropdown, which is expecting ValueChanged. Shouldn't this throw an error?
If someone can explain the flow of this code and what I am missing I would greatly appreciate it.
Thank you!
You seem to be misunderstanding the assignment of a variable to a function for a function call.
Let me try to show it with example code.
void _updateFromConversion(dynamic unitName) {
print("Unit name: $unitName");
}
class SomeClass {
void Function(dynamic arg) myFunction;
}
void main() {
final c = SomeClass()..myFunction = _updateFromConversion;
print("Created c. Calling its function");
c.myFunction("foo");
print("Done");
}
When you run this code, you will see this printed:
Created c. Calling its function
Unit name: foo
Done
This shows that the _updateFromConversion function is not called when you create the SomeClass instance in SomeClass()..myFunction = _updateFromConversion;. This is only an assignment (it assigns to the field myFunction the value _updateFromConversion... yes, in Dart a function itself can be a value)!
You should know that because there's no () after the function name, and function invocation in Dart always must contain the list of arguments between () even if it's empty.
So, here's where the function is invoked:
c.myFunction("foo");
See? There's a list of arguments containing a single value, "foo". That's why the function then prints Unit name: foo, because the argument unitName takes the value "foo".
TL;DR
This is a function invocation:
c.myFunction("foo");
This is NOT:
c.myFunction;
Yashvin,
In dart function can be passed as parameter to other functions. This is usually used to pass callbacks for instance.
In example you provided, function _updateFromConversion is passed as parameter onChanged to another function _createDropdown.
In that function it will be assigned to onChanged listener of DropdownButton button.
Every time value of DropdownButton changes, this function will be invoked and will be passed selected value of DropdownButton.