How to set a variable value in a widget and in another widget? - flutter

I'm trying to set a variable value (number, in the code below) that exists in FirstWidget, from SecondWidget. And notify both widgets so the number will be updated in the two widgets.
class FirstWidget extends StatefulWidget {
#override
_FirstWidgetState createState() => _FirstWidgetState();
}
class _FirstWidgetState extends State<FirstWidget> {
int number = 0;
#override
Widget build(BuildContext context) {
return Column(
children: [
Text(
'$number',
),
SecondWidget(),
Text(
'$number',
)
],
);
}
}
class SecondWidget extends StatefulWidget {
#override
_SecondWidgetState createState() => _SecondWidgetState();
}
class _SecondWidgetState extends State<SecondWidget> {
#override
Widget build(BuildContext context) {
return TextButton(
child: Text('The number is $number. Press to increase the number'),
onPressed: () {
setState(() {
number++;
});
},
);
}
}
(I know that that code gives an error, but the main idea was to give you the problem I want to solve).
The output I want it to be shown:
before pressing the button -
0
The number is 0. Press to increase the number
0
after pressing the button -
1
The number is 1. Press to increase the number
1
So I would be happy if you can help solving this.
Thanks.

There are many approaches to get the result you are looking for, this one is using ValueNotifier in order to change the value of number
Here is an example based on your code:
https://dartpad.dev/b6409e10de32b280b8938aa75364fa7b
We can use another State Management like Provider or Cubit, and we will get the same result.
Another way is to pass a function as a param in the second widget and execute that function when button is pressed

Related

Flutter Dropdown Container/Widget

I have spent hours googling something that should be incredibly simple, but have found nothing to this sort on the internet. Effectively, I want to make a dropdown, so that when a button is clicked, I have a menu dropdown. However, I do not wish to have this dropdown be a list of items. I want the dropdown to be able to take in a child widget, similar to the showDialog function, and I can pass what I wish to the child widget.
Eg., I wish to merge dropdown's positioning with dialog ability to not only render an opinionated list.
Does anyone have any clue how to accomplish this?
You can use flutter_portal. I used this package to build many types of dropdowns.
Another way I found to do this is to use the showGeneralDialog function and customize the position.
What you could do is to copy the implementation of PopupMenuDivider:
class MyEntry extends PopupMenuEntry<Never> {
const MyEntry();
#override
double get height => kMinInteractiveDimension;
#override
bool represents(void value) => false;
#override
State<MyEntry> createState() => _MyEntryState();
}
class _MyEntryState extends State<MyEntry> {
#override
Widget build(BuildContext context) {
return MyWidget();
}
And then you can use it in a PopupMenuButton:
class MyButton extends StatelessWidget {
const MyButton();
#override
Widget build(BuildContext context) {
return PopupMenuButton(
itemBuilder: (context) {
return [
const MyEntry();
];
},
onSeleted: (_) {},
child: MyChild(),
);
}
}

I want to send data to a new screen without navigating to it on pressing a button in flutter

I want to send data to different screen on pressing a button.
I am using
Get.to(Screen(), arguments: [data])
I only want to send data
It send the data but also navigate to it
Please give me. Some. Hint
Let's suppose we have two Stateful widget class.
The CheetahInput has a static variable data that will get data from any class And
we have a check on TEXT() when variable data is empty simply show "old value" in TEXT() widget
if variable data is not empty then show its value on Text() widget.
class CheetahInput extends StatefulWidget {
Static String? data;
#override
_CheetahInputState createState() => _CheetahInputState();
}
class _CheetahInputState extends State<CheetahInput> {
#override
Widget build(BuildContext context) {
return Center(child: Text(SignIn.data!=null?SignIn.data!:'old value'),); }
}
The TestEditor Class has saveButton and navigatebutton, while the savebutton will assign data into static variable "data" in SignIn class,
And the NavigateButton will Navigate to that screen where you have sended the data
class TestEditor extends StatefulWidget {
#override
_TestEditorState createState() => _TestEditorState();
}
class _TestEditorState extends State<TestEditor> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(),
floatingActionButton:Container( width:MediaQuery.of(context).size.width,
child: Row(
children: [Spacer(),
FloatingActionButton(onPressed: (){Navigator.push(context, MaterialPageRoute(builder:(context)=>SignIn(context)));},child: Text('NavigateButton'),),
Spacer(),
FloatingActionButton(onPressed: (){SignIn.data='I am data from new page';},child: Text('saveButton'),),Spacer(),
],
),
);
}
}
So in this way, you send data to other screens without navigate to that screen at meantime

flutter slider not updating widget variables

am playing around with the slider widget on flutter, and I can't figure out why it does not update certain values in a different widget, example code is shown below;
When i move the slider, it has no issues moving, but the value i'm trying to update on the other widget does not update even though the onchanged is updating the variable passed through in a set state accordingly.
any help would be greatly appreciated!
Scaffold Code
class TestPage extends StatelessWidget {
static const id = "test_page";
#override
Widget build(BuildContext context) {
double testValue = 0;
return Scaffold(
body: Column(
children: [
Text("Hello World"),
TestBoxNumber(
numberDisplay: testValue,
),
TestSlider(testValue: testValue),
],
),
);
}
}
Slider Code
class TestSlider extends StatefulWidget {
double testValue;
TestSlider({required this.testValue});
#override
_TestSliderState createState() => _TestSliderState();
}
class _TestSliderState extends State<TestSlider> {
#override
Widget build(BuildContext context) {
return Slider(
activeColor: themeData.primaryColorLight,
value: widget.testValue,
min: 0,
max: 100,
divisions: 100,
label: widget.testValue.round().toString(),
onChanged: (double value) {
setState(() {
widget.testValue = value;
});
},
);
}
}
Different Widget Code
class TestBoxNumber extends StatefulWidget {
final double numberDisplay;
const TestBoxNumber({required this.numberDisplay});
#override
_TestBoxNumberState createState() => _TestBoxNumberState();
}
class _TestBoxNumberState extends State<TestBoxNumber> {
#override
Widget build(BuildContext context) {
return Container(
child: Text(widget.numberDisplay.toString()),
);
}
}
The problem is that you are constructing TestBoxNumber widget in such a way that value (testValue) will always be the same (testValue is never returned out of the TestSlider widget).
How to overcome this issue?
You can make your TestPage a StatefullWidget. Then create callback from TestSlider, so when you change value in TestSlider you will call some function in TestPage (with setState in it, causing re-rendering your page).
Or if you don't want your whole TestPage widget to be Statefull (if, let's say, you predict a lot of other static widgets in it and you don't want them to be re-rendered because you just moved a slider), you can create wrapper Statefull widget and put both TestSlider and TestBoxNumber widgets in it. This is more flexible approach, imho.
Here is small scheme of what I mean by wrapping two widgets in another one:
UPD: btw, there is no point in making TestBoxText a statefull widget if it's only purpose is to display a text and you pass it's value through the constructor.

I was told that 25th line of code contains an issue where setState() with random color being used. Help identify an issue

Original task sounded like:
The application should: display the text "Hey there" in the middle of
the screen and after tapping anywhere on the screen a background color
should be changed to a random color. You can also add any other
feature to the app - that adds bonus points Please do not use any
external libraries for color generation
My solution (GitHub):
import 'dart:math';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: RandomBackgroundColorWidget(),
);
}
}
class RandomBackgroundColorWidget extends StatefulWidget {
#override
_RandomBackgroundColorWidget createState() => _RandomBackgroundColorWidget();
}
class _RandomBackgroundColorWidget extends State<RandomBackgroundColorWidget> {
int _colorIndex = 0xFF42A5F5;
void _randomColorIndexGenerator() {
final _rng = new Random();
setState(() => {_colorIndex = (_rng.nextInt(0xFFFFFF) + 0xFF000000)});
}
#override
Widget build(BuildContext context) {
return Stack(children: [
Material(
color: Color(_colorIndex),
child: Center(
child: Text("Hey there"),
),
),
GestureDetector(
onTap: () => _randomColorIndexGenerator(),
),
]);
}
}
While reviewing my test task interviewer said that 25th line of code contains an issue.
setState(() => {_colorIndex = (_rng.nextInt(0xFFFFFF) + 0xFF000000)});
And he commented:
"It is working in a way that is not intended by you."
Help to identify an issue in 25th line of code.
You are accidentally combining the two ways to declare a function in Dart: the arrow operator => and curly braces {}.
Line 25 should be:
setState(() => _colorIndex = _rng.nextInt(0xFFFFFF) + 0xFF000000);
with no extra curly braces.
The issue is a syntax error. When using setState() =>, you dont need the {}
setState(() {_colorIndex = (_rng.nextInt(0xFFFFFF) + 0xFF000000)});
or
setState(() => _colorIndex = (_rng.nextInt(0xFFFFFF) + 0xFF000000));
I couldn't find the error you mention, however I recommend that you always use init state when assigning default values.
Here other way
import 'dart:math';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: RandomBackgroundColorWidget(),
);
}
}
class RandomBackgroundColorWidget extends StatefulWidget {
#override
_RandomBackgroundColorWidget createState() => _RandomBackgroundColorWidget();
}
class _RandomBackgroundColorWidget extends State<RandomBackgroundColorWidget> {
Color _color;
#override
void initState() {
_color = Colors.white;
super.initState();
}
void getrandomColor() {
setState(() {
_color = Colors.primaries[Random().nextInt(Colors.primaries.length)];
});
}
#override
Widget build(BuildContext context) {
return Stack(children: [
Material(
color: _color,
child: Center(
child: Text("Hey there"),
),
),
GestureDetector(
onTap: getrandomColor,
),
]);
}
}
Issue is in nextInt function.
Flutter accepts color codes for generation up to 0xFFFFFFFF, where first pair of numbers is needed for opacity level and other pairs needed for RGB levels
nextInt function generates random number in range up to, but not including, passed number. For example, nextInt(3) will generate randomly 0,1 or 2, but not 3.
So original app was generating all random colors (from 0x0 to 0xFFFFFE) except last one - 0xFFFFFF
Therefore, 25th line should look like this in order to generate every possible color.
setState(() => _colorIndex = (_rng.nextInt(0x1000000) + 0xFF000000));

How to change values within a stateful widget class from a different class?

I have a stateful widget LetterButton()
#override
Widget build(BuildContext context) {
return RaisedButton(
child: Text(widget.caption),
onPressed: onChanged,
color: colors[currentIndex],
padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
);
}
In my main.dart file I declare an array of LetterButtons
List<LetterButton> buttonArray;
which I initialize and fill during initState() via the method
void makeButtons() {
for (var letter in alphabet) {
buttonArray.add(
LetterButton(letter),
);
}
}
The buttons in the list are then displayed in the UI
Wrap(
children: buttonArray,
)
How can I change the value of currentIndex (an int in
class LetterButtonState extends State<LetterButton>) or otherwise change all the buttons to the same color from main.dart?
NOTE: I asked a similar question a few days ago, but the answer was a little above my current knowledge, as are responses I've seen to similar Q's here on SO. I have a little understanding of callbacks, and experimented a little with the provider package, but there's such a variety of answers and info available online that it's hard for me to even know what I don't know to be able to answer my question :-)
Create stateful widget with state as public access, so that you can access outside of the package and provide key to constructor. So that you can refer key and get can get state to change value. See the following example
class LetterButton extends StatefulWidget {
LetterButton({GlobalKey key}) : super(key: key);
#override
LetterButtonState createState() => LetterButtonState();
}
class LetterButtonState extends State<LetterButton> {
int value = 0;
//this public method is to update int value
setValue(int value) {
setState(() {
this.value = value;
});
}
#override
Widget build(BuildContext context) {
return Center(
child: Text(value.toString()),
);
}
}
//In Main.dart
GlobalKey<LetterButtonState> _buttonStateKey = GlobalKey();
//while creating widget
LetterButton(key:_buttonStateKey)
//in onTapCallback you can call to update value
_buttonStateKey.currentState?.setValue(10);
Just send your created function to new class by parameter and the new class should be Constarcter with Function lThen you can call the function from a new class.