Is anyone know how to change a text style on Flutter when the button pressed?
As example, i have a code like this :
class _scanningState extends State<scan> {
String strText = 'ABCDEFG';
#override
Widget build(BuildContext context) {
return Scaffold(backgroundColor: Colors.blue,
body: new Column(
children: <Widget>[
new Text(strText),
new RaisedButton(
child: new Text('Button'),
onPressed: (){
//Change text style of strText()???
},
)
],
)
);
}
class _scanningState extends State<scanning> {
bool pressed = true;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue,
body: new Column(
children: <Widget>[
new Text(strText,
style: pressed
? TextStyle(color: Colors.black)
: TextStyle(color:Colors.green),
),
new RaisedButton(
child: new Text(
'Change color'),
onPressed: () {
setState(() {
pressed = !pressed;
});
},
)
],
));
}
Maybe you want to change the sibling text. The concept is the same. Happy Flutter
I recommend you to read about Stateful Widgets https://flutter.io/tutorials/interactive/#stateful-stateless
class _scanningState extends State<scanning> {
bool pressed = false;
String strText = 'ABCDEFG';
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue,
body: new Column(
children: <Widget>[
new Text(strText),
new RaisedButton(
child: new Text(
'Button',
style: pressed
? TextStyle(fontSize: 30.0)
: TextStyle(fontSize: 10.0),
),
onPressed: () {
//Change text style of strText()???
setState(() {
pressed = !pressed;
});
},
)
],
));
}
Related
I have two screens. In screen1 I have an appbar and a card in the body. IF I click the card it should take me to new screen 'screen2'. I am getting the screen2 but I am also getting the appbar from screen1 as well.. I am doing a push from screen1 to screen2.. May I know how to avoid the appbar from the screen1 in screen2? I have onTap method in VideoCard widget which pushes to screen2... it looks like body of the screen1 is being replaced by screen2.. instead i need to push to screen2 from screen1...
enter image description here
class _AllVideosPageTabletState extends State<AllVideosPageTablet> {
bool searchFlag = false;
String searchText = '';
#override
void initState() {
searchFlag = false;
searchText = '';
super.initState();
}
#override
Widget build(BuildContext context) {
final isLandscape = MediaQuery.of(context).orientation ==
Orientation.landscape;
return Scaffold(
body: Container(
padding: EdgeInsets.all(10.0),
child: Column(
children: [
CupertinoSearchTextField(
onChanged: (value) {
if (value != '') {
setState(
() {
searchFlag = true;
searchText = value;
},
);
}
},
onSubmitted: (value) {
if (value != '') {
setState(
() {
searchFlag = true;
searchText = value;
},
);
}
},
),
Divider(),
Row(
children: [
IconButton(
icon: Image.asset('lib/assets/icons/back.png'),
onPressed: () {
Navigator.pop(context);
},
),
Expanded(
child: Container(
child: Center(
child: Text(
'All Videos',
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
color: '#D86300'.toColor(),
),
),
),
),
),
],
),
searchFlag
? SearchResultsListView(searchText)
: Expanded(
child: FutureBuilder(
future: VideoXML().getDataFromXML(context),
builder: (context, data) {
if (data.hasData) {
List<Video> videoList = data.data;
return GridView.count(
scrollDirection: Axis.vertical,
crossAxisCount: isLandscape ? 4 : 2,
crossAxisSpacing: 10.0,
mainAxisSpacing: 10.0,
children: videoList.map(
(video) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: VideoCard(
video.title,
video.name,
video.image,
),
);
},
).toList(),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
),
],
),
),
);
}
Flutter works in a way that every new screen is based on a new Scaffold widget. This way you can customize, whether to show the appBar at all or should be display different appBar on different screens.
For example:
Screen 1 should be a scaffold of its own:
class FirstScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title:'Screen 1'),
body: InkWell(onTap: () => Navigator.of(context).pushedName(routeToSecondScreen),
child: Text('Navigate to secondScreen'),
);
);
}
}
Screen 2 should be a scaffold of its own:
class SecondScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title:'Screen 2'),
body: Text('Screen 2'),
);
}
}
This way you can have different appBars for each screen. If you do not wish to display appBar on the second screen at all, simply do not specify appBar on the second screen as follows.
class SecondScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Text('Screen 2'),
);
}
}
I want to show entered text in scrambled form. ie, each letter of the word need to display in individual Container in a row. For this, I am taking text input, storing it in List<String> and then scrambling it using shuffle() and then using List.generate to return Container with Text, as below:
List<Widget> _generateJumble(String input) {
inputList = input.split('');
var shuffleList = inputList.toList()..shuffle();
print(shuffleList);
return List<Widget>.generate(shuffleList.length, (int index) {
return Container(
width: 50,
color: Colors.blue,
child: Text(shuffleList[index].toString(),
style: TextStyle(color: Colors.white),
)
);
});
}
I am calling above method onTap of a button upon which the scrambled form of the input should be displayed. But I am not sure how to display the result of above method in UI. How should I use this method so that the returning Container based on shuffleList.length will be displayed in UI as below ?
RaisedButton(
onPressed: () {},
child: Text('Clear'),
)
],
),
),
Row(
children: <Widget>[
// ? _displayJumble()
]
)
This is my solution:
1) Press a button, scrable the string and set it to the a list
2) setState and show the list to the user
This is the widget code:
class _MyHomePageState extends State<MyHomePage> {
List<String> inputList = [];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Wrap(
children: inputList.map((s) {
return Container(
width: 50,
color: Colors.blue,
child: Text(
s,
style: TextStyle(color: Colors.white),
),
);
}).toList(),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_generateJumble('Random string');
});
},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
List<Widget> _generateJumble(String input) {
inputList = input.split('');
inputList = inputList.toList()..shuffle();
print(inputList);
}
}
I used the widget Wrap because automatically wrap the widget when there is no space available for it. You can use whatever you like to use.
This is the screen result:
Before press the button:
After press the button:
Please check the below solution of it, I have used the Wrap widget for it
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutterlearningapp/colors.dart';
class HomeScreen extends StatefulWidget {
var inputVales;
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _HomeScreen();
}
}
class _HomeScreen extends State<HomeScreen> {
List<String> charcaterArray = new List<String>();
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("Home"),
),
body: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: TextField(
decoration: InputDecoration(labelText: 'Enter Words'),
onChanged: (text) {
setState(() {
widget.inputVales = text;
charcaterArray.clear();
for (var i = 0; i < widget.inputVales.length; i++) {
var character = widget.inputVales[i];
if (character != " ") {
charcaterArray.add(character);
}
}
});
},
),
),
Wrap(
spacing: 6.0,
runSpacing: 6.0,
children:
List<Widget>.generate(charcaterArray.length, (int index) {
return Container(
height: MediaQuery.of(context).size.height * 0.1,
width: MediaQuery.of(context).size.width * 0.1,
decoration: BoxDecoration(
color: Colors.lightGreen,
borderRadius: BorderRadius.all(Radius.elliptical(4.0, 4.0)),
),
child: Center(
child: Text(
charcaterArray[index],
style:
TextStyle(color: Colors.deepOrange, fontSize: 20.0),
),
),
);
/*Chip(
label: Text(charcaterArray[index]),
onDeleted: () {
setState(() {
charcaterArray.removeAt(index);
});
},
);*/
}),
)
],
));
}
}
And here is the output of it
in flutter I need that when I call setstate, it only rebuilds a widget
I put 2 children in a stack, I need that when a button is pressed, only the second one is rebuilt.
bool popup = false;
Scaffold(
appBar: AppBar(
title: const Text('TEST'),
actions: <Widget>[
IconButton( // + BUTTON
icon: Icon(Icons.add),
onPressed: () {
setState(() {
popup = true;
});
},
),
IconButton( // - BUTTON
icon: Icon(Icons.remove),
onPressed: () {
setState(() {
popup = false;
});
),
],
),
body: SafeArea(
child: Stack(
children: <Widget>[
Container( // FIRST WIDGET
key: ValueKey(1),
child: Text("Random - "+new Random().nextInt(20).toString())
),
popup ? Center(child: Text("abc")) : Text("") , // SECOND WIDGET
],
),
),
);
I expect that when I press the "+" button only the second widget will be re-built, but now it will rebuild all the contents of the stack.
thank you all.
From the official docs we can read:
"When setState() is called on a State, all descendent widgets rebuild. Therefore, localize the setState() call to the part of the subtree whose UI actually needs to change. Avoid calling setState() high up in the tree if the change is contained to a small part of the tree."
My suggestion, and I use it most of the times, is separate the widget that you want to rebuild in a new StatefulWidget. This way the setState only will be rebuild that widget.
class MyAppBar extends StatefulWidget
...
class _MyAppBarState extends State<MyAppBar> {
bool popup = false;
#override
Widget build(BuildContext context) {
return AppBar(
title: const Text('TEST'),
actions: <Widget>[
IconButton( // + BUTTON
icon: Icon(Icons.add),
onPressed: () {
setState(() {
popup = true;
});
},
),
IconButton( // - BUTTON
icon: Icon(Icons.remove),
onPressed: () {
setState(() {
popup = false;
});
),
],
),
}
Then call it in your Scaffold:
Scaffold(
appBar: MyAppBar(),
Other method I can suggest is using ValueNotifier or notifyListeners(). Please read this page Avoid rebuilding all the widgets repetitively. It is well explained.
Another option is to use ValueListenableBuilder:
class _MyHomePageState extends State<MyHomePage> {
final ValueNotifier<bool> popup = ValueNotifier<bool>(false);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('TEST'),
actions: <Widget>[
IconButton(
// + BUTTON
icon: Icon(Icons.add),
onPressed: () {
popup.value = true;
}),
IconButton(
// - BUTTON
icon: Icon(Icons.remove),
onPressed: () {
popup.value = false;
})
],
),
body: Center(
child: ValueListenableBuilder<bool>(
valueListenable: popup,
builder: (context, value, _) {
return Stack(
children: [
Text("Random - " + new Random().nextInt(20).toString()),
popup.value ? Center(child: Text("abc")) : Text(""),
],
);
}),
),
);
}
}
You can use StreamBuilder:
StreamController<bool> popup = StreamController<bool>();
#override
void dispose() {
popup.close();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('TEST'),
actions: <Widget>[
IconButton( // + BUTTON
icon: Icon(Icons.add),
onPressed: () => popup.add(true),
),
IconButton( // - BUTTON
icon: Icon(Icons.remove),
onPressed: () => popup.add(false),
),
],
),
body: SafeArea(
child: Stack(
children: <Widget>[
Container( // FIRST WIDGET
key: ValueKey(1),
child: Text("Random - "+new Random().nextInt(20).toString())
),
StreamBuilder<bool>(
stream: popup.stream,
initialData: false,
builder: (cxt, snapshot) {
return snapshot.data ? Center(child: Text("abc")) : Text("");
},
)
],
),
),
);
}
Remove the setState from the widget you don't want to be changed. And only use setState for the ones you need to rebuild
Or you can consider using inheritedModel widget
Here is the example from where you can learn how to build an Inherited model widget to update only specific widgets rather than the whole widgets.
https://medium.com/flutter-community/flutter-state-management-setstate-fn-is-the-easiest-and-the-most-powerful-44703c97f035
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.
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);