I'am trying to create a custom widget CarteSim and I'am trying to call it everytime I click on Floating Action Button , but unfortunately it doesn't show when I call it inside the button , but it shows when I call it in the Scaffold , please who has ever experience that
here s my code
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.pink,
title: Text(" INWI "),
),
body: SingleChildScrollView(
child: Container(
child: Center(
child: Column(
children: <Widget>[
DropdownButton<String>(
items: _type.map((String dropDownStringItem) {
return DropdownMenuItem<String>(
value: dropDownStringItem,
child: Text(dropDownStringItem),
);
}).toList(),
onChanged: (String newValueSelected) {
setState(() {
this._currentItemSelected = newValueSelected;
});
},
value: _currentItemSelected,
),
Divider(
color: Colors.black,
),
new Row(
children: [
new Text(" type client supporte * carte avec 1 cin"),
new Checkbox(value: _isChecked, onChanged: (bool value){ onChanged(value);}),
]
),
Divider(
color: Colors.black,
),
new Column(
children: <Widget>[
CarteCin(),
CarteSim(),
]
)
],
),
),
)
),
floatingActionButton: FloatingActionButton(
onPressed: (){
Column(
children: <Widget>[
CarteSim(),
]
);
},
child: Icon(Icons.add),
backgroundColor: Colors.pink,
),
);
}
]
}
you are misunderstanding the process. The onPressed key actually used for call actions on press the floatingActionButton. You can write functions there, like you can update your state or print anything on your console or call an API to get data. But you can't display any widget from there.
Now what you're trying to do, that can be resolved like this. Whenever you press that button you should update your state, i.e bool show. Then modify your Column children based on that show state.
Here is an example how tu update the UI in flutter
class FrontPage extends StatefulWidget {
#override
_FrontPageState createState() => _FrontPageState();
}
class _FrontPageState extends State<FrontPage> {
bool currentStateShowsThis;
initState() {
currentStateShowsThis = false;
super.initState();
}
Widget build(BuildContext context) {
final color = currentStateShowsThis ? Colors.blue : Colors.red;
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.pink,
title: Text(" INWI "),
),
body: SingleChildScrollView(
child: Container(
child: Center(
child: Column(
children: <Widget>[
Container(width: 100, height: 100, color: color,) // alternatively you can change the widgets being displayed
],
),
),
)
),
floatingActionButton: FloatingActionButton(
onPressed: (){
setState(() {
currentStateShowsThis = !currentStateShowsThis;
});
},
child: Icon(Icons.add),
backgroundColor: Colors.pink,
),
);
}
}
In your example "the button" will call back the
onPressed:
Which will only create the widgets in that method (Column ...) and not place them in a the layout.
Related
In Flutter, I am trying to build a counter that increments only until i hold down the button. I have done it, but why is there value difference between within Terminal and in the UI. (see picture)
I am using riverpod to update the UI.
I checked putting print() just before ref.read(myprovider.notifier).state ++
my full code is:
class StateProviderPond extends ConsumerWidget {
static const String page_id = 'goto_state';
int counter_int = 90001;
Timer? timerCounter;
StateProviderPond({Key? key}) : super(key: key);
#override
Widget build(BuildContext context, WidgetRef ref) {
counter_int = ref.watch(myStateProviderInt);
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.transparent,
title: const Text('riverpod-state provider'),
centerTitle: true,
actions: [
IconButton(onPressed: () {}, icon: Icon(Icons.arrow_back_ios))
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(
'$counter_int',
style: TextStyle(fontSize: 50, color: Colors.white38),
),
Column(
children: [
GestureDetector(
child: Center(
child: Text('~',
style: TextStyle(fontSize: 30, color: Colors.indigo)),
),
onTapDown: (TapDownDetails details) {
print('down');
// timer?.cancel();
timerCounter =
Timer.periodic(Duration(milliseconds: 1), (t) {
print(counter_int++);
ref.read(myStateProviderInt.notifier).state++;
});
},
onTapUp: (TapUpDetails details) {
timerCounter?.cancel();
print('up');
print('***********');
},
),
],
),
],
),
),
);
}
}
Because print(counter++); firstly prints the value, then increment it. You should do print(++counter); Here you can see simple dart cli to explain this behaviour.
I'm trying to access branchSelected, a Provider declared towards the top of my code in the scaffold's child widgets. When I use branchSelected.branchDropdownValue in the original widget, it works. However, when I go into the child widget methods, specifically
ElevatedButton(
onPressed: () {
branchSelected.branchChange;
/*
refreshBranchData();
refreshProjectData();
*/
},
child: Icon(Icons.refresh))
, I received the error "Undefined name 'branchSelected'." Looking at other documentation, I thought that all child widgets should be able to access the Provider; however, that doesn't seem to be the case here. Any ideas? I've attached my code below:
#override
Widget build(BuildContext context) {
final branchSelected = Provider.of<branchListChanges>(context);
return Scaffold(
appBar: AppBar(
title: Text('Build Launcher'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
_buildTopRow(),
Consumer<branchListChanges>(builder: (context, data, child) {
return Text(
'Current Branch: ${branchSelected.branchDropdownValue}');
}),
_buildList(),
],
),
),
backgroundColor: Colors.grey[200],
);
}
Expanded _buildList() {
// Sets which branch to view for the list runs
return Expanded(
child: RunList(branches, "main"),
);
}
Row _buildTopRow() {
return Row(
children: [
Text("Project:"),
SizedBox(width: 6),
ProjectDropdown(packages),
SizedBox(width: 6),
Text("Branch:"),
SizedBox(width: 6),
BranchDropdown(branchNames),
SizedBox(width: 6),
Checkbox(
checkColor: Colors.white,
fillColor: MaterialStateProperty.all<Color>(Colors.blue),
value: onlyLatestPerDay,
onChanged: (bool? value) {
setState(() {
onlyLatestPerDay = value!;
});
},
),
SizedBox(width: 3),
Text("Only latest per-day"),
SizedBox(width: 6),
Checkbox(
checkColor: Colors.white,
fillColor: MaterialStateProperty.all<Color>(Colors.blue),
value: onlyInstalled,
onChanged: (bool? value) {
setState(() {
onlyInstalled = value!;
});
},
),
SizedBox(width: 3),
Text("Only installed"),
SizedBox(width: 6),
ElevatedButton(
onPressed: () {
branchSelected.branchChange;
/*
refreshBranchData();
refreshProjectData();
*/
},
child: Icon(Icons.refresh))
],
);
}
}
I created my Provider in main.dart attached below:
class HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'cornerCan',
theme: ThemeData(
primarySwatch: Colors.blue,
),
// EFFECTS: runs mainPage function in main_page.dart
home: ChangeNotifierProvider<branchListChanges>(
create: (context) => branchListChanges(),
child: mainPage(),
),
);
}
}
The scope of your branchSelected variable is only inside the build function. You need to declare it outside the build function to access it.
You can also pass it as a parameter to the _buildTopRow() function
e.g. _buildTopRow(branchSelected)
I am using Cards in Flutter and want Progress Indicator at the left bottom position for 2 seconds while Tap on the card so that another page load successfully.
Does anyone know how to add?
Container(
height: 130,
child: Card(
child: Row(
children: <Widget>[
Expanded(
child: ListTile(
title: Text(
'My card Location',
style: TextStyle(
fontSize: 15, fontWeight: FontWeight.w700),
),
leading: Icon(Icons.setting),
// color: Colors.blueAccent, size: mediumIconSize),
trailing: Icon(Icons.keyboard_arrow_right),
selected: true,
onTap: () async {
// I try this one but not working
// Flushbar(
//
// showProgressIndicator: true,
// duration: Duration(seconds: 2),
// );
getDetails().then((myCardlocations) {
Navigator
.of(context)
.pushNamed('/myCardlocations',
arguments: ObjectLocations(locations, 'myCardlocations'));
}
);
}
),
),
],
),
),
),
You can do something like this using Stack and CircularProgressIndicator..
class _MyWidgetState extends State<MyWidget> {
bool isLoading = false;
#override
Widget build(BuildContext context) {
return Container(
height: 130,
child: Stack(
children: [
Container(
height: 130,
child: Card(
child: Row(
children: <Widget>[
Expanded(
child: ListTile(
title: Text(
'My card Location',
style: TextStyle(
fontSize: 15, fontWeight: FontWeight.w700),
),
leading: Icon(Icons.settings),
// color: Colors.blueAccent, size: mediumIconSize),
trailing: Icon(Icons.keyboard_arrow_right),
selected: true,
onTap: () async {
setState(() {
isLoading = true;
});
getDetails().then((myCardLocations) {
setState(() {
isLoading = false;
});
// navigation code here
});
},
),
),
],
),
),
),
Align(
alignment: Alignment.bottomLeft,
child: isLoading
? Padding(
padding: EdgeInsets.fromLTRB(15,0,0,15),
child: SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(),
),
)
: SizedBox(),
),
],
),
);
}
}
Edit:
Looks like I misunderstood the question a bit. Specifically, the place where to show the progress indicator. Anyways, if you get the idea, you can put the indicator at a different place as per your requirement.
There are certain things, which I would like to mention before I give the actual answer.
Read about Flutter.delayed constructor, very useful thing to make some thing wait for a while and do the operation by providing Duration. Whatever you want to do after that duration, it will implement in the callback function
Future.delayed(Duration(seconds: your_time, (){
//it will perform this operation after that much of seconds
}));
You can always show/hide a Widget using bool value, and make changes accordingly
Use a column and Add the LinearProgressIndicator at the end of the Widget. Show/hide it based up on the data
Also, use MediaQuery to give out the height. It is more efficient way of giving the dimensions according to all phone size. Like match-parent in Android Studio. Do the math accordingly, I have shown in the code also
Column(
children: [
Row(),
bool val ? LinearProgressIndicator() : Container() // Container() is nothing but an empty widget which shows nothing
]
)
Some heads up: I have not used getData, since it is not defined properly but you can call it the in function which I will show you in the code, that is pageTransit(). Follow the comments and you are good to go
class _MyHomePageState extends State<MyHomePage> {
// this takes care of the show/hide of your progress indicator
bool _showProgress = false;
// this takes care of the operation
void pageTransit(){
// first show when the ListTile is clicked
setState(() => _showProgress = true);
Future.delayed(Duration(seconds: 2), (){
// hide it after 2 seconds
setState(() => _showProgress = false);
// do the page trnasition here
//getDetails().then((myCardlocations) {
//Navigator.of(context).pushNamed('/myCardlocations',
//arguments: ObjectLocations(locations, 'myCardlocations'));
//}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
height: MediaQuery.of(context).size.height * 0.1,
child: Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// use your items here, based upon the bool value show hide your
// progress indicator
Row(
children: <Widget>[
Expanded(
child: ListTile(
title: Text(
'My card Location',
style: TextStyle(
fontSize: 15, fontWeight: FontWeight.w700),
),
leading: Icon(Icons.settings),
// color: Colors.blueAccent, size: mediumIconSize),
trailing: Icon(Icons.keyboard_arrow_right),
selected: true,
onTap: () => pageTransit()
)
)
]
),
// show/hide in the card
_showProgress ? LinearProgressIndicator() : Container()
]
)
)
)
);
}
}
Result
Look at the ProgressIndicator, it remains there for 2 seconds, and then goes away
1. You need to define a GlobalKey for the Scaffold so that you can use a SnackBar (you can define the GloablKey in your page's State).
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
2. You need to set the key for the Scaffold.
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
...
3. You need to wrap the Card with a GestureDetector and set the onTap function to call showLoading which shows a SnackBar on the bottom of the screen. Call your getDetails function in the showLoading. Full code (except the define key step):
void _showLoading() {
_scaffoldKey.currentState.showSnackBar(new SnackBar(
duration: new Duration(seconds: 2),
content: new Row(
children: <Widget>[
new CircularProgressIndicator(),
new Text("Loading...")
],
),
));
// call to your getDetails and its steps should be here
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text("My app"),
),
body: Center(
child: GestureDetector(
child: Card(
child: Row(children: <Widget>[
Expanded(
child: ListTile(
title: Text(
'My card Location',
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w700),
),
leading: Icon(Icons.settings),
// color: Colors.blueAccent, size: mediumIconSize),
trailing: Icon(Icons.keyboard_arrow_right),
selected: true,
)),
])),
onTap: () => _showLoading(),
)),
);
}
}
Note: you can also style the SnackBar.
Result:
In my app on the Devices page i currently have 2 example devices(as Hero widget), but in the end i want the user to be able to add and delete devices.
So i added a Floating Action Button to add a new device(first image).
When it gets pressed there should pop up a field to enter a Name.
After choosing a name the new Device should be visible on the Devices (Hero)page. And if it gets selected i wanna come to a Device Page like on the second image.
If someone has an idea how i could realize that i would be very thankful!
Code of the Hero Devices Page:
class DevicesPageHero extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: color_1,
title: Text('Devices'),
),
body: Center(
child:Row(
children: [
Hero(
tag: 'matrix1',
child: GestureDetector(
onTap: () => Navigator.push(context, MaterialPageRoute(builder: (context) => MatrixPageOne())),
child: Column(
children: <Widget>[
Image( image: new AssetImage('imgs/matrix1.png'),
height: 100,
width: 100,),
Text("Matrix Kitchen", style: mytextStyle,),
]
)
),
),
Hero(
tag: 'matrix2',
child: GestureDetector(
onTap: () => Navigator.push(context, MaterialPageRoute(builder: (context) => MatrixPageTwo())),
child: Column(
children: <Widget>[
Image( image: new AssetImage('imgs/matrix2.png'),
height: 100,
width: 100,),
Text("PARTY ROOM", style: mytextStyle,),
]
)
),
),
] // wrap children
)
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// Create new matrix page
},
child: Icon(Icons.add),
backgroundColor: color_3,
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat
);
}
}
Code of the Selected-Device-Page
class MatrixPageOne extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: color_1,
title: Text('Matrix Kitchen'),
),
body: Column(
children: [
Hero(
tag: 'matrix1',
child:Image( image: new AssetImage('imgs/matrix1.png'),
height: 150,
width: 150
)
),
Container(
width: MediaQuery.of(context).size.width, // returns Screen width
child: Text(" Live update Matrix Kitchen", style: TextStyle( fontSize: 15, fontFamily: "Arial", fontWeight: FontWeight.bold) ,/*textAlign: TextAlign.left*/),
),
Divider(),
Spacer(flex: 1),
Container(
width: MediaQuery.of(context).size.width,
child:Text(" Option 1 ...", textAlign: TextAlign.left,),
),
Divider(),
Spacer(flex: 1),
Container(
width: MediaQuery.of(context).size.width,
child:Text(" Option 2 ...", textAlign: TextAlign.left,),
),
Divider(),
Spacer(flex: 80),
IconButton(
icon: Icon(Icons.delete, color: Colors.red,),
onPressed: (){
//Delete Hero Page
}
)
], // Column children
),
);
}
}
You can create a new single page, then send parameter like tagName and Image to that page. On that page, you can display the previously sent data up to your liking.
For example:
..
onTap: () => Navigator.push(context, MaterialPageRoute(builder: (context) => MatrixPageTwo(
'tagName': 'matrix2',
'image': new AssetImage('imgs/matrix2.png'), height: 100, width: 100)
))),
..
And then, on that MatrixPageTwo page:
class MatrixPageTwo extends StatefulWidget {
const MatrixPageTwo({ Key key, this.image, this.tagName }) : super(key: key);
final Image image;
final String tagName;
#override
_MatrixPageTwoState createState() => _MatrixPageTwoState();
}
class _MatrixPageTwoState extends State<MatrixPageTwo> {
#override
Widget build(BuildContext context) {
return Center(
child: Text(widget.tagName),
);
}
}
I'm new to flutter, I trying to pass a value from textfield and when i click a button submit, display it in textformfield in another screen, my problem, I don't know the right way to get value
Some Code :
String txt = "";
TextEditingController controllerTxt = new TextEditingController();
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: Text('Create'),
actions: <Widget>[
FlatButton(
child: Text('Submit'),
textColor: Colors.white,
onPressed: () {
setState(() {
//txt = (controllerTxt.text);
Navigator.pushNamed(context, '/ResultPage');
});
},
),
],
),
body: new Container(
child: new Column(
children: <Widget>[
new TextField(
controller: controllerTxt,
maxLines: 5,
decoration: new InputDecoration(
),
),
],
),
),
);
}
}
class _ResultPageState extends State<ResultPage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: Text('Result'),
),
body: new Container(
padding: EdgeInsets.all(10.0),
child: new Column(
children: <Widget>[
new TextFormField(
decoration: InputDecoration(
labelText: 'Name :',
),
),
new Text("${controllerTxt.text}"),
],
),
),
);
}
}
I have done the same thing by passing data through the constructor
Navigator.push(context,
MaterialPageRoute(builder: (context) => ResultPage(controllerTxt.text)));
class ResultPage extends StatefulWidget {
final String result;
ResultPage(this.result);