My problem is that : The listview does not appear at the first launch of app but after a hot reload it appears.
It's the first time I meet this bug.
That's my code :
#override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.black,
body: new ListView.builder(
itemCount: toutesLesCartes.length,
itemBuilder: (context, count) {
Carte carte = toutesLesCartes[count];
String nom = carte.nomCarte;
String image = carte.imageCarte;
return new Dismissible(
key: new Key(nom),
direction: DismissDirection.endToStart,
child: new Container(
margin: EdgeInsets.all(5.0),
child: new Card(
color: Colors.transparent,
elevation: 10.0,
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Image.network(image, width: 150.0, height: 150.0,),
new CustomText(nom, factor: 2.0,),
],
),
),
),
background: new Container(
padding: EdgeInsets.only(right: 20.0),
color: Colors.red,
child: new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new CustomText("Supprimer"),
new Icon(Icons.delete, color: Colors.white,)
],
),
),
onDismissed: (direction) {
setState(() {
toutesLesCartes.removeAt(count);
nombreCarteChoisiValeur--;
});
},
);
}
),
);
}
I have an idea but it's strange : before, I using the Visibility widget so it is possible that it comes from a possible "cache" of the application?
All that will look at this post and help me, thank you very much!
Have a nice day !
Likely because toutesLesCartes.length is 0.
you can check this using the debugger or display something when the length is 0 eg
#override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.black,
body: new ListView.builder(
itemCount: toutesLesCartes.length, //* place breakpoint here
itemBuilder: (context, count) {
Carte carte = toutesLesCartes[count];
String nom = carte.nomCarte;
String image = carte.imageCarte;
if(toutesLesCartes == null || toutesLesCartes.length == 0){
return CircularProgressIndicator(); //you should see loading animation if list is empty
}
return new Dismissible(
key: new Key(nom),
direction: DismissDirection.endToStart,
child: new Container(
margin: EdgeInsets.all(5.0),
child: new Card(
color: Colors.transparent,
elevation: 10.0,
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Image.network(image, width: 150.0, height: 150.0,),
new CustomText(nom, factor: 2.0,),
],
),
),
),
background: new Container(
padding: EdgeInsets.only(right: 20.0),
color: Colors.red,
child: new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new CustomText("Supprimer"),
new Icon(Icons.delete, color: Colors.white,)
],
),
),
onDismissed: (direction) {
setState(() {
toutesLesCartes.removeAt(count);
nombreCarteChoisiValeur--;
});
},
);
}
),
);
}
The solution would be to use a FutureBuilder
Word of warning: The application will run the build method multiple times, it's good practice to place anything you don't want to be repeatedly called (like database calls) outside of the method.
Related
I'm building List of questions for my Quizzler app and want to access the question one by one but can't able to add the list of my questions in Text function of my app... So how should I add my list of strings to Text to display them on screen one by one?
enter image description here
class QuizPage extends StatefulWidget {
#override
_QuizPageState createState() => _QuizPageState();
}
class _QuizPageState extends State<QuizPage> {
List<Widget> scorekeeper = [];
List<String> questions = [
'You can lead a cow down stairs but not up stairs.',
'Approximately one quarter of human bones are in the feet.',
'A slug\'s blood is green.'
];
int questionNum = 0;
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
const Expanded(
flex: 3,
child: Padding(
padding: EdgeInsets.all(10.0),
child: Center(
child: Text(
questions[questionNum],
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25.0,
color: Colors.white,
),
),
You can use ListView.builder like this:
ListView.builder(
itemCount: questions.length,
itemBuilder: (_, i) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Center(
child: Text(
questions[i],
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25.0,
color: Colors.white,
),
)
)
);
}
);
And remove key word const.
I have been experimenting with Flutter trying to recreate an app that I wrote for Android 5 years ago. But I can't seem to get the layout to work very well.
I have tried a number of different widgets, but each time I try something, it seems like I am taking 2 steps forward and 3 steps back.
The app is going to be vertical position only.
Simple banner image at the top.
A trivia question.
Radio button group with 4 answers.
Then 2 buttons - 'Check Answer' and 'Skip Question'
Bottom bar
I am trying to make sure that the radio buttons and the buttons don't bounce around when the question changes.
This is what I have
This is what I would like
And this is the code that I have been fighting with.
Any help or tips would be greatly appreciated.
class _MyHomePageState extends State<MyHomePage> {
final TriviaBloc _triviaBloc = TriviaBloc();
TriviaQuestion _initTriviaQuestion = new TriviaQuestion('', '', '', '', '', 1, 1);
String _selectedAnswer = "";
TextStyle _answerStyle = new TextStyle(textBaseline: TextBaseline.alphabetic, fontStyle: FontStyle.normal, fontFamily: 'QarmicsansAbridged', fontSize: 16);
#override
void dispose() {
_triviaBloc.dispose();
super.dispose();
}
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.orangeAccent,
body: SafeArea(
minimum: const EdgeInsets.all(16.0),
child:
Column(children: [
ImageBanner("assets/header_2.jpg"),
Expanded(
child:
StreamBuilder<TriviaQuestion>(
initialData: _triviaBloc.getInitialTriviaQuestion(),
//_initTriviaQuestion,
stream: _triviaBloc.triviaQuestionStream,
//initialData: _triviaBloc.getInitialTriviaQuestion(),
//builder: (BuildContext context, AsyncSnapshot<TriviaQuestion> snapshot)
builder: (BuildContext context, snapshot) {
//_triviaBloc.getTriviaQuestion(snapshot, context);
if (snapshot.data != null) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(height: 15),
Padding(
padding: EdgeInsets.all(2.0),
child: TriviaAutoSizeText(context, snapshot.data.Question),
),
RadioButtonGroup(
labels: <String>[
snapshot.data.IncorrectAnswer1,
snapshot.data.IncorrectAnswer2,
snapshot.data.CorrectAnswer,
snapshot.data.IncorrectAnswer3
],
labelStyle: _answerStyle,
onSelected: (String selected) => _selectedAnswer = selected),
//),
SizedBox(height: 10),
new InkWell(
onTap: () => {_triviaBloc.checkAnswer(QuestionAnswered(_selectedAnswer))},
child: new Container(
width: MediaQuery.of(context).size.width * 0.5,
height: 50.0,
decoration: new BoxDecoration(
color: _butttonInteriorColour,
//Colors.blueAccent,
border:
new Border.all(color: Colors.white, width: 1.0),
borderRadius: new BorderRadius.circular(20.0),
),
child: new Center(
child: new Text(
'Check Answer',
style: new TextStyle(
fontSize: 18.0, color: Colors.white),
),
),
),
),
SizedBox(height: 10),
new InkWell(
onTap: () =>
{_triviaBloc.getTriviaQuestion(snapshot, context)},
child: new Container(
width: MediaQuery.of(context).size.width * 0.5,
height: 50.0,
decoration: new BoxDecoration(
color: _butttonInteriorColour,
//Colors.blueAccent,
border:
new Border.all(color: Colors.white, width: 1.0),
borderRadius: new BorderRadius.circular(20.0),
),
child: new Center(
child: new Text(
'Next Question',
style: new TextStyle(
fontSize: 18.0, color: Colors.white),
),
),
),
),
],
);
} else {
return Center(child: CircularProgressIndicator());
}
;
}),
)]),
),
bottomNavigationBar: buildBottomNav(context),
);
}
}
So you want the 4 button group and the 2 buttons at the bottom without changing position ?
Maybe a Spacer will help with that
if (snapshot.data != null) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max, //replace this to fill everything
children: <Widget>[
SizedBox(height: 15),
Padding(
padding: EdgeInsets.all(2.0),
child: TriviaAutoSizeText(context, snapshot.data.Question),
),
Spacer(), //add the spacer here
RadioButtonGroup(
labels: <String>[
I have a long text and I need to show the scrollbar by default when the user enters my page.
Currently, the bars not shown until the user click over the text and this, not good behavior because the user could leave the page without notice that there is some unread text.
My code:
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(15.0),
child: Center(
child: Column(
children: <Widget>[
Image.asset(
"assets/images/logo.png",
height: 200.0,
),
SizedBox(
height: 40,
),
Expanded(
child: Scrollbar(
child: SingleChildScrollView(
child: Text("Long Text Here ...",
textDirection: TextDirection.rtl,
style: TextStyle(fontSize: 17.2),
),
),
),
),
SizedBox(
height: 50,
),
Row(
children: <Widget>[
Expanded(
child: RaisedButton(
child: Text("Continue"),
onPressed: () {
MaterialPageRoute route = MaterialPageRoute(
builder: (BuildContext context) => MainPage());
Navigator.of(context).push(route);
},
),
),
SizedBox(
width: 20.0,
),
RaisedButton(
child: Text("Close"),
onPressed: () {
exit(0);
},
),
],
)
],
),
),
),
);
}```
As of Flutter version 1.17, on Scrollbar you can set isAlwaysShown to true, but you must set the same controller for your Scrollbar and your SingleChildScrollView (and that applies to any other scrollable Widget as well).
Have in mind that, for the Scrollbar to be visible, there must be enough items to scroll. If there are not, the Scrollbar won't be shown.
Full working example:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: MyWidget(),
),
);
}
}
class MyWidget extends StatefulWidget {
#override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
final _scrollController = ScrollController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(15.0),
child: Center(
child: Column(
children: <Widget>[
// ...
Expanded(
child: Scrollbar(
controller: _scrollController, // <---- Here, the controller
isAlwaysShown: true, // <---- Required
child: SingleChildScrollView(
controller: _scrollController, // <---- Same as the Scrollbar controller
child: Text(
"Long Text Here ...",
textDirection: TextDirection.rtl,
style: TextStyle(fontSize: 17.2),
),
),
),
),
// ...
],
),
),
),
);
}
}
As of v2.9.0-1.0, thumbVisiblity is the proper field to set.
Note you can set this globally for your app (or a certain subtree) using ScrollbarTheme:
return MaterialApp(
...
theme: ThemeData(
...
scrollbarTheme: ScrollbarThemeData(
thumbVisibility: MaterialStateProperty.all<bool>(true),
)
)
)
It's good to prefer themes for styling like this, so avoid doing more than once.
You'll still need to add a Scrollbar and Controller as described in other answers though.
Use draggable_scrollbar package. It provides a dragable scrollbar with option to make the scrollbar always visible. For example, you can use the following code
DraggableScrollbar.arrows(
alwaysVisibleScrollThumb: true, //use this to make scroll thumb always visible
labelTextBuilder: (double offset) => Text("${offset ~/ 100}"),
controller: myScrollController,
child: ListView.builder(
controller: myScrollController,
itemCount: 1000,
itemExtent: 100.0,
itemBuilder: (context, index) {
return Container(
padding: EdgeInsets.all(8.0),
child: Material(
elevation: 4.0,
borderRadius: BorderRadius.circular(4.0),
color: Colors.purple[index % 9 * 100],
child: Center(
child: Text(index.toString()),
),
),
);
},
),
);
'isAlwaysShown' is deprecated and shouldn't be used. Use thumbVisibility instead.
Example:
Scrollbar(
controller: ScrollController(),
thumbVisibility: true,
child: SingleChildScrollView(
child: Column(
thumbVisibility make true for show always scroll bar for list in scrollbar widget
Scrollbar(thumbVisibility: true,)
You can change the scrollbartheme to set flag isAlwaysShown true
scrollbarTheme: const ScrollbarThemeData(isAlwaysShown: true)
I am having a bit of a problem trying to create an image and text/icons below that image within a container in flutter. What I have so far , I want to include three row widgets under the image, each row will have a text widget or an icon widget but whenever i try to do this the container will just take the shape of the text/icon widgets and the image will disappear. Am I using the wrong widget in this case? I would like to have something similar to this notice the bottom section of the picture with the title, date, and location.
My code:
class EventRow extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
height: 150.0,
margin: const EdgeInsets.symmetric(
vertical: 16.0,
horizontal: 24.0,
),
child: new Stack(
children: <Widget>[
eventCardContent,
userThumbnail,
],
),
);
}
final userThumbnail = new Container(
margin: EdgeInsets.symmetric(vertical: 16.0),
alignment: FractionalOffset.centerLeft,
child: CircleAvatar(
backgroundImage: AssetImage("assets/images/letter_u.png"),
backgroundColor: Colors.white,
maxRadius: 40.0,
),
);
final eventCardContent = new Container(
margin: new EdgeInsets.only(left: 46.0),
decoration: new BoxDecoration(
shape: BoxShape.rectangle,
color: new Color(0xFFFFFFFF),
borderRadius: new BorderRadius.circular(8.0),
image: DecorationImage(
image: AssetImage("assets/images/moon_pumpkin.jpeg"),
fit: BoxFit.fill,
),
),
);
you nee d to just wrap your container of userThumbnail with Column and use property mainAxisSize: MainAxisSize.min, that solved your problem.
It tells column widget to take space whatever is required but not more than that. Any
uncertainty in size won't work with mainAxisSize: MainAxisSize.min and can result in ui error of size undefined.
Following code may help you.
#override
Widget build (BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: new Text("Csd"),
),
body: Column(
children: <Widget>[
Container(
height: 150.0,
margin: const EdgeInsets.symmetric(
vertical: 16.0,
horizontal: 24.0,
),
child: new Stack(
children: <Widget>[
eventCardContent,
userThumbnail,
],
),
),
new Column(
children: <Widget>[
Row(
children: <Widget>[
new Column(
children: <Widget>[
Text("SEP"),
Text("30"),
],
),
Expanded(
child:new Column(
children: <Widget>[
new Text("title"),
new Text("Sub title"),
new Text("Second Sub Title"),
],
)
)
],
),
],
)
],
),
);
}
God day,
Im having a trouble with layouts in flutter, anyone can help?
EDIT:
i will try to explain better.
I have this screen:
With this code:
return new Container(
height: height,
padding: new EdgeInsets.all(10.0),
child: new Card(
elevation: 10.0,
child:
new Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new ListTile(
trailing:
_buildCounterButton(),
title: new Center(child: new Text('VENDAS POR PRODUTOS', style: new TextStyle(fontWeight: FontWeight.bold))),
subtitle: new Center(child: new Padding(padding: new EdgeInsets.only(top: 5.0), child:
new Text('Top 3 produtos dos últimos 30 dias', textAlign: TextAlign.center,))),
),
new FutureBuilder<List<RelatorioProdutos>>(
future: fetchRelatorioPorProduto(new http.Client(),'$dateInicial', '$dateFinal'),
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
else
auxTelaDetalhada = RelatorioVendasTotalizadasProdutos(prods: snapshot.data, aondeVoltar: 0,);
return snapshot.hasData
? new porProdutoList(listas: snapshot.data)
: new Center(child: new RefreshProgressIndicator());
},
),
new Expanded(
child: new Align(
alignment: Alignment.bottomCenter,
child: new Padding(padding: new EdgeInsets.only(bottom: 10.0),
child: new RaisedButton(
child: new Text("Relatório Completo",
style: new TextStyle(color: Colors.white, fontSize: 20.0),),
color: Colors.blue,
elevation: 8.0,
splashColor: Colors.lightBlue,
onPressed: () {
Navigator.pushReplacement(
context,
new MaterialPageRoute(
builder: (context) => auxTelaDetalhada),
);
}
),))),
],)
),
);
I want to have this screen in the end of process.
But i have this method:
new FutureBuilder<List<RelatorioProdutos>>(
future: fetchRelatorioPorProduto(new http.Client(),'$dateInicial', '$dateFinal'),
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
else
auxTelaDetalhada = RelatorioVendasTotalizadasProdutos(prods: snapshot.data, aondeVoltar: 0,);
return snapshot.hasData
? new porProdutoList(listas: snapshot.data)
: new Center(child: new RefreshProgressIndicator());
},
),
And this method loads a json request, and i need the button to appear only at the end of json request.
So i was tring to put this RaisedButton in the other method return, with this the button appear only on the end of json request. But, i cant align this button when i put it inside the other method.
Other method:
Widget test =
new Column(
children: <Widget>[
listaTiles[0],
listaTiles[1],
listaTiles[2]]);
return test;
Im tring to do this:
Widget test =
new Column(children: <Widget>[
new Column(
children: <Widget>[
listaTiles[0],
listaTiles[1],
listaTiles[2]]),
new Align(
alignment: Alignment.bottomCenter,
child: new Padding(padding: new EdgeInsets.only(bottom: 10.0),
child: new RaisedButton(
child: new Text("Relatório Completo",
style: new TextStyle(color: Colors.white, fontSize: 20.0),),
color: Colors.blue,
elevation: 8.0,
splashColor: Colors.lightBlue,
onPressed: () {
Navigator.pushReplacement(
context,
new MaterialPageRoute(
builder: (context) => auxTelaDetalhada),
);
}
),)),
],);
But i get this:
Anyone have any idea to get this working?
Try this...
This question is answered here Flutter: Trying to bottom-center an item in a Column, but it keeps left-aligning
return new Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
//your elements here
],
);
Though I should write it in the comments but it requires 50 reputation but anyways..
This will help you and if you want to center it then wrap the column in the center widget
Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(Text("Hello to all", style: TextStyle(fontSize: 60.0)))
],
),
),
This would produce following result. Hope this is what you are looking for:)