send data to another flutter screen - flutter

I need this screen to receive the name (winner X) of the winner that is sent from another screen how can I do this?
on the previous screen I ask the user to type the name and I made an if, if he wins his name appears, I tried with the push navgator and I couldn't
import 'package:flutter/material.dart';
class ganhadorScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Flutter Card Example')),
backgroundColor: Colors.yellow,
body: MyCardWidget(),
),
);
}
}
class MyCardWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: Container(
width: 300,
height: 500,
padding: const EdgeInsets.all(10.0),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
color: Colors.red,
elevation: 10,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
title: Text('PARABENS', style: TextStyle(fontSize: 30.0)),
),
Image.asset("assets/images/trofeu.png"),
Text('winner X',
style: TextStyle(fontSize: 18.0))
],
),
),
),
);
}
}

You can pass data as arguments to another class like this:
class MyClass extends StatelessWidget {
final String data;
final int number;
const MyClass({required this.data, required this.number});
// or like this if you don't like named arguments:
const MyClass(this.data, this.number);
#override
Widget build(BuildContext context) {
return Container();
}
}
So if the navigator pushes MyClass widget to the screen, you will have to write it like this:
MyClass(data: "some data", number: -1);
// or without named parameters, then like this:
MyClass("some data", -1); //note that without named parameters, the order of the parameters is important!

You can pass the values through the arguments property of navigation. In the navigation action of the previous page, however you do it,
Navigator.of(context).pushNamed('MyCardWidget', arguments: variable-that-holds-users-name);
In this screen you recieve the text
final name = ModalRoute.of(context)!.settings.arguments.toString();
Now you can use it
Text(name, style: TextStyle(fontSize 17)),

Related

How to make Column scrollable when overflowed but use expanded otherwise

I am trying to achieve an effect where there is expandable content on the top end of a sidebar, and other links on the bottom of the sidebar. When the content on the top expands to the point it needs to scroll, the bottom links should scroll in the same view.
Here is an example of what I am trying to do, except that it does not scroll. If I wrap a scrollable view around the column, that won't work with the spacer or expanded that is needed to keep the bottom links on bottom:
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatefulWidget {
#override
State<MyWidget> createState() {
return MyWidgetState();
}
}
class MyWidgetState extends State<MyWidget> {
List<int> items = [1];
#override
Widget build(BuildContext context) {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: const Icon(Icons.add),
onPressed: () {
setState(() {
items.add(items.last + 1);
});
},
),
IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
setState(() {
if (items.length != 1) items.removeLast();
});
},
),
],
),
for (final item in items)
MyAnimatedWidget(
child: SizedBox(
height: 200,
child: Center(
child: Text('Top content item $item'),
),
),
),
Spacer(),
Container(
alignment: Alignment.center,
decoration: BoxDecoration(border: Border.all()),
height: 200,
child: Text('Bottom content'),
)
],
);
}
}
class MyAnimatedWidget extends StatefulWidget {
final Widget? child;
const MyAnimatedWidget({this.child, Key? key}) : super(key: key);
#override
State<MyAnimatedWidget> createState() {
return MyAnimatedWidgetState();
}
}
class MyAnimatedWidgetState extends State<MyAnimatedWidget>
with SingleTickerProviderStateMixin {
late AnimationController controller;
#override
initState() {
controller = AnimationController(
value: 0, duration: const Duration(seconds: 1), vsync: this);
controller.animateTo(1, curve: Curves.linear);
super.initState();
}
#override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: controller,
builder: (context, child) {
return SizedBox(height: 200 * controller.value, child: widget.child);
});
}
}
I have tried using a global key to get the size of the spacer and detect after rebuilds whether the spacer has been sized to 0, and if so, re-build the entire widget as a list view (without the spacer) instead of a column. You also need to listen in that case for if the size shrinks and it needs to become a column again, it seemed to make the performance noticeably worse, it was tricky to save the state when switching between column/listview, and it seemed not the best way to solve the problem.
Any ideas?
Try implementing this solution I've just created without the animation you have. Is a scrollable area at the top and a persistent footer.
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
home: SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text("My AppBar"),
),
body: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
// Your scrollable widgets here
Container(
height: 100,
color: Colors.green,
),
Container(
height: 100,
color: Colors.blue,
),
Container(
height: 100,
color: Colors.red,
),
],
),
),
),
Container(
child: Text(
'Your footer',
),
color: Colors.blueGrey,
height: 200,
width: double.infinity,
)
],
),
),
),
);
}
}

Flutter: Change text colour of a widget, when a button is pressed

I have 2 Pieces of text, which come from an API call, one in German, one translated in English, they are fed as parameters into a Basic Template, which holds custom styling of the Text. The second Text, the translation is the same colour as the background and when the Reveal button is pressed, I would like the colour to become white (visible). An image for clarity:
How would I change the colour of the second text, I am unsure due to feeding the data through the custom made templates (See code below). Any point in the right direction appreciated.
Main Class
class MistakesScreen extends StatefulWidget {
String username;
MistakesScreen({this.username});
#override
_MistakesScreenState createState() => _MistakesScreenState();
}
class _MistakesScreenState extends State<MistakesScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Hello ${widget.username}"),
),
body: Container(
child: FutureBuilder(
future: fetchGermanPhrases(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('Connection State None');
case ConnectionState.active:
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
case ConnectionState.done:
var gname = snapshot.data['gname'].toString();
var ename = snapshot.data['ename'].toString();
return BasicExerciseTemplate(textOne: gname, textTwo: ename);
default:
return Center(child: CircularProgressIndicator());
}
},
),
),
);
}
}
Templates and Button Code:
class BasicTextTemplate extends StatelessWidget {
final String text;
final Color colour;
BasicTextTemplate({this.text, this.colour});
#override
Widget build(BuildContext context) {
return Center(
child: Container(
child: Padding(
padding: const EdgeInsets.all(16),
child: Text(
text,
style: TextStyle(
color: colour,
fontSize: 30,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic,
),
),
),
width: 350,
decoration: BoxDecoration(
color: Colors.green.shade800,
borderRadius: BorderRadius.circular(8),
),
),
);
}
}
class BasicExerciseTemplate extends StatelessWidget {
final String textOne;
final String textTwo;
BasicExerciseTemplate({this.textOne, this.textTwo});
#override
Widget build(BuildContext context) {
return Center(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: BasicTextTemplate(text: textOne, colour: Colors.white),
),
Padding(
padding: const EdgeInsets.all(8.0),
child:
BasicTextTemplate(text: textTwo, colour: Colors.green.shade800),
),
RevealButton()
],
),
);
}
}
class RevealButton extends StatelessWidget {
final String textOne;
final String textTwo;
RevealButton({this.textOne, this.textTwo});
#override
Widget build(BuildContext context) {
return Center(
child: FlatButton(
child: Text('Reveal'),
color: Colors.blueAccent,
textColor: Colors.white,
onPressed: () {
print('Reveal Pressed');
},
),
);
}
}
Try this
isReveal = false;
onPressed: () {
setState(() {
IsReveal = true
});
},
BasicTextTemplate(text: textTwo, colour:!isReveal ? Colors.green.shade800:Colors.white);
To achieve what you are trying, I recommend you to use the Visibility widget. It controls whether the given child is visible or not. I think it'll be much easier.
For instance:
Visibility(
visible: myBoolean,
child: Text(
"Die Deutschen sind sehr nett",
style: TextStyle(fontSize: 20),
),
),
Simply use a function where you change the value of your boolean and trigger the setState method. That way you'll be able to hide or show your texts depending on a condition. For more info, see:
https://api.flutter.dev/flutter/widgets/Visibility-class.html

How to dynamically generate and store state of a custom stateful widget in the parent class?

I am currently stuck with dynamic generation of widget and its state maintenance.
This is my code.
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData.dark().copyWith(
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Column(
children: <Widget>[
DescriptionTextField(),
DividerAddDescription(onPressed: () => print('Add another description'))
],
),
),
),
);
}
}
class DescriptionTextField extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(color: Colors.white38),
child: TextField(
minLines: 1,
maxLines: null,
style: TextStyle(
fontSize: 16,
),
decoration: InputDecoration(
hintText: 'Enter description',
hintStyle: TextStyle(
fontSize: 16,
),
contentPadding: EdgeInsets.symmetric(
vertical: 10.0, horizontal: 10.0),
border: InputBorder.none,
),
),
);
}
}
class DividerAddDescription extends StatelessWidget {
DividerAddDescription({#required this.onPressed});
final Function onPressed;
#override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Expanded(
child: Divider(
thickness: 1,
),
),
FloatingActionButton(
onPressed: onPressed,
child: Icon(
Icons.add,
color: Color(0xFF232F34),
),
backgroundColor: Colors.orange,
),
],
);
}
}
This is how the screen looks like.
What I am trying to achieve:
when clicking on the plus button, another DescriptionTextField will be added to the Column widget.
as a new DescriptionTextField is added, if the previous DescriptionTextField has description text in it, the text should be preserved.
What I don't know how to do:
where should the description text be stored? Is it in DescriptionTextField's state? i.e. do I need to make it a Stateful widget instead?
when I have multiple DescriptionTextField, how am I supposed to store the state? e.g. the description text
You should create a List variable in your State, add the new elements there and call the setState method when adding.
class _HomeScreenState extends State<HomeScreen> {
//Create a field which hold the elements
List<DescriptionTextField> myDescriptions = List<DescriptionTextField>();
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Column(
children: <Widget>[
...myDescriptions, //Add the elements to the Column using the spread operator
DividerAddDescription(onPressed: () => setState(() => myDescriptions.add(DescriptionTextField(key: UniqueKey()))) //Adding new widget
],
),
),
),
);
}
}
I recommend you to use a key value in your DescriptionTextField widgets, because you will be adding widget dynamically and Flutter could struggle to match the respectively their states.
There are of course many improvements, but from my perspective and what I understand from your description, this may help you.

How to use Custom Widgets in flutter

I am new to Flutter and I am following Flutter's official tutorial to learn basics of flutter.
So, I want to create a reusable component named "CustomCard" and I did this:
class CustomCard extends StatelessWidget {
CustomCard({#required this.index, #required this.onPress});
final index;
final Function onPress;
#override
Widget build(BuildContext context) {
return Card(
child: Column(
children: <Widget>[
Text('Card $index'),
FlatButton(
child: const Text('Press'),
onPressed: this.onPress,
)
],
),
);
}
}
Now, to use it in MyApp, I did this:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to flutter',
home: Scaffold(
appBar: AppBar(
title: Text('hello'),
),
body: Center(
child: Text('centre'),
CustomCard(
index:'card1',
onPress: print(' this is $index')
),
),
),
);
}
}
Now my IDE says that:
The method 'CustonCard' isn't defined for the class 'MyApp'.
How to solve this?
Error in terminal:
Compiler message:
lib/main.dart:17:6: Error: Place positional arguments before named arguments.
Try moving the positional argument before the named arguments, or add a name to the argument.
CustomCard(
^^^^^^^^^^
lib/main.dart:17:6: Error: Expected named argument.
CustomCard(
^
lib/main.dart:15:21: Error: No named parameter with the name '#1'.
body: Center(
^^...
/C:/src/flutter/packages/flutter/lib/src/widgets/basic.dart:1863:9: Context: Found this candidate, but the arguments don't match.
const Center({ Key key, double widthFactor, double heightFactor, Widget child })
Edit: corrected a spelling mistake. Also adding console log.
You have got a few mistakes going on, but don't worry it happens at the very beginning. So let's step into the problems:
First, inside the body you've defined a Center Widget which only allows a single child within it but you have tried to put two Widgets (Text and CustomCard). So to put both widgets you could change it to something like this:
Center(
child: Column(
children: <Widget>[
Text('centre'),
CustomCard(...)
],
),
),
Moreover, pay attention that the onPress function takes a Function as argument but you are passing the result of print(...) which is void. Simply change it to:
CustomCard(index: index, onPress: () => print(' this is $index'))
Finally, I think you missed to define the index variable. Simply add:
String index = "card1";
Hey Please check the updated code here. There are couple of compile errors as you are wrapping up both Text and you CustomWidget in Center where it accepts only one child widget and also at the onPress method some code change required.
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to flutter',
home: Scaffold(
appBar: AppBar(
title: Text('hello'),
),
body: Center(
child:Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('centre'),
CustomCard(
index:'card1',
onPress: onPress
)
],
)
)
),
);
}
onPress(index){
print("this is $index");
}
}
class CustomCard extends StatelessWidget {
CustomCard({#required this.index, #required this.onPress});
final index;
final Function onPress;
#override
Widget build(BuildContext context) {
return Card(
child: Column(
children: <Widget>[
Text('Card $index'),
FlatButton(
child: const Text('Press'),
onPressed: (){
this.onPress(index);
},
)
],
),
);
}
}
child: Center(
child: Row(
children: <Widget>[
_box(), //Custom pin view
_box(), //Custom pin view
_box(), //Custom pin view
_box(),//Custom pin view
],
),
)
and Custom Widgets (_box) Code
Widget _box() {
return Container(
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 3),
alignment: Alignment.center,
height: 50,
width: 50,
child: TextField(
keyboardType: TextInputType.number,
maxLength: 1,
decoration: InputDecoration(border: InputBorder.none, counterText: ''),
),
decoration: BoxDecoration(border: Border.all(color: Colors.blue)),
);
}

How to make flutter TextField at bottom of screen show over IME

My page is a SingleChildScrollView,it's has a column as child .And I have a TextField at bottom of the screen.
How can I make the TextField show over of IME when IME is expend.
now the TextField is covered by IME. And it is invisible,util scroll manually.
demo code
import 'package:flutter/material.dart';
class Demo extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
elevation: 0.0,
title: new Text(
'title',
),
),
body: new Home(),
),
);
}
}
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new SingleChildScrollView(
child: new Column(
children: <Widget>[
new ImageZone(),
new Div(),
new TextEditZone(),
new Div(),
],
),
);
}
}
class ImageZone extends StatefulWidget {
#override
State<StatefulWidget> createState() => new ImageZoneState();
}
class ImageZoneState extends State<ImageZone> {
#override
Widget build(BuildContext context) {
return new Material(
elevation: 1.0,
color: Colors.white,
child: new Container(
height: 380.0,
width: double.infinity,
child: new Icon(
Icons.access_time,
size: 360.0,
),
),
);
}
}
class Div extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new SizedBox(
height: 12.0,
);
}
}
class TextEditZone extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return new TextEditZoneState();
}
}
class TextEditZoneState extends State<TextEditZone> {
#override
Widget build(BuildContext context) {
return new Material(
elevation: 1.0,
child: new Container(
width: double.infinity,
color: Colors.white,
padding: new EdgeInsets.all(16.0),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new TextField(
style: new TextStyle(fontSize: 14.0),
textAlign: TextAlign.end,
),
new Div(),
new TextField(
style: new TextStyle(fontSize: 14.0),
textAlign: TextAlign.end,
),
new Div(),
new TextField(
style: new TextStyle(fontSize: 14.0),
textAlign: TextAlign.end,
),
],
),
),
);
}
}
screen Shot:
What I want:
TextField auto scroll over IME when I click one of TextField.
Your problem was solved in this example here
, Please go through and wrap all your TextField 's inside EnsureVisibleWhenFocused and this will bring the TextField just above the keyboard.
Regards,
Mahi