Why does my text suddenly get whitespace when applying a style? - flutter

Here is my flutter code:
class LandingScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
LandingPageForm(),
],
),
);
}
}
class LandingPageForm extends StatefulWidget {
#override
LandingPageFormState createState() {
return LandingPageFormState();
}
}
final headerStyle = TextStyle();
class LandingPageFormState extends State<LandingPageForm> {
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Container(
color: Colors.grey,
padding: EdgeInsets.all(10),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
color: Colors.amber,
child: FittedBox(
child: Text(
'Hey there!',
style: headerStyle,
),
fit: BoxFit.fitWidth,
),
),
],
),
));
}
}
If I remove the headerStyle from the fitted textbox, the padding above disappears which is how I want it. As soon as I add a style though this whitespace appears and I have no idea what is causing it.
What is going on?

Closing this - it seems there is a persistent caching issue with styles on my device. Closing and reopening the app fixed the issue.

Related

The following _TypeError was thrown building -Exception caught by widgets library

The following _TypeError was thrown building
BlurImagePageScaffold(dirty): type 'List' is not a subtype of
type 'Widget'
I'm getting above error when Im trying to run my code. I have included my codes files below. how to solve this.
blur_image_page_scaffold.dart
import 'dart:ui';
import 'package:flutter/material.dart';
class BlurImagePageScaffold extends StatelessWidget {
const BlurImagePageScaffold({Key? key,this.imagePath, this.body}) : super(key: key);
final body;
final imagePath;
#override
Widget build(BuildContext context) {
return Container(
height: double.infinity,
width: double.infinity,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
image: DecorationImage(
image: AssetImage(imagePath),fit: BoxFit.fill),
),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX:10, sigmaY:10),
child: Container(
color: Colors.black.withOpacity(0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
body
],
)
),
),
);
}
}
hello.dart
import 'package:flutter/material.dart';
import 'package:new_chat_app/components/blur_image_page_scaffold.dart';
import 'package:new_chat_app/components/lets_start.dart';
import 'package:new_chat_app/components/logo.dart';
import 'package:new_chat_app/components/terms_and_conditions.dart';
class Hello extends StatelessWidget {
const Hello({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return BlurImagePageScaffold(imagePath: 'images/bg.jpg', body: [
Logo(),
Column(
children: [
Text('Hello'),
Column(
children: [
Text("Whatsapp is a Cross-Platform"),
Text("mobile messaging with friends"),
Text("all over the world"),
],
),
TermsAndConditions(),
LetsStart(),
],
),
]);
}
}
Simply set children to body
Like so:
BackdropFilter(
filter: ImageFilter.blur(sigmaX:10, sigmaY:10),
child: Container(
color: Colors.black.withOpacity(0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: body,
)
),
),
)

Flutter : I want to change an image when you tap the image, and others are not affected by the tap

I am creating a simple app in Flutter. There are 7 images on 1 screen. I need a function that you can change an image when you tap one of the images. However, now when I tap an image, the other 6 images are also changed. I made a variable "isReal" to put into buildButton() and "isReal" would be switched true and false in the For statement which switch "isReal" in buildButton(). But, that did not work. Could you give me some advice on this problem? Thank you.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:audioplayers/audioplayers.dart';
class Screen extends StatefulWidget {
#override
_ScreenState createState() => _ScreenState();
}
class _ScreenState extends State<Screen> {
bool isReal = true;
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
backgroundColor: Colors.teal[100],
// appBar: AppBar(
// title: Text('AnimalSounds'), backgroundColor: Colors.teal),
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
buildButton('cat.mp3', Colors.red, 'images/cat.png',
'images/cat_real.jpg'),
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
buildButton('dog.mp3', Colors.yellow, 'images/dog.png',
'images/cow.png'),
buildButton('cow.mp3', Colors.orange, 'images/cow.png',
'images/dog.png'),
])),
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
buildButton('pig.mp3', Colors.green, 'images/pig.png',
'images/elephant.png'),
buildButton('elephant.mp3', Colors.teal,
'images/elephant.png', 'images/rooster.png'),
buildButton('rooster.mp3', Colors.blue,
'images/rooster.png', 'images/pig.png'),
])),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
buildButton('goat.mp3', Colors.purple, 'images/goat.jpg',
'images/pig.png'),
],
)),
],
),
)));
}
Expanded buildButton(sound, color, simpleImage, realImage) {
return Expanded(
child: FlatButton(
onPressed: () {
setState(() {
isReal = !isReal;
});
final player = AudioCache();
player.play(sound);
},
color: color,
child: isReal ? Image.asset(simpleImage) : Image.asset(realImage),
));
}
}
Ok, you have variable isReal that is the same for entire class (i.e. each button use the same variable). So when you change it's value by tapping on one button it affects all other buttons as well.
To solve this issue I would recommend to move button implementation into a separate Statefull widget. This way you can keep your Screen class as Stateless.
UPD:
Obviously you should watch some tutorials on how to make this on your own. But just for this time this is how it should look like after you separate widgets.
What I did here is:
Create new widget class FlipButton
Move code from your method into build function of new widget
Add parameters to constructor
This way when each FlipButton will have it's own isReal variable.
NOTE: I didn't try to compile it so there might be some errors.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:audioplayers/audioplayers.dart';
class Screen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
backgroundColor: Colors.teal[100],
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
//replace all occurances on `buildButton` method with new widget
FlipButton(sound: 'cat.mp3', color: Colors.red, simpleImage: 'images/cat.png', realImage: 'images/cat_real.jpg'),
Expanded(
child: Row(crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[
FlipButton(sound: 'dog.mp3', color: Colors.yellow, simpleImage: 'images/dog.png', realImage: 'images/cow.png'),
FlipButton(sound: 'cow.mp3', color: Colors.orange, simpleImage: 'images/cow.png', realImage: 'images/dog.png'),
])),
Expanded(
child: Row(crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[
FlipButton(sound: 'pig.mp3', color: Colors.green, simpleImage: 'images/pig.png', realImage: 'images/elephant.png'),
FlipButton(sound: 'elephant.mp3', color: Colors.teal, simpleImage: 'images/elephant.png', realImage: 'images/rooster.png'),
FlipButton(sound: 'rooster.mp3', color: Colors.blue, simpleImage: 'images/rooster.png', realImage: 'images/pig.png'),
])),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
FlipButton(sound: 'goat.mp3', color: Colors.purple, simpleImage: 'images/goat.jpg', realImage: 'images/pig.png'),
],
)),
],
),
),
),
);
}
}
/// You can copy this widget into separate file for better formatting
///
class FlipButton extends StatefulWidget {
//declare final variables
final String sound;
final Color color;
final String simpleImage;
final String realImage;
//constructor for this class
const FlipButton({
Key? key,
required this.sound,
required this.color,
required this.simpleImage,
required this.realImage,
}) : super(key: key);
#override
_FlipButtonState createState() => _FlipButtonState();
}
class _FlipButtonState extends State<FlipButton> {
//inside the state declare variable that is about to change
bool isReal = false;
#override
Widget build(BuildContext context) {
return Expanded(
child: FlatButton(
onPressed: () {
setState(() {
isReal = !isReal;
});
final player = AudioCache();
player.play(sound);
},
color: widget.color,
child: isReal ? Image.asset(widget.simpleImage) : Image.asset(widget.realImage),
));
}
}
You can use Random class from dart:math to generate the next random image.
Exemple :
int imageNumber = 1;
void updateImage() {
setState(() {
//Random.nextInt(n) returns random integer from 0 to n-1
imageNumber = Random().nextInt(7) + 1;
});
}
#override
Widget build(BuildContext context) {
return Center(
child: Expanded(
child: Padding(
padding: const EdgeInsets.all(50.0),
child: FlatButton(
child: Image.asset('images/dice$imageNumber.png'),
onPressed: () {
updateImage();
},
),
),
),
);
}

Slide Widget to left

I am trying to make this Card Widget go from this position to completely right till its not visible using animation.
How can I do that?
Later I will be adding more cards below and want them go left, up and down too, currently it's only for one card.
import 'package:flutter/material.dart';
class Swipe extends StatefulWidget {
#override
_SwipeState createState() => _SwipeState();
}
class _SwipeState extends State<Swipe> {
//bool bgColor = true;
#override
Widget build(BuildContext context) {
return Scaffold(
//backgroundColor: bgColor ? Colors.black : Colors.white,
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
padding: EdgeInsets.fromLTRB(40, 30, 40, 0),
height: 140,
width: 400,
child: Card(
child: Center(child: Text("RIGHT")),
color: Colors.green,
),
),
]),
),
);
}
}
There is a widget called Dismissible. Example:
Dismissible(
onDismissed: (direction) {
onWidgetRemove();
},
confirmDismiss: (direction) {
return confirmRemoveWidget();
},
key: ValueKey(someItemId),
child: MyWidget())
Note that key must not be null. confirmDismiss is optional and usually used with dialog to confirm action.
Small tip: Rather than using SingleChildScrollView+Column use ListView

Screen not updating in a statefulWidget in Flutter

I have a statefulWidget in Flutter like this:
class GameScreen extends StatefulWidget {
#override
GameScreenState createState() => GameScreenState();
}
class GameScreenState extends State<GameScreen> {
List<String> selectedWord = ['h', 'e', 'l', 'l', 'o'];
Widget _letterInput() {
return Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
for (var letter in selectedWord) LetterInput(letter: letter)
],
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
_letterInput(),
],
)),
);
}
}
class LetterInput extends StatelessWidget {
LetterInput({this.letter});
final String letter;
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.fromLTRB(5, 0, 5, 0),
decoration: BoxDecoration(
border: BorderDirectional(
bottom: BorderSide(width: 6.0, color: Colors.green))),
child: Text(letter,
textAlign: TextAlign.center,
style:
GoogleFonts.acme(fontSize: 28.0, fontWeight: FontWeight.w400)));
}
}
The problem is that when I first launch the app with this widget, I can see hello on the screen, but if I go on and change hello to hellos in selectedWord, that does not update the screen and it still shows me hello even though the hot reload is turned on. I have to go and restart the app so it shows me hellos. How could I fix this?
In my experience, hot reload keeps states. Try hot restart instead?
Referring to your comment, if you want to keep using hot reload, I suggest you pull out the variable to your widget itself (if that is an option for you), like this:
class GameScreen extends StatefulWidget {
final List<String> selectedWord = ['h', 'e', 'l', 'l', 'o'];
#override
GameScreenState createState() => GameScreenState();
}
class GameScreenState extends State<GameScreen> {
Widget _letterInput() {
return Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
for (var letter in widget.selectedWord) LetterInput(letter: letter)
],
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
_letterInput(),
],
)),
);
}
}

Flutter: Calling SetState() from another class

I am trying to make a simple image that appears or disappears when a button is pushed. This button resides in a separate class to the image, so in Flutter this creates a massive headache of an issue.
I have read many forums on this and I have tried all the solutions posed but none of them are working for me.
What I am trying to do:
class SinglePlayerMode extends StatefulWidget {
#override
SinglePlayerModeParentState createState() => SinglePlayerModeParentState();
}
class SinglePlayerModeParentState extends State<SinglePlayerMode> {\
bool coinVisible = false;
toggleCoin() {
setState(() {
coinVisible = !coinVisible;
});
}
Widget topMenuRow() {
return Stack(
children: [
Column(
children: [
coinVisible == true ?
Padding(
padding: EdgeInsets.all(50),
child: Container(
height: 60,
width: 60,
color: Colors.blueGrey[0],
decoration: BoxDecoration(
color: Colors.blueAccent,
image: DecorationImage(
image: ExactAssetImage('lib/images/coin_head.jpg'),
fit: BoxFit.cover,
),
),
),
) : Container(
height: 60,
width: 60,
color: Colors.black,
),
],
),
],
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
child: ListView(
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0),
children: [
topMenuRow(),
SizedBox(height: 40),
],
),
),
);
}
And this is the separate class which I would like to trigger the SetState() on coinVisible from:
class dropDownMenu extends StatefulWidget { #override
_dropDownMenuState createState() => _dropDownMenuState();
}
class _dropDownMenuState extends State<dropDownMenu> {
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget> [
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
child: Opacity(
opacity: 0.0,
child: FloatingActionButton(
heroTag: null,
onPressed: (){
//SOMEHOW CALL SetState() ON coinVisble HERE!
},
),
),
);
}
}
But nothing I have tried is working, and I have lost hours.
It simple, you need to send your SinglePlayMode::toggleCoin function as callback to dropDownMenu class.
class dropDownMenu extends StatefulWidget {
final _callback; // callback reference holder
//you will pass the callback here in constructor
dropDownMenu( {#required void toggleCoinCallback() } ) :
_callback = toggleCoinCallback;
#override
_dropDownMenuState createState() => _dropDownMenuState();
}
class _dropDownMenuState extends State<dropDownMenu> {
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget> [
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
child: Opacity(
opacity: 0.0,
child: FloatingActionButton(
heroTag: null,
onPressed: (){
widget?._callback(); // callback calling
},
),
),
);
}
}
Then when you create a dropDownMenu class instance in your SinglePlayerMode class you will do
dropDownMenu(
toggleCoinCallback: toogleCoin,
);