How can I create a custom widget like this in Flutter? [closed] - flutter

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 days ago.
Improve this question
This is the required widget
I have tried using Stack. But didn't got correct solution

You can achieve this first you need to calculate the Text widget to draw that blue underline with that same width of the text using TextPainter and LayoutBuilder:
class TextPainterWidget extends StatelessWidget {
final TextPainter textPainter;
const TextPainterWidget({
Key? key,
required this.textPainter,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return CustomPaint(
painter: _TextPainterWidget(textPainter),
);
}
}
class _TextPainterWidget extends CustomPainter {
final TextPainter textPainter;
_TextPainterWidget(this.textPainter);
#override
void paint(Canvas canvas, Size size) {
textPainter.layout();
textPainter.paint(canvas, Offset.zero);
}
#override
bool shouldRepaint(_TextPainterWidget oldDelegate) {
return oldDelegate.textPainter.text != textPainter.text ||
oldDelegate.textPainter.text?.style != textPainter.text?.style;
}
}
Then Your main widget should be like that:
LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
final TextPainter textPainter = TextPainter(
text: const TextSpan(
text: 'Grab The Best Deal On ',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
),
children: <TextSpan>[
TextSpan(
text: 'Smartphones',
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.bold,
),
),
],
),
textDirection: TextDirection.ltr,
)..layout(maxWidth: constraints.maxWidth);
final double textWidth = textPainter.width;
return Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
TextPainterWidget(textPainter: textPainter),
Row(
children: <Widget>[
const Text('View All'),
const SizedBox(width: 8),
InkWell(
onTap: () {},
child: const Icon(
Icons.arrow_forward_ios,
size: 15,
color: Colors.blue,
),
),
],
),
],
),
Row(
children: <Widget>[
SizedBox(
width: textWidth,
child: const Divider(
color: Colors.blue,
thickness: 2,
),
),
const Expanded(
child: Divider(
color: Colors.grey,
thickness: 1,
),
),
],
),
],
);
},
),
Here's the code on Zapp

Related

Two screen overlapping flutter?

I am new to flutter development and i am doing it from past 3 months and i never have that issue when i press back.
Whenever i press back and back to home screen screen overlap:
here is my code of home screen:
class HomePage extends StatefulWidget {
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
BannerAd _bottomBannerAd;
bool _isBottomBannerAdLoaded = false;
final BannerAd myBanner = BannerAd(
adUnitId: 'ca-app-pub-3940256099942544/6300978111',
size: AdSize.banner,
request: AdRequest(),
listener: BannerAdListener(),
);
#override
void initState() {
super.initState();
myBanner.load();
}
#override
Widget build(BuildContext context) {
return Container(
child: Scaffold(
bottomNavigationBar: Container(
height: 50,
width: 320,
child: AdWidget(ad: myBanner,),
) ,
backgroundColor: Colors.transparent,
body: SingleChildScrollView(
child: Column(
children: <Widget>[NavBar(), Body()],
)),
));
}
}
class Body extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ResponsiveLayout(
largeScreen: LargeChild(),
smallScreen: SmallChild(),
);
}
}
class LargeChild extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SizedBox(
height: 600,
child: Stack(
fit: StackFit.expand,
children: <Widget>[
FractionallySizedBox(
alignment: Alignment.centerLeft,
widthFactor: .6,
child: Padding(
padding: EdgeInsets.only(left: 48),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"Memory Game",
style: TextStyle(
fontSize: 60,
fontWeight: FontWeight.bold,
fontFamily: "Montserrat-Regular",
color: Color(0xFF111111)),
),
RichText(
text: TextSpan(
text: "Say Hi to ",
style: TextStyle(
fontSize: 60, color: Color(0xFF8591B0)),
children: [
TextSpan(
text: "🐱",
style: TextStyle(
fontSize: 60,
fontWeight: FontWeight.bold,
// color: Colors.black54
))
],
),
),
SizedBox(
height: 40,
),
Search()
])))
],
),
);
}
}
class SmallChild extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(40),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Memory Game!",
style: TextStyle(
fontSize: 60,
fontWeight: FontWeight.bold,
fontFamily: "Montserrat-Regular",
color: Colors.white),
),
RichText(
text: TextSpan(
text: "Play Now",
style: TextStyle(fontSize: 60, color: Color(0xFF8591B0)),
children: [
TextSpan(
text: "🐱",
style: TextStyle(
fontSize: 40,
fontWeight: FontWeight.bold,
))
],
),
),
SizedBox(
height: 32,
),
Search(),
SizedBox(
height: 30,
)
],
),
));
}
}
Problem:Whenever i press back whole screen apears in back of home screen as you can see in the provided gif.
Can someone please tell me that why is this happening?
Its happening just because you have written backgroundColor: Colors.transparent, in your Scaffold
Try to change it with some another color and check it out, you will not face the problem.

Making a widget go over another with animating [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I'm new with Flutter and need some help. I used to build apps with Phonegap, but they've stoped delivering their services.
I'm facing a problem with the following: I'm trying to create a container with a button in it. When pushing the button the container must fill (animate) the screen in 1 second.
So it has to be filled untill the bottom bar, it must not go over the bottom.
See example: the container (orange) which is under the other container (green), is a list view.
I've tried using several widgets (Column, ListView, Container) yet no result. Could someone help me out with this? Which widget should I use? Any advise is welcome.
example
You can achieve given example like this:
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
double unexpandedTileHeight = 200.0;
bool isExpandedMode = false;
int _bottomNavIndex = 0;
final double initialUnexpandedTileHeight = 200.0;
final double roundedButtonSize = 48.0;
final double bottomBarSize = 64.0;
AnimationController _animationController;
#override
void initState() {
super.initState();
_animationController =
AnimationController(vsync: this, duration: Duration(milliseconds: 450));
}
#override
void dispose() {
_animationController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Stack(
fit: StackFit.expand,
children: [
MainPage(),
AnimatedPositioned(
duration: Duration(milliseconds: 200),
top: unexpandedTileHeight,
left: 0,
right: 0,
bottom: 0,
child: OverlayPage(),
),
AnimatedPositioned(
duration: Duration(milliseconds: 200),
left: MediaQuery.of(context).size.width / 2 -
roundedButtonSize / 2,
top: unexpandedTileHeight -
(isExpandedMode
? roundedButtonSize + 4
: roundedButtonSize / 2),
child: RawMaterialButton(
fillColor: Colors.white,
constraints: BoxConstraints.tightFor(
width: roundedButtonSize, height: roundedButtonSize),
onPressed: () {
isExpandedMode
? setState(() {
isExpandedMode = false;
unexpandedTileHeight = initialUnexpandedTileHeight;
_animationController.reverse();
})
: setState(() {
isExpandedMode = true;
var mediaQueryData = MediaQuery.of(context);
unexpandedTileHeight = mediaQueryData.size.height -
bottomBarSize -
mediaQueryData.padding.top -
mediaQueryData.padding.bottom;
_animationController.forward();
});
},
shape: StadiumBorder(),
child: AnimatedIcon(
icon: AnimatedIcons.list_view,
progress: _animationController,
),
))
],
),
),
bottomNavigationBar: SizedBox(
height: bottomBarSize,
child: BottomNavigationBar(
backgroundColor: Colors.white,
currentIndex: _bottomNavIndex,
onTap: (index) => setState(() {
_bottomNavIndex = index;
}),
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.radio),
label: 'Radio',
),
],
),
),
);
}
}
class OverlayPage extends StatelessWidget {
const OverlayPage({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
color: Colors.orange,
);
}
}
class MainPage extends StatelessWidget {
const MainPage({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
),
color: Colors.green,
child: Column(
children: [
SizedBox(height: 16),
Text('bla bla bla'),
SizedBox(height: 24),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.photo,
size: 56,
),
SizedBox(width: 24),
Text(
'bla bla bla',
style: TextStyle(fontSize: 18),
),
],
),
SizedBox(height: 100),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'dasdadasds',
style: TextStyle(fontSize: 18),
),
Text(
'fdsfsdf',
style: TextStyle(fontSize: 18),
),
],
),
SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'dasdadasds',
style: TextStyle(fontSize: 18),
),
Text(
'fdsfsdf',
style: TextStyle(fontSize: 18),
),
],
),
SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'dasdadasds',
style: TextStyle(fontSize: 18),
),
Text(
'fdsfsdf',
style: TextStyle(fontSize: 18),
),
],
),
SizedBox(height: 16),
],
),
);
}
}

How to display ListTile after storing data into local database not from the api?

I am using flutter_ffmpeg package for fetching the metadata of songs. In my application user can select the songs from the internal storage and then the metadata is fetched by flutter_ffmpeg stored in local lists. I am using these lists to build my custom widget (Song tiles which has artist name, duration etc..). In my case all the widgets are render first with null list I want to render the widget after all selected songs metadata is stored in list and then able to render the widget. How to archive this?
Since I am not using API i cannot use Builder widget. Please help.
Code : https://pastebin.com/gwZkuujA
CustomSongTile Widget : https://pastebin.com/edit/ZSi25ydz
import 'package:audiobook_player/presentation/pages/widgets/book_info_tile.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_ffmpeg/flutter_ffmpeg.dart';
class FilePickerTrial extends StatelessWidget {
final FlutterFFprobe _flutterFFprobe = new FlutterFFprobe();
final List<String> audioPaths = [];
final List<String> audioTitle = [];
final List<String> audioAuthor = [];
final List<String> audioDuration = [];
FilePickerTrial({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Container(
child: Scaffold(
appBar: AppBar(
actions: [
Container(
width: size.width,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Align(
alignment: Alignment.centerLeft,
child: IconButton(
icon: Icon(Icons.sort, color: Colors.black),
onPressed: () {},
),
),
IconButton(
icon: Icon(Icons.add_circle, color: Colors.black),
onPressed: () async {
FilePickerResult pathResult = await FilePicker.platform
.pickFiles(
type: FileType.audio, allowMultiple: true);
for (int i = 0; i < pathResult.paths.length; i++) {
audioPaths.add(pathResult.paths[i]);
}
print(
'AudioPaths Length ============== ${audioPaths.length} ==============');
for (int j = 0; j < audioPaths.length; j++) {
await _flutterFFprobe
.getMediaInformation(audioPaths[j])
.then(
(info) {
print(
"================Media Information=============");
audioTitle.add(
info.getMediaProperties()['tags']['title']);
audioAuthor.add(
info.getMediaProperties()['tags']['artist']);
audioDuration
.add(info.getMediaProperties()['duration']);
print(
'====================> $audioTitle ==============');
print(
'====================> $audioAuthor ==============');
},
);
}
},
),
],
),
),
),
],
),
body: ListView.builder(
itemCount: audioPaths.length,
itemBuilder: (BuildContext context, int index) {
return BookInfoTile(
bookCoverImageURL: 'assets/no_cover.png',
bookTitle: audioTitle[index],
authorName: audioAuthor[index],
bookLength: int.parse(audioDuration[index]),
onClick: () {
print('Button is Clicked');
});
}),
),
);
}
}
BookInfoTile Code :
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
class BookInfoTile extends StatelessWidget {
final String bookCoverImageURL;
final String bookTitle;
final String authorName;
final int bookLength;
final onClick;
final Function onStop;
const BookInfoTile(
{Key key,
#required this.bookCoverImageURL,
#required this.bookTitle,
#required this.authorName,
#required this.bookLength,
#required this.onClick,
this.onStop})
: super(key: key);
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return GestureDetector(
onTap: onClick,
child: Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(25.0),
child: Image.asset(
bookCoverImageURL,
fit: BoxFit.fill,
alignment: Alignment.centerLeft,
height: size.height * 0.22,
width: size.width * 0.40,
),
),
SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
bookTitle,
overflow: TextOverflow.visible,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
const SizedBox(
height: 10,
),
Text(
'by $authorName',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.normal,
color: Color(0xFF767676),
),
),
const SizedBox(
height: 8,
),
RichText(
text: TextSpan(
children: [
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: SvgPicture.asset(
'assets/svg/circle-fill.svg',
color: Color(0xFFffe564),
height: 10,
alignment: Alignment.topCenter,
),
),
TextSpan(
text: " $bookLength",
),
],
),
),
RaisedButton(
onPressed: onStop,
child: Text('Stop'),
),
],
),
),
],
),
),
);
}
}
Try using a Stateful Widget instead of a Stateless widget.
Then in the on pressed fxn of your icon button, surround code with
setState({
}) ;
This helps to rebuild the listview and if there is content in the audiopath, it'll populate the listview.

Flutter - Expandable text not working properly with overflow property

Basically I want to achieve exactly the same thing as Flutter: How to hide or show more text within certain length.
Here is my code snippet.
LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
final TextSpan span = TextSpan(
text: text,
style: TextStyle(
fontSize: 13,
),
);
final TextPainter textPainter = TextPainter(
text: span,
maxLines: 1,
ellipsis: '...',
textDirection: TextDirection.ltr,
);
textPainter.layout(maxWidth: constraints.maxWidth);
if (textPainter.didExceedMaxLines)
return Row(
crossAxisAlignment: _basicInformationIsExpanded
? CrossAxisAlignment.end
: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: Text(
text,
style: TextStyle(
fontSize: 13,
),
maxLines: _isExpanded ? null : 1,
//overflow: TextOverflow.ellipsis,
),
),
GestureDetector(
child: _isExpanded
? Icon(
Icons.expand_less,
)
: Icon(
Icons.expand_more,
),
onTap: () {
setState(() => _isExpanded =
!_isExpanded);
},
),
],
);
else
return Text(
text,
style: TextStyle(
fontSize: 13,
),
);
}),
The weird thing is if I comment overflow: TextOverflow.ellipsis,, everything is fine. But I need to show the ellipsis and if I add that line, the text doesn't expand when I click the icon.
Can anyone help me with it? Thanks.
You can copy paste run full code below
You can set overflow based on _isExpanded
overflow: _isExpanded ? null : TextOverflow.ellipsis,
working demo
full code
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: 200,
child: ExpandText(
text: "long string" * 10,
)),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
class ExpandText extends StatefulWidget {
String text;
ExpandText({this.text});
#override
_ExpandTextState createState() => _ExpandTextState();
}
class _ExpandTextState extends State<ExpandText> {
bool _isExpanded = false;
bool _basicInformationIsExpanded = true;
#override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
final TextSpan span = TextSpan(
text: widget.text,
style: TextStyle(
fontSize: 13,
),
);
final TextPainter textPainter = TextPainter(
text: span,
maxLines: 1,
ellipsis: '...',
textDirection: TextDirection.ltr,
);
textPainter.layout(maxWidth: constraints.maxWidth);
if (textPainter.didExceedMaxLines) {
print("exceed");
return Row(
crossAxisAlignment: _basicInformationIsExpanded
? CrossAxisAlignment.end
: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
flex: 1,
child: Text(
widget.text,
style: TextStyle(
fontSize: 13,
),
maxLines: _isExpanded ? null : 1,
overflow: _isExpanded ? null : TextOverflow.ellipsis,
),
),
GestureDetector(
child: _isExpanded
? Icon(
Icons.expand_less,
)
: Icon(
Icons.expand_more,
),
onTap: () {
setState(() => _isExpanded = !_isExpanded);
},
),
],
);
} else {
print("not exceed");
return Text(
widget.text,
style: TextStyle(
fontSize: 13,
),
);
}
});
}
}
A long ago i stumbled onto same thing, surely using these widget's is a way to do this,
but here is the code which i wrote and its totally customizable.
You can change the limit variable to use it accordinly
class QNAContainer extends StatefulWidget {
final String ques;
final String answer;
QNAContainer({#required this.ques, #required this.answer});
#override
_QNAContainerState createState() => _QNAContainerState();
}
class _QNAContainerState extends State<QNAContainer> {
String truncAns;
bool showingAll = false;
int limit = 80;
#override
void initState() {
super.initState();
if (widget.answer.length > limit ) {
print("truncc");
truncAns = widget.answer.toString().substring(0, limit) + '...';
} else {
truncAns = widget.answer;
}
}
#override
Widget build(BuildContext context) {
ScreenUtil.instance = ScreenUtil(
width: Styles.get_width(context),
height: Styles.get_height(context),
allowFontScaling: true);
return Container(
width: double.infinity,
padding: EdgeInsets.symmetric(horizontal: ScreenUtil().setWidth(10), vertical: ScreenUtil().setHeight(10)),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: AppColors.greyFillColor.withOpacity(0.6),
),
margin: EdgeInsets.symmetric(vertical: ScreenUtil().setHeight(7)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(widget.ques,
style: TextStyle(
fontSize: ScreenUtil().setHeight(14),
fontWeight: FontWeight.bold,
)),
SizedBox(height: ScreenUtil().setHeight(5)),
Text(showingAll ? widget.answer : truncAns,
style: TextStyle(
fontSize: ScreenUtil().setHeight(14),
)),
SizedBox(height: ScreenUtil().setHeight(5)),
truncAns.contains('...')
? GestureDetector(
onTap: () {
setState(() {
showingAll = !showingAll;
});
},
child: Align(
alignment: Alignment.centerRight,
child: Container(
margin: EdgeInsets.only(bottom: ScreenUtil().setHeight(5)),
padding: EdgeInsets.symmetric(vertical: ScreenUtil().setHeight(5), horizontal: ScreenUtil().setWidth(9)),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: AppColors.kDefaultPink),
child: Text(
showingAll ? 'see less' : 'see more',
style: TextStyle(color: Colors.white, fontSize: ScreenUtil().setHeight(14)),
),
),
),
)
: SizedBox()
],
),
);
}
}

Stateful widget not updating, after being updated in setState, how to solve this?

I am new to Flutter. I am trying to build a Quiz App. Now, I am on the Quiz Screen, and then a quiz has multiple questions. I am showing the question title along with the answers, and when someone clicks on the answer, I am updating the QuestionView again with the new question data. These are stateful widgets, and when the result is fetched I am using setState to update the widget, and if I place a break point there I can see that the things are updated, but that is not rendered on the screen or the view is not changed, it has same title, answers and everything. I am using an optionTap method and you can find it in the comments below. I have mentioned where I am tapping the option and what is done below it.
Here's what I have done so far:
import 'package:flutter/material.dart';
import 'package:flutter_app/Constants/constants.dart';
import 'package:flutter_app/Models/question_model.dart';
import 'package:flutter_app/ViewModels/QuestionsVM.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
QuizQuestionViewModel questionViewModel = QuizQuestionViewModel();
QuizQuestionModel _questionModel;
Widget updateWidget;
class SQQuiz extends StatefulWidget {
final QuizQuestionModel quizQuestionModel;
final int quizId;
SQQuiz({Key key, #required this.quizQuestionModel, #required this.quizId})
: super(key: key);
#override
_SQQuizState createState() =>
_SQQuizState(quizQuestionModel: quizQuestionModel, quizId: quizId);
}
class _SQQuizState extends State<SQQuiz> {
final QuizQuestionModel quizQuestionModel;
final int quizId;
_SQQuizState(
{Key key, #required this.quizQuestionModel, #required this.quizId});
#override
Widget build(BuildContext context) {
_questionModel = quizQuestionModel;
updateWidget = QuestionView(
quizQuestionModel: _questionModel,
quizId: quizId,
);
return Scaffold(
appBar: AppBar(
leading: Container(
child: Row(
children: <Widget>[
IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(Icons.arrow_back),
),
],
),
),
title: Padding(
padding: const EdgeInsets.symmetric(horizontal: 0),
child: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(
_questionModel.questionDetail.quizName,
style: TextStyle(color: Constants.greyColor, fontSize: 12),
textAlign: TextAlign.left,
),
SizedBox(
width: 14,
),
CircularProgressIndicator(
value: 15,
strokeWidth: 2,
),
],
),
),
),
actions: <Widget>[
Container(
margin: const EdgeInsets.only(right: 10),
child: Center(
child: Container(
child: Text("SCORE ${_questionModel.score}"),
),
),
)
],
),
body: SafeArea(child: updateWidget),
);
}
}
class QuestionView extends StatefulWidget {
final QuizQuestionModel quizQuestionModel;
final int quizId;
QuestionView(
{Key key, #required this.quizQuestionModel, #required this.quizId})
: super(key: key);
#override
_QuestionViewState createState() => _QuestionViewState(
quizQuestionModel: quizQuestionModel,
quizId: quizId,
);
}
class _QuestionViewState extends State<QuestionView> {
final QuizQuestionModel quizQuestionModel;
final int quizId;
_QuestionViewState({#required this.quizQuestionModel, #required this.quizId});
#override
Widget build(BuildContext context) {
QuestionDetail questionDetail = quizQuestionModel.questionDetail;
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(
height: 10,
),
Text(
"Question ${quizQuestionModel.count}/${quizQuestionModel.totalCount}",
style: TextStyle(fontSize: 12),
),
SizedBox(
height: 5,
),
Image(
image: NetworkImage(
questionDetail.pic,
),
fit: BoxFit.cover,
),
Container(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 50),
color: Constants.orangeColor,
child: Text(
questionDetail.title,
style: TextStyle(
color: Colors.white,
fontSize: 16,
),
textAlign: TextAlign.center,
),
),
ListView.builder(
itemBuilder: (context, index) {
Answers answers = questionDetail.answers[index];
return Card(
elevation: 5,
margin:
const EdgeInsets.symmetric(vertical: 10, horizontal: 0),
child: ListTile(
onTap: () { //This is where I am tapping the option
optionTap(
context: context,
sessionId: quizQuestionModel.sessionId,
quizId: quizId,
questionId: questionDetail.questionId,
answerId: answers.id,
hintUsed: false,
fiftyUsed: false,
).then((response) {
setState(() { //Here the updateWidget is updated, which you can see in the body, but it is not rendered
_questionModel = response;
updateWidget = new QuestionView(
quizQuestionModel: response,
quizId: quizId,
); // The new QuestionView with new details
});
});
},
contentPadding: const EdgeInsets.symmetric(vertical: 10),
title: Text(
answers.title,
textAlign: TextAlign.center,
),
),
);
},
itemCount: questionDetail.answers.length,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
RaisedButton(
padding: const EdgeInsets.symmetric(horizontal: 50),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
onPressed: () {
print("50-50 Tapped");
},
child: Text(
"50 | 50\n ${quizQuestionModel.fiftyCoin} coins",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
),
),
),
Wrap(
spacing: 3,
children: <Widget>[
Icon(FontAwesomeIcons.coins),
Text("${quizQuestionModel.coins}"),
],
),
RaisedButton(
padding: const EdgeInsets.symmetric(horizontal: 50),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
onPressed: () {
print("Hint Tapped");
},
child: Text(
"HINT\n ${quizQuestionModel.hintUsed} coins",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
),
),
)
],
),
],
)
],
);
}
There are no errors at the moment, can anyone please help me with this? Thanks in advance.
No offence - but I think you have completely misunderstood the concept of state management in flutter.
If you have a stateful widget, the setState() method triggers the build() method again. So setState is a notifier to say: Hey there was an update to our variable, please build again.
Your Stateful Widget is doing that. BUT there are no new updates on variables from that widget, because your variables ARE OUTSIDE of the widget. They won't get updated for your StatefulWidget. Consider to rethink you architecture. For small Apps it is enough to pass the variables in a constructor.
Here are some links to get closer to the Flutter-State-Management-Concept:
https://flutter.dev/docs/get-started/codelab
https://flutter.dev/docs/development/data-and-backend/state-mgmt/options