Related
I have a collection (blog style) of box entries that are stacked on top of each other.
I can see 3 entries on my home screen but it doesnt allow me to scroll down on the emulator device.
If i add another entry it just lays on top of my other entries. I have tried the SingleChildScrollView but have a feeling im using it in the incorrect place?
See code below:
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_blog_application/services/crud.dart';
import 'package:flutter_blog_application/views/create_blog.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
CrudMethods crudMethods = CrudMethods();
late Stream playerStream;
Widget TransferList(){
return SingleChildScrollView(
child: playerStream != null
? Column(
children: <Widget>[
StreamBuilder(
stream: playerStream,
builder: (context, snapshot){
return ListView.builder(
padding: const EdgeInsets.symmetric(horizontal: 10),
itemCount: snapshot.data.documents.length,
shrinkWrap: true,
itemBuilder: (context, index){
return PlayerDisplay(
playerName: snapshot.data.documents[index].data['playerName'],
fromClub: snapshot.data.documents[index].data['fromClub'],
toClub: snapshot.data.documents[index].data['toClub'],
rumourDesc: snapshot.data.documents[index].data['rumourDesc'],
imgUrl: snapshot.data.documents[index].data['imgUrl'],
);
});
},)
],
) : Container(
alignment: Alignment.center,
child: const CircularProgressIndicator(),),
);
}
#override
void initState() {
crudMethods.fetchData().then((result){
setState(() {
playerStream = result;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar:AppBar(
title: Row(
children: const <Widget>[
Text(
"Transfer",
style: TextStyle(fontSize: 22, color: Colors.orangeAccent)
),
Text("Center",
style: TextStyle(fontSize: 22, color: Colors.white),
)
],
),
backgroundColor: Colors.transparent,
elevation: 0.0,
),
body: TransferList(),
floatingActionButton: Container(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FloatingActionButton(
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => CreateBlog()));
},
backgroundColor: Colors.orangeAccent,
child: const Icon(Icons.add),
)
],),
),
);
}
}
class PlayerDisplay extends StatelessWidget {
late String imgUrl, playerName, fromClub, toClub, rumourDesc;
PlayerDisplay({required this.imgUrl,
required this.playerName,
required this.fromClub,
required this.toClub,
required this.rumourDesc});
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(bottom: 20),
height: 200,
child: Stack(children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.circular(10),
child: CachedNetworkImage(imageUrl: imgUrl, width: MediaQuery.of(context).size.width
,fit: BoxFit.cover,
),
),
Container(
height: 200,
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.3),
borderRadius: BorderRadius.circular(10)),
),
Container(child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Player:", style: const TextStyle(color: Colors.orangeAccent, backgroundColor: Colors.black, fontSize: 20,)),
Text(playerName, style: const TextStyle(color: Colors.white, backgroundColor: Colors.black, fontSize: 20)),
Text("From:", style: const TextStyle(color: Colors.orangeAccent, backgroundColor: Colors.black, fontSize: 20)),
Text(fromClub, style: const TextStyle(color: Colors.white, backgroundColor: Colors.black, fontSize: 20)),
Text("To:", style: const TextStyle(color: Colors.orangeAccent, backgroundColor: Colors.black, fontSize: 20)),
Text(toClub, style: const TextStyle(color: Colors.white, backgroundColor: Colors.black, fontSize: 20)),
Text("Details:", style: const TextStyle(color: Colors.orangeAccent, backgroundColor: Colors.black, fontSize: 20)),
Text(rumourDesc, style: const TextStyle(color: Colors.white, backgroundColor: Colors.black, fontSize: 20))
],),)
],),
);
}
}
Remove the SingleChildScrollView and try wrapping your ListView.builder with an Expanded widget.
return Expanded(child:ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: false,
padding: const EdgeInsets.symmetric(horizontal: 10),
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index){....
Steps:
(VS Code) Right click on your ListView.builder
Click on Refactor
Click on Wrap with widget...
Rename widget to Expanded
I'm creating a flutter project on which it consist of news feature sadly after building an apk and installing it to try in become an empty screen with grey shade, i also try to test it on my phone and this is what happen i dont know where the bugs came from.. please help me
here's the code
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'Article_View.dart';
import 'News_Categories.dart';
import 'helper/Data.dart';
import 'helper/News.dart';
import 'model/Article_Model.dart';
import 'model/CategoryModel.dart';
class NewsHomePage extends StatefulWidget {
#override
_NewsHomePageState createState() => _NewsHomePageState();
}
class _NewsHomePageState extends State<NewsHomePage> {
List<CategoryModel> categories = <CategoryModel>[];
List<ArticleModel> articles = <ArticleModel>[];
bool _loading = true;
//bannerads
late BannerAd _bannerads;
bool _isAdsLoaded = false ;
#override
void initState() {
// TODO: implement initState
super.initState();
categories = getCategories();
getNews();
_initBannerAds();
}
getNews() async {
News newsClass = News();
await newsClass.getNews();
articles = newsClass.news;
setState(() {
_loading = false;
});
}
_initBannerAds(){
_bannerads = BannerAd(
size: AdSize.banner,
// ignore: deprecated_member_use
adUnitId: "ca-app-pub-8634651641429291/4830511818",
listener: BannerAdListener(
onAdLoaded: (ad){
setState(() {
_isAdsLoaded =true;
});
},
onAdFailedToLoad: (ad,error){}
),
request: const AdRequest()
);
_bannerads.load();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.green,
elevation: 0.0,
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text('Stock '),
Text(
'News',
style: TextStyle(
color: Colors.black54,
),
),
],
),
centerTitle:true,
bottom: const PreferredSize(
preferredSize: Size.zero,
child: Text("Powered by news.org")),
),
body: _loading
? Container(
child: const Center(
child: CircularProgressIndicator(),
),
)
: SingleChildScrollView(
child: Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
///Categories
Container(
padding: const EdgeInsets.symmetric(horizontal: 22.0),
height: 90.0,
child: Expanded(
child: ListView.builder(
itemCount: categories.length,
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemBuilder: (context, index) {
return CategoryTile(
imageUrl: categories[index].imageAssetUrl,
categoryName: categories[index].categoryName,
);
}),
),
),
///Blogs
Container(
padding: const EdgeInsets.only(top: 16.0),
child: Expanded(
child: ListView.builder(
physics: const ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: articles.length,
itemBuilder: (context, index) {
return BlogTile(
imageURL: articles[index].urlToImage,
title: articles[index].title,
desc: articles[index].description,
url: articles[index].url,
);
},
),
),
),
],
),
),
),
bottomNavigationBar: _isAdsLoaded?SizedBox(
height: _bannerads.size.height.toDouble(),
width: _bannerads.size.width.toDouble(),
child: AdWidget(ad: _bannerads),
)
:const SizedBox(),
);
}
}
class CategoryTile extends StatelessWidget {
final String imageUrl, categoryName;
const CategoryTile({required this.imageUrl, required this.categoryName});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CategoryNews(
category: categoryName.toLowerCase(),
),
),
);
},
child: Container(
margin: EdgeInsets.only(right: 10.0),
child: Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(6),
child: imageUrl != null
? CachedNetworkImage(
imageUrl: imageUrl,
width: 120,
height: 60.0,
fit: BoxFit.cover,
)
: Image.network(
imageUrl,
width: 120.0,
height: 60.0,
fit: BoxFit.cover,
),
),
Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.black26,
borderRadius: BorderRadius.circular(6),
),
width: 120,
height: 60.0,
child: Text(
categoryName,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 18.0,
),
),
),
],
),
),
);
}
}
class BlogTile extends StatelessWidget {
final String imageURL, title, desc, url;
BlogTile(
{required this.imageURL,
required this.title,
required this.desc,
required this.url});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ArticleView(
blogUrl: url,
)),
);
},
child: Container(
margin: const EdgeInsets.only(bottom: 16.0, left: 10.0, right: 10.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(6.0),
child: imageURL != null
? CachedNetworkImage(
imageUrl: imageURL,
)
: Image.network(imageURL),
),
const SizedBox(
height: 8.0,
),
Text(
title,
style: const TextStyle(
//color: Colors.black87,
fontSize: 17.0,
fontWeight: FontWeight.w500,
),
),
const SizedBox(
height: 8.0,
),
Text(
desc,
style: const TextStyle(
//color: Colors.black54,
),
),
],
),
),
);
}
}
and here's the screen shots of the app
[![debugging app][1]][1]
[![build app][2]][2]
[1]: https://i.stack.imgur.com/tvBsG.jpg
[2]: https://i.stack.imgur.com/wOuxS.jpg
Check if this line exists in android/app/src/main/AndroidManifest.xml file. If it doesn't add it right below the package name line. This will grant the app INTERNET permission so it can access it & display the data from the internet.
<uses-permission android:name="android.permission.INTERNET"/>
Flutter by default only adds the INTERNET permission in debug mode. When you build an APK in release mode, you have to explicitly add the permission by including the above line.
More info here.
I created a button shape called 'VocabularyWordsButton' and when I try it under a ListView it works just fine. But when I make 100 buttons under ListView, I want to find them via Search Bar. But I don't know how to do it somehow.
What I want to do: I want to distinguish the buttons by filtering the word 'englishWord' among the buttons listed below. When I enter the word in 'englishWord' in Search Bar, I want the buttons containing that word to be filtered.
If I do something like below, only the texts inside are listed, not the button I made.
VocabularyWordsButton.dart
import 'package:being_moroccan/AdHelper.dart';
import 'package:flutter/material.dart';
import 'package:audioplayers/audioplayers.dart';
import 'package:sizer/sizer.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:easy_localization/easy_localization.dart';
class VocabularyWordsButton extends StatefulWidget {
VocabularyWordsButton(
{required this.englishWord,
required this.trasncribedWord,
required this.arabicWord,
required this.sound});
final String englishWord;
final String trasncribedWord;
final String arabicWord;
final String sound;
#override
_VocabularyWordsButtonState createState() => _VocabularyWordsButtonState();
}
class _VocabularyWordsButtonState extends State<VocabularyWordsButton> {
AdHelper adHelper = AdHelper();
#override
void didChangeDependencies() {
// TODO: implement didChangeDependencies
super.didChangeDependencies();
adHelper.myLargeBanner.load();
}
bool _canShowButton = true;
void hideWidget() {
setState(() {
_canShowButton = !_canShowButton;
});
}
final AudioCache _audioCache = AudioCache(
prefix: 'audio/',
fixedPlayer: AudioPlayer()..setReleaseMode(ReleaseMode.STOP),
);
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: !_canShowButton
? Column(
children: [
Container(
height: 195.h / 6,
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.all(Radius.circular(20)),
),
child: Container(
height: 100,
child: Column(
children: [
Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(20))),
child: Center(
child: TextButton(
onPressed: () {
hideWidget();
},
child: Container(
width: MediaQuery.of(context).size.width,
child: Center(
child: Text(
widget.englishWord,
style: TextStyle(
fontSize: 30.sp / 2,
color: Colors.white),
),
),
),
),
),
),
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(
Colors.transparent),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius:
BorderRadius.all(Radius.circular(20)),
),
),
),
onPressed: () {
print('cal');
_audioCache.play('${widget.sound}.mp3');
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(2.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'TRANSCRIBED'.tr(),
style: TextStyle(
fontSize: 25.sp / 2,
),
),
Container(
width:
MediaQuery.of(context).size.width /
2,
height: 60.h / 7,
child: Center(
child: Text(
widget.trasncribedWord,
style: TextStyle(
fontSize: 25.sp / 2,
),
),
),
),
],
),
),
Padding(
padding: const EdgeInsets.all(2.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'ARABIC'.tr(),
style: TextStyle(
fontSize: 25.sp / 2,
),
),
Container(
width:
MediaQuery.of(context).size.width /
2,
height: 60.h / 7,
child: Center(
child: Text(
widget.arabicWord,
style: TextStyle(
fontSize: 25.sp / 2,
),
),
),
),
],
),
),
],
),
),
),
],
),
),
),
Container(
height: 100,
child: AdWidget(ad: adHelper.myLargeBanner),
),
],
)
: Container(
width: MediaQuery.of(context).size.width / 2,
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.1),
borderRadius: BorderRadius.all(Radius.circular(20))),
child: Center(
child: ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all<Color>(Colors.transparent),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20)),
),
),
),
onPressed: () {
hideWidget();
},
child: Container(
width: MediaQuery.of(context).size.width,
child: Center(
child: Text(
widget.englishWord,
style:
TextStyle(fontSize: 30.sp / 2, color: Colors.white),
),
),
),
),
),
),
);
}
}
DictionaryScreen.dart
import 'package:sizer/sizer.dart';
import 'package:flutter/material.dart';
import 'package:easy_localization/easy_localization.dart';
import 'VocabularyWords/VocabularyWordsButton.dart';
class DictionaryScreen extends StatefulWidget {
static const String id = 'Dictionary_Screen';
const DictionaryScreen({Key? key}) : super(key: key);
#override
_DictionaryScreenState createState() => _DictionaryScreenState();
}
class _DictionaryScreenState extends State<DictionaryScreen> {
TextEditingController editingController = TextEditingController();
// final duplicateItems = List<String>.generate(10000, (i) => "Item $i");
// var items = List<String>();
List<VocabularyWordsButton> words = [
VocabularyWordsButton(
englishWord: 'To pray'.tr(),
trasncribedWord: 'Sella',
arabicWord: 'صْلّى',
sound: 'Sella',
),
VocabularyWordsButton(
englishWord: 'To prefer'.tr(),
trasncribedWord: 'Feddel',
arabicWord: 'فْضّلْ',
sound: 'Feddel',
)
];
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(),
body: Container(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
onChanged: (value) {
setState(() {});
},
controller: editingController,
decoration: InputDecoration(
labelText: "Search",
hintText: "Search",
prefixIcon: Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(25.0)))),
),
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: words.length,
itemBuilder: (context, index) {
if (editingController.text.isEmpty) {
return ListTile(
title: Text('${words[index].englishWord} '),
);
} else if (words[index]
.englishWord
.toLowerCase()
.contains(editingController.text)) {
return ListTile(
title: Text('${words[index].englishWord} '),
);
} else {
return Container();
}
}),
),
],
),
),
);
}
}
I create Welcome Page, when clicking the button I would like the user to be redirected to the home page, but when I click it gives several errors. I don't know how to program very well in flutter, can someone help me?
I tried in many ways, and they all fail. If you have to press the button to restart the APP it would also work, but I don't know how to solve it in any way
WELCOME PAGE (I would like to be redirected to HOME by clicking the button)
import 'package:flutter/material.dart';
import '../../main.dart';
import '../models/items.dart';
import '../helpers/helper.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/cupertino.dart';
void main() => runApp(Welcome());
Future<void> Return() async {
runApp(MyApp());
}
class Welcome extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: WelcomeScreen(),
);
}
}
class WelcomeScreen extends StatefulWidget {
final GlobalKey<ScaffoldState> parentScaffoldKey;
WelcomeScreen({Key key, this.parentScaffoldKey}) : super(key: key);
#override
_WelcomeScreenState createState() => _WelcomeScreenState();
}
class _WelcomeScreenState extends State<WelcomeScreen> {
List<Widget> slides = items
.map((item) => Container(
padding: EdgeInsets.symmetric(horizontal: 18.0),
child: Column(
children: <Widget>[
Flexible(
flex: 1,
fit: FlexFit.tight,
child: Image.asset(
item['image'],
fit: BoxFit.fitWidth,
width: 220.0,
alignment: Alignment.bottomCenter,
),
),
Flexible(
flex: 1,
fit: FlexFit.tight,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 30.0),
child: Column(
children: <Widget>[
Text(item['header'],
style: TextStyle(
fontSize: 50.0,
fontWeight: FontWeight.w300,
color: Color(0XFF3F3D56),
height: 2.0)),
Text(
item['description'],
style: TextStyle(
color: Colors.grey,
letterSpacing: 1.2,
fontSize: 16.0,
height: 1.3),
textAlign: TextAlign.center,
)
],
),
),
)
],
)))
.toList();
double currentPage = 0.0;
final _pageViewController = new PageController();
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: Helper.of(context).onWillPop,
child: Scaffold(
body: Stack(
alignment: AlignmentDirectional.topCenter,
children: <Widget>[
PageView.builder(
controller: _pageViewController,
itemCount: slides.length,
itemBuilder: (BuildContext context, int index) {
_pageViewController.addListener(() {
setState(() {
currentPage = _pageViewController.page;
});
});
return slides[index];
},
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
margin: EdgeInsets.only(top: 70.0),
padding: EdgeInsets.symmetric(vertical: 40.0),
)
),
Positioned(
bottom: 10,
child: RaisedButton(
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context){
return HomeWidget();
},
highlightElevation: 2,
splashColor: Color(0xFF2F4565),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)
),
padding: EdgeInsets.symmetric(horizontal: 40),
color: Color(0XFFEA5C44),
child: Text(
"Permitir",
style: TextStyle(color: Colors.white),
),
),
)
],
),
),
);
}
}
HOMEPAGE (I would like to be redirected to that page by clicking the button on the WELCOME page)
import 'package:flutter/material.dart';
import 'package:mvc_pattern/mvc_pattern.dart';
import '../../generated/l10n.dart';
import '../controllers/home_controller.dart';
import '../elements/CardsCarouselWidget.dart';
import '../elements/CaregoriesCarouselWidget.dart';
import '../elements/DeliveryAddressBottomSheetWidget.dart';
import '../elements/GridWidget.dart';
import '../elements/ProductsCarouselWidget.dart';
import '../elements/ReviewsListWidget.dart';
import '../elements/SearchBarWidget.dart';
import '../elements/ShoppingCartButtonWidget.dart';
import '../repository/settings_repository.dart' as settingsRepo;
import '../repository/user_repository.dart';
class HomeWidget extends StatefulWidget {
final GlobalKey<ScaffoldState> parentScaffoldKey;
HomeWidget({Key key, this.parentScaffoldKey}) : super(key: key);
#override
_HomeWidgetState createState() => _HomeWidgetState();
}
class _HomeWidgetState extends StateMVC<HomeWidget> {
HomeController _con;
#override
_HomeWidgetState() : super(HomeController()) {
_con = controller;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: new IconButton(
icon: new Icon(Icons.sort, color: Theme.of(context).hintColor),
onPressed: () => widget.parentScaffoldKey.currentState.openDrawer(),
),
automaticallyImplyLeading: false,
backgroundColor: Colors.transparent,
elevation: 0,
centerTitle: true,
title: ValueListenableBuilder(
valueListenable: settingsRepo.setting,
builder: (context, value, child) {
return Text(
value.appName ?? S.of(context).home,
style: Theme.of(context).textTheme.headline6.merge(TextStyle(letterSpacing: 1.3)),
);
},
),
actions: <Widget>[
new ShoppingCartButtonWidget(iconColor: Theme.of(context).hintColor, labelColor: Theme.of(context).accentColor),
],
),
body: RefreshIndicator(
onRefresh: _con.refreshHome,
child: SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 0, vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: SearchBarWidget(
onClickFilter: (event) {
widget.parentScaffoldKey.currentState.openEndDrawer();
},
),
),
Padding(
padding: const EdgeInsets.only(top: 15, left: 20, right: 20),
child: ListTile(
dense: true,
contentPadding: EdgeInsets.symmetric(vertical: 0),
leading: Icon(
Icons.stars,
color: Theme.of(context).hintColor,
),
trailing: IconButton(
onPressed: () {
if (currentUser.value.apiToken == null) {
_con.requestForCurrentLocation(context);
} else {
var bottomSheetController = widget.parentScaffoldKey.currentState.showBottomSheet(
(context) => DeliveryAddressBottomSheetWidget(scaffoldKey: widget.parentScaffoldKey),
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.only(topLeft: Radius.circular(10), topRight: Radius.circular(10)),
),
);
bottomSheetController.closed.then((value) {
_con.refreshHome();
});
}
},
icon: Icon(
Icons.my_location,
color: Theme.of(context).hintColor,
),
),
title: Text(
S.of(context).top_markets,
style: Theme.of(context).textTheme.headline4,
),
subtitle: Text(
S.of(context).near_to + " " + (settingsRepo.deliveryAddress.value?.address ?? S.of(context).unknown),
style: Theme.of(context).textTheme.caption,
),
),
),
CardsCarouselWidget(marketsList: _con.topMarkets, heroTag: 'home_top_markets'),
ListTile(
dense: true,
contentPadding: EdgeInsets.symmetric(horizontal: 20),
leading: Icon(
Icons.trending_up,
color: Theme.of(context).hintColor,
),
title: Text(
S.of(context).trending_this_week,
style: Theme.of(context).textTheme.headline4,
),
subtitle: Text(
S.of(context).clickOnTheProductToGetMoreDetailsAboutIt,
maxLines: 2,
style: Theme.of(context).textTheme.caption,
),
),
ProductsCarouselWidget(productsList: _con.trendingProducts, heroTag: 'home_product_carousel'),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: ListTile(
dense: true,
contentPadding: EdgeInsets.symmetric(vertical: 0),
leading: Icon(
Icons.category,
color: Theme.of(context).hintColor,
),
title: Text(
S.of(context).product_categories,
style: Theme.of(context).textTheme.headline4,
),
),
),
CategoriesCarouselWidget(
categories: _con.categories,
),
Padding(
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20),
child: ListTile(
dense: true,
contentPadding: EdgeInsets.symmetric(vertical: 0),
leading: Icon(
Icons.trending_up,
color: Theme.of(context).hintColor,
),
title: Text(
S.of(context).most_popular,
style: Theme.of(context).textTheme.headline4,
),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: GridWidget(
marketsList: _con.popularMarkets,
heroTag: 'home_markets',
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: ListTile(
dense: true,
contentPadding: EdgeInsets.symmetric(vertical: 20),
leading: Icon(
Icons.recent_actors,
color: Theme.of(context).hintColor,
),
title: Text(
S.of(context).recent_reviews,
style: Theme.of(context).textTheme.headline4,
),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: ReviewsListWidget(reviewsList: _con.recentReviews),
),
],
),
),
),
);
}
}
First you need to set up the route:
MaterialApp(
// Start the app with the "/" named route. In this case, the app starts
// on the FirstScreen widget.
initialRoute: '/',
routes: {
// When navigating to the "/" route, build the FirstScreen widget.
'/': (context) => FirstScreen(), //NOTE: Change the FirstScreen() to your own screen's class name (ex: WelcomeScreen())
// When navigating to the "/second" route, build the SecondScreen widget.
'/second': (context) => SecondScreen(), //NOTE: Change the SecondScreen() to your own screen's class name (ex: HomeWidget())
'/third': (context) => ThirdScreen(),
},
);
And then, inside your button, navigate to the page:
// Within the `FirstScreen` widget
onPressed: () {
// Navigate to the second screen using a named route.
Navigator.pushNamed(context, '/second');
}
NOTE: One of your pages must be named as / to prevent error, for the full tutorial please visit this link
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