how to change the state of one statefulwidget from another in flutter? - flutter

I have a stateful widget which is conditionally rendering two childs inside stack, and i want to change the condition of the rending from a third child . any idea ?
Parent code :
class MapPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body:Body()
);
}
}
class Body extends StatefulWidget {
final String showScreen;
const Body({
Key key,
this.showScreen="post",
}) : super(key:key);
#override
_BodyState createState() => _BodyState();
}
class _BodyState extends State<Body> {
Widget _conditionedWidget(){
if(this.widget.showScreen=="map"){
return MapScreen();
}else if(this.widget.showScreen == "post"){
return PostScreen();
}
}
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
DrawerScreen(),
_conditionedWidget(),
],
);
}
}
child code
class DrawerScreen extends StatefulWidget {
#override
_DrawerScreenState createState() => _DrawerScreenState();
}
class _DrawerScreenState extends State<DrawerScreen> {
#override
Widget build(BuildContext context) {
return Container(
color:kPrimaryColor,
padding:EdgeInsets.only(top:70),
child:Column(
children: <Widget>[
Row(
children: <Widget>[
SizedBox(width:20.0),
CircleAvatar(),
SizedBox(width:10.0),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Biswas Sampad',style:TextStyle(
color:Colors.white,
fontWeight: FontWeight.bold,
fontSize: 20.0,
)),
Text('#biswassampad',style:TextStyle(
color:Colors.grey[200],
fontSize: 15.0,
))
],
)
],
),
Container(
padding: EdgeInsets.symmetric(horizontal: 20,vertical:20),
margin: EdgeInsets.symmetric(vertical:30),
child: Column(
children: <Widget>[
MenuButton(icon:Icons.style, name:'Explore',action:(){
print('showing maop');
}),
MenuButton(icon:Icons.tag_faces, name:'Profile',action:(){
print('showing profile');
}),
MenuButton(icon:Icons.people, name:'People',action:(){
print('showing People');
}),
MenuButton(icon:Icons.speaker_notes, name:'Messages',action:(){
print('showing messages');
}),
MenuButton(icon:Icons.notifications, name:'Notifications',action:(){
print('showing Notifications');
}),
MenuButton(icon:Icons.satellite,name:'Settings',action:(){
print('showing settings');
})
],
),
),
LogoutSection()
],
)
);
}
}
So basically i want to change the showScreen value of the parent widget from DrawerScreen>MenuButton>action ?
any idea how to do it !! Thanks in advance.

You can use the Function in "DrawerScreen" widget like this :
write this code into the header of the class :
final Function onChangeState = Function();
DrawerScreen({#rquired onChangeState});
and in MenuButton call onChangeState function , like this:
MenuButton(icon:Icons.satellite,name:'Settings',action:(){
widget.onChangeState("Settings");
})
and change old code in Body widget to :
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
DrawerScreen(onChangeState : (newState){
setState(){
this.widget.showScreen = newState;
};
}),
_conditionedWidget(),
],
);
}

Related

flutter variable is not passing in class widget

How to pass variable declared to class widget.
It is showing error "undefined name abcd".
But I have already declared it.
How to pass this variable abcd in Text widget.
Code is attached.
Thanks in advance.
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final String abcd = "abcd";
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Column(
children: [
TextField(),
OkButton(),
],
),
),
);
}
}
class OkButton extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(4),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
FlatButton(
onPressed: () {},
child: Text("ok"),
),
Text(abcd),
],
),
);
}
}
Add a constructor in the OkButton which accepts a String.
class OkButton extends StatelessWidget {
OkButton({#required this.text});
final String text;
...
Text(text), // from Text(abcd),
...
}
Then, when you create OkButton, set the text property.
OkButton(text: abcd),
You can pass your value from one class to another by using Constructor
class _MyHomePageState extends State<MyHomePage> {
final String abcd = "abcd";
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Column(
children: [
TextField(),
OkButton(abcd),
],
),
),
);
}
}
class OkButton extends StatelessWidget {
final String abcd;
OkButton(this.abcd);
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(4),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
FlatButton(
onPressed: () {},
child: Text("ok"),
),
Text(abcd),
],
),
);
}
}

Flutter: Provider Value Not Updating

I am new to flutter/dart and am trying to get a value to update for a loading bar I would like to make. The value is updating within a provider widget I created, but when I try to utilize it, I am unable to figure out what is missing. Any assistance would be greatly appreciated.
class LoadingProvider extends ChangeNotifier{
int _downloadPercentage = 0;
int get downloadPercentage => _downloadPercentage;
void getPercentage(int input) {
_downloadPercentage = input;
notifyListeners();
print(downloadPercentage);
}
}
Here is the page I wish to display on
class ContourScreen extends StatefulWidget {
final Note note;
ContourScreen(this.note);
#override
State<StatefulWidget> createState() => new _ContourScreenState();
}
class _ContourScreenState extends State<ContourScreen> with TickerProviderStateMixin{
#override
void initState() {
super.initState();
}
#override
dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
final loadingProvider = Provider.of<LoadingProvider>(context);
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(),
body: Scrollbar(
child: SingleChildScrollView(
child: Container(
child: Padding(
padding: const EdgeInsets.only(left: 20.0, right: 20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ChangeNotifierProvider<ValueNotifier<int>>(
create: (context) => ValueNotifier<int>(0),
child: Text('${loadingProvider.downloadPercentage}'),),
],
),
),
),
),
),
);
}
}
Here is the git hub to all pages for reference https://github.com/mattcubs/loadinggif

flutter: How to detect keyboard?

I want detect Keyboard. And want to show it other text when keyboard is visible or unvisible.
But my code is not working.
This is my code.
class Search extends StatefulWidget {
#override
_SearchState createState() => _SearchState();
}
class _SearchState extends State<Search> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.white,
child: Column(
children: [
Expanded(
flex: 1,
child: ListView(
children: [
MediaQuery.of(context).viewInsets.bottom !=0 ? Center(child: Text("true"),) : Center(child: Text("false"),)
],
),
)
],
),
),
);
}
}
As #Anas Mohammed mentioned, you can do it with the keyboard_visibility package. Here is a total example:
import 'package:flutter/material.dart';
import 'package:keyboard_visibility/keyboard_visibility.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Keyboard visibility example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: KeyboardVisibilityExample(),
);
}
}
class KeyboardVisibilityExample extends StatefulWidget {
KeyboardVisibilityExample({Key key}) : super(key: key);
#override
_KeyboardVisibilityExampleState createState() => _KeyboardVisibilityExampleState();
}
class _KeyboardVisibilityExampleState extends State<KeyboardVisibilityExample> {
KeyboardVisibilityNotification _keyboardVisibility = new KeyboardVisibilityNotification();
int _keyboardVisibilitySubscriberId;
bool _keyboardState;
#protected
void initState() {
super.initState();
_keyboardState = _keyboardVisibility.isKeyboardVisible;
_keyboardVisibilitySubscriberId = _keyboardVisibility.addNewListener(
onChange: (bool visible) {
setState(() {
_keyboardState = visible;
});
},
);
}
#override
void dispose() {
_keyboardVisibility.removeListener(_keyboardVisibilitySubscriberId);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Keyboard visibility example'),
),
body: Center(
child: Padding(
padding: EdgeInsets.all(24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
keyboardType: TextInputType.text,
decoration: InputDecoration(
labelText: 'Input box for keyboard test',
),
),
Container(height: 60.0),
Text(
'The current state of the keyboard is: ' + (_keyboardState ? 'VISIBLE' : 'NOT VISIBLE'),
),
],
)
),
),
);
}
}
for to visible keyboard this code:
FocusScope.of(context).requestFocus();
for to unvisible keyboard this code:
FocusScope.of(context).unfocus();
for check visiblity of keyboard :
FocusScope.of(context).hasFocus
your provided code:
class Search extends StatefulWidget {
#override
_SearchState createState() => _SearchState();
}
class _SearchState extends State<Search> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.white,
child: Column(
children: [
Expanded(
flex: 1,
child: ListView(
children: [
FocusScope.of(context).hasFocus ? Center(child: Text("true"),) : Center(child: Text("false"),)
],
),
)
],
),
),
);
}
}
Accepted answer contains old library not support null safety, you can use this one flutter_keyboard_visibility which support null safety.

How to send simple data from `secondpage` to `mainpage` (stateful to stateful)

i found a lot of solution passing data between stateless and stateful widget, but not between two stateful widgets
EDIT: i edited the code to show more details
MainPage
class MainPage extends StatefulWidget {
final String name;
MainPage({Key key, this.name}) : super(key: key);
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Text from 2nd page -> "), //should return "Text from 2nd page -> BATMAN"
FloatingActionButton(
child: Icon(Icons.android),
onPressed: (){
Navigator.push(context, MaterialPageRoute(
builder: (context) => SecondPage()
));
},
),
],
),
),
);
}
}
SecondPage:
class SecondPage extends StatefulWidget {
SecondPage({Key key}) : super(key: key);
#override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
...
Text("I choose ${_selectedMethod.name}"), // this returned "I choose BATMAN"
...
}
So basically i want to pass ${_selectedMethod.name} from 2ndPage to MainPage. sorry im so bad at explaining :(
You can pass variables back to a previous Page in the Navigator stack by sending it through the .pop() method and expecting them in the previous page with the .then() method:
class MainPage60643815 extends StatefulWidget {
#override
_MainPage60643815State createState() => _MainPage60643815State();
}
class _MainPage60643815State extends State<MainPage60643815> {
String displayTextFromSecondPage = '';
#override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Test from second page: '),
Text(displayTextFromSecondPage),
],
),
RaisedButton(
onPressed: goToSecondPage,
child: Text('Go to 2nd Page'),
),
],
),
);
}
void goToSecondPage(){
Navigator.of(context).push(MaterialPageRoute(
builder: (context) {
return SecondPage60643815(text: displayTextFromSecondPage);
}
)).then((valueFromSecondPage){
setState(() {
displayTextFromSecondPage = valueFromSecondPage;
});
});
}
}
class SecondPage60643815 extends StatefulWidget {
final String text;
SecondPage60643815({this.text});
#override
_SecondPage60643815State createState() => _SecondPage60643815State();
}
class _SecondPage60643815State extends State<SecondPage60643815> {
TextEditingController _textEditingController;
#override
void initState() {
_textEditingController = TextEditingController(
text: widget.text,
);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: goToFirstPage,
),
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
TextFormField(
controller: _textEditingController,
autofocus: true,
),
],
),
),
),
);
}
void goToFirstPage(){
Navigator.of(context).pop(_textEditingController.text);
}
}
I assume that you have a SecondPage-Widget. So you can do something like:
class _MainPageState extends State<MainPage> {
#override
Widget build(BuildContext context) {
return Container(
child: SecondPage('BATMAN'),
);
}
}
This might print the desired "BATMAT" Text.
EDIT
This might be your SecondPage Widget:
class SecondPage extends StatefulWidget {
final String selection;
SecondPage(this.selection);
#override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
#override
Widget build(BuildContext context) {
return Container(
child: Text(widget.selection),
);
}
}

Flutter How to Get Rid of Default fillColor for the First Item of DropdownButton

Question: title
So I have this DropdownButton
And here is the DropdownMenuItem
As you can see, the first item has a grey color on the background. So how to remove it?
To be more clear, here is what I want to achieve
Navbar Snippet:
class Navbar extends StatefulWidget {
#override
_NavbarState createState() => _NavbarState();
}
class _NavbarState extends State<Navbar> {
action() {
print('test');
}
#override
Widget build(BuildContext context) {
return Container(
height: 100,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
NavbarLogo(),
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
NavbarItem(
title: 'welcome',
navigationPath: RouterDashboardView.welcomeView,
),
SizedBox(width: 50.0),
NavbarItemDropdown(
items: ['labelExitLabel', 'labelExitLabel', 'actionExitAction'],
functions: [action],
),
],
),
],
),
);
}
}
Nothing fancy, just contains a logo, a text and the dropdown
NavbarDropdown Snippet:
class NavbarItemDropdown extends StatefulWidget {
final List<String> items;
final List<Function> functions;
const NavbarItemDropdown({
Key key,
#required this.items,
this.functions,
}) : super(key: key);
#override
_NavbarItemDropdownState createState() => _NavbarItemDropdownState();
}
class _NavbarItemDropdownState extends State<NavbarItemDropdown> {
#override
Widget build(BuildContext context) {
return DropdownButtonHideUnderline(
child: DropdownButton(
items: widget.items.map((String _value) {
return DropdownMenuItem<String>(
value: _value,
child: _value.contains('label')
? Text(
'${_value.split('label')[1]}',
style: TextStyle(fontSize: 13.0),
)
: Text('${_value.split('action')[1]}'),
);
}).toList(),
onChanged: (String _value) {
if (_value.contains('action')) widget.functions[0]();
},
hint: Text('TestDropDown'),
),
);
}
}