Flutter - How to change child widgets language - flutter

I would like to change all app language without reload app. I used flutter_i18n
I have a switch language button on appBar and AppHomeScreen in body, here is build function in MyHomePage class:
addClickFn(model) {
FocusScope.of(context).requestFocus(FocusNode());
Navigator.push<dynamic>(
context,
MaterialPageRoute<dynamic>(
builder: (BuildContext context) => MyPopupScreen(callback: (c, id) => { }),
fullscreenDialog: true),
);
}
#override
Widget build(BuildContext context) {
return ScopedModelDescendant<ResponseDataModel>(
builder: (context, _, model) => Scaffold(
backgroundColor: AppTheme.white,
body: FutureBuilder<bool>(
future: getData(),
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
if (!snapshot.hasData) {
return const SizedBox();
} else {
return Padding(
padding: EdgeInsets.only(
top: MediaQuery.of(context).padding.top),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
appBar(),
Expanded(
child: FutureBuilder<bool>(
future: getData(),
builder: (BuildContext context,
AsyncSnapshot<bool> snapshot) {
if (!snapshot.hasData) {
return const SizedBox();
} else {
return AppHomeScreen(
addClickFn: () => addClickFn(model));
}
},
),
),
],
),
);
}
},
),
));
}
appBar with onTap switch button function:
Widget appBar() {
return SizedBox(
height: AppBar().preferredSize.height,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 8, left: 8),
child: Container(
width: AppBar().preferredSize.height - 8,
height: AppBar().preferredSize.height - 8,
),
),
Expanded(
child: Center(
child: Padding(
padding: const EdgeInsets.only(top: 4),
child: Text(
FlutterI18n.translate(context, "title"),
style: TextStyle(
fontSize: 22,
color: AppTheme.darkText,
fontWeight: FontWeight.w700,
),
),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 8, right: 8),
child: Container(
width: AppBar().preferredSize.height - 8,
height: AppBar().preferredSize.height - 8,
color: Colors.white,
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius:
BorderRadius.circular(AppBar().preferredSize.height),
child: Image.asset(
'icons/flags/png/' + currentLang.languageCode + '.png',
package: 'country_icons'),
onTap: () async {
setState(() {
currentLang = currentLang.languageCode == 'vn'
? new Locale('gb')
: new Locale('vn');
});
await FlutterI18n.refresh(context, currentLang);
},
),
),
),
),
],
),
);
}
In AppHomePage I included BottomBarView with DashboardScreen as tab body
#override
Widget build(BuildContext context) {
return Container(
color: AppTheme.background,
child: Scaffold(
backgroundColor: Colors.transparent,
body: FutureBuilder<bool>(
future: getData(),
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
if (!snapshot.hasData) {
return const SizedBox();
} else {
return Stack(
children: <Widget>[
tabBody,
bottomBar(),
],
);
}
},
),
),
);
}
Future<bool> getData() async {
await Future<dynamic>.delayed(const Duration(milliseconds: 200));
return true;
}
Widget bottomBar() {
return Column(
children: <Widget>[
const Expanded(
child: SizedBox(),
),
BottomBarView(
tabIconsList: tabIconsList,
addClick: () {
if (widget.addClickFn != null) widget.addClickFn();
},
changeIndex: (int index) {
if (index == 0) {
animationController.reverse().then<dynamic>((data) {
if (!mounted) {
return;
}
setState(() {
tabBody =
DashboardScreen(animationController: animationController);
});
});
}
},
),
],
);
}
And in DashboardScreen I show a label:
#override
Widget build(BuildContext context) {
return Container(
color: AppTheme.background,
child: Scaffold(
backgroundColor: Colors.transparent,
body: Stack(
children: <Widget>[
getMainListViewUI(),
// getAppBarUI(),
SizedBox(
height: MediaQuery.of(context).padding.bottom,
)
],
),
),
);
}
Widget getMainListViewUI() {
return ListView(
scrollDirection: Axis.vertical,
semanticChildCount: 10,
children: <Widget>[
Container(
padding:
EdgeInsets.only(top: 0.0, left: 24, right: 24, bottom: 24.0),
child: Text(FlutterI18n.translate(context, "label.welcome"),
textAlign: TextAlign.left,
style: TextStyle(
fontFamily: AppTheme.fontName,
fontWeight: FontWeight.w700,
fontSize: 30 + 6 - 6 * topBarOpacity,
letterSpacing: 1.2,
color: AppTheme.darkerText,
))),
],
);
}
When I click switch language button, all text in current context (title) translates very well, but in DashboardScreen (label.welcome) are not.
And when I click add button on bottomBar to redirect to MyPopupScreen then close this popup, text in DashboardScreen has been translated.
How can I change all text in DashboardScreen when click switch language button on MyHomePage?
Sorry for my bad english!!!

You call FlutterI18n.refresh with the old currentLang value.
Try this:
setState(() {
currentLang = currentLang.languageCode == 'vn'
? new Locale('gb')
: new Locale('vn');
FlutterI18n.refresh(context, currentLang);
});

Related

Gesture detector on tap not working in flutter release app but working in debug app

I am using firestore and created 4 cards on which the user taps on goes to the next screen. Everything is working fine in debug mode, in debug mode both Inkwell and Gesture Detector are working but when I make a release version I don't know why but both Inkwell and Gesture Detector are not working. Have no idea what's causing this. Please help.
class _RestaurantDashboardState extends State<RestaurantDashboard> {
Widget buildRestaurantCards(String title, IconData iconData, int orderCount) {
return Expanded(
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
if (title == "Menu\nManagement") {
Navigator.push(context,
MaterialPageRoute(builder: (context) => MenuManagement()));
} else if (title == "Current Orders") {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => OrderScreen("In Progress"),
),
);
} else if (title == "Order History") {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => OrderHistory("In Progress"),
),
);
} else if (title == "Update Profile") {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
RestaurantSignUp(Utils.restaurant!.restaurantId, true),
),
);
}
},
child: Container(
height: double.infinity,
child: Card(
margin: EdgeInsets.all(8),
elevation: 8,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
margin: EdgeInsets.only(top: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
orderCount > 0
? Row(
children: [
Container(
alignment: Alignment.center,
width: 30,
height: 30,
margin: EdgeInsets.all(4),
padding: EdgeInsets.all(4),
child: FittedBox(
child: Text(
orderCount.toString(),
style: TextStyle(
color: Colors.white, fontSize: 18),
)),
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(16),
),
)
],
)
: SizedBox(),
Container(
margin: EdgeInsets.symmetric(horizontal: 16),
alignment: Alignment.centerRight,
child: Icon(
iconData,
size: 40,
),
),
],
),
),
Container(
width: double.infinity,
margin:
EdgeInsets.symmetric(horizontal: 16, vertical: 16),
alignment: Alignment.center,
child: FittedBox(
child: Text(
title,
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.w600),
textAlign: TextAlign.center,
),
)),
],
)),
),
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Dashboard'),
),
body: Container(
child: Column(
children: [
Container(
height: MediaQuery.of(context).size.height * 0.25,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
isFirebaseInitialized
? StreamBuilder(
stream: FirebaseFirestore.instance
.collection("orders")
.snapshots(),
builder: (context,
AsyncSnapshot<
QuerySnapshot<Map<String, dynamic>>>
snapshot) {
if (!snapshot.hasData) {
setState(() {
_isLoading = false;
});
return Container();
}
if (snapshot.hasError) {
setState(() {
_isLoading = false;
});
}
List<DocumentSnapshot> itemsList = [];
for (DocumentSnapshot doc
in snapshot.data!.docs) {
if (doc['restaurantId'] ==
Utils.restaurant!.restaurantId &&
doc['orderStatus'] == "In Progress") {
itemsList.add(doc);
}
}
return buildRestaurantCards("Current Orders",
Icons.list_alt, itemsList.length);
},
)
: buildRestaurantCards(
"Current Orders", Icons.list_alt, 0),
buildRestaurantCards("Order History", Icons.history, 0),
],
),
),
Container(
height: MediaQuery.of(context).size.height * 0.25,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
buildRestaurantCards(
"Menu\nManagement", Icons.restaurant_menu_rounded, 0),
buildRestaurantCards("Update Profile", Icons.person, 0),
],
),
),
],
),
)
);
}
}
Check if there are any exceptions caught in the debug console, If there are then fix those, then the issue will be resolved

Flutter different screen navigation using on onTap uncertain ListView

How can i navigate to a different route in ListView querySnapshot.docs[index].data()['image']. In my case all the cards will navigate to different route.
Relevant code with facing this issue:
import 'dart:ui';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:fluttertravelapp/screens/home.dart';
import 'package:fluttertravelapp/screens/location_list_screen.dart';
import 'package:fluttertravelapp/widgets/nav_drawer.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class SelectedCategoryScreen extends StatefulWidget {
SelectedCategoryScreen();
#override
_SelectedCategoryScreen createState() => _SelectedCategoryScreen();
}
class _SelectedCategoryScreen extends State<SelectedCategoryScreen> {
#override
void initState() {
super.initState();
}
final Query query = FirebaseFirestore.instance
.collection("movies")
.orderBy('year', descending: true);
void gotoPage(String pageName) {
switch (pageName) {
case 'home':
{
// statements;
Navigator.push(
context, CupertinoPageRoute(builder: (redContext) => HomePage()));
}
break;
case 'yard':
{
//statements;
Navigator.push(
context,
CupertinoPageRoute(
builder: (redContext) => LocationListScreen()));
}
break;
default:
{
throw new Exception("Path ${pageName} not supported");
}
break;
}
}
/// Page Controller
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(Icons.arrow_back_ios_new_sharp),
),
title: Container(
width: 170,
child: Image.network(
'https://i.hizliresim.com/sf4asddsau.jpg',
),
),
centerTitle: true,
actions: [
IconButton(
onPressed: () {},
icon: Icon(Icons.cloud_queue_outlined),
),
],
),
drawer: NavDrawer(),
body: SafeArea(
child: Container(
child: StreamBuilder(
stream: query.snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
} else if (snapshot.hasError) {
return Center(
child: Icon(Icons.error),
);
}
final QuerySnapshot<Map<String, dynamic>> querySnapshot =
snapshot.data;
return ListView(
physics: BouncingScrollPhysics(),
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 28.8, bottom: 16.8),
height: 724.8,
child: ListView.builder(
itemCount: querySnapshot.size,
padding: EdgeInsets.only(left: 28.8, right: 12),
scrollDirection: Axis.vertical,
physics: BouncingScrollPhysics(),
itemBuilder: (context, index) {
return Container(
height: 214.8,
width: 188.4,
margin: EdgeInsets.only(right: 16.8, bottom: 50),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(9.6),
image: DecorationImage(
fit: BoxFit.cover,
image: CachedNetworkImageProvider(
querySnapshot.docs[index].data()['image'],
maxHeight: 200,
maxWidth: 200),
),
),
child: Stack(
children: <Widget>[
GestureDetector(
onTap: () {
GestureDetector(
onTap: () => gotoPage(querySnapshot
.docs[index]
.data()['page']));
/* Navigator.push(
context,
CupertinoPageRoute(
builder: (redContext) => MyApp()));*/
},
),
Positioned(
bottom: 19.2,
left: 19.2,
child: ClipRRect(
borderRadius: BorderRadius.circular(4.8),
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaY: 19.2, sigmaX: 19.2),
child: Container(
height: 26,
padding: EdgeInsets.only(
left: 0.0, right: 0.0),
alignment: Alignment.centerLeft,
child: Row(
children: <Widget>[
SizedBox(
width: 9.52,
),
SvgPicture.asset(
'assets/svg/icon_location.svg'),
SizedBox(
width: 9.52,
),
SvgPicture.asset(
'assets/svg/icon_location.svg',
height: 50,
),
SizedBox(
width: 9.52,
),
SvgPicture.asset(
'assets/svg/icon_location.svg'),
SizedBox(
width: 9.52,
),
/* Text(
recommendations[index].name,
style: GoogleFonts.lato(
fontWeight: FontWeight.w700,
color: Colors.white,
fontSize: 16.8),
) */
],
),
),
),
),
),
Align(
alignment: Alignment.center,
child: Container(
margin: EdgeInsets.all(70),
child: Text(
querySnapshot.docs[index].data()['title'],
style: TextStyle(
fontSize: 27,
color: Colors.white,
fontWeight: FontWeight.bold),
textAlign: TextAlign.left,
),
),
),
],
),
);
},
),
)
],
);
},
),
),
),
);
}
}
Firestore:
If you look at the picture you can easily understand what I mean.
I am not sure how your document from QuerySnapshot looks like but you could add a field/property that contains the name of the page to be navigated to. Then add a function with a switch-case or if-else statements that control which page to navigate to in your onTap().
void gotoPage(String pageName){
switch(pageName) {
case 'home': {
// statements;
Navigator.push(context,CupertinoPageRoute(builder: (redContext) => HomePage()));
}
break;
case 'yard': {
//statements;
Navigator.push(context,CupertinoPageRoute(builder: (redContext) => YardPage()));
}
break;
default: {
throw new Exception(`Path ${pageName} not supported`);
}
break;
}
}
then call it in onTap.
GestureDetector(onTap: () => gotoPage(querySnapshot.docs[index].data()['page']) ),
where page will be the field/property with the pageName that you would have added to your document

Horizontal viewport was given unbounded height while using PageView.Builder

I'm working on simple quiz app with BLoC pattern. Tried to implement swipe feature for each quiz with PageView.Builder, here is my code
class _QuizScreenState extends State<QuizScreen> {
#override
void initState() {
context.read<QuizInfoBloc>().add(GetQuizStat("1"));
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
backgroundColor: kSecondaryColor,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
actions: [],
),
body: Container(
decoration: BoxDecoration(color: kSecondaryColor),
width: double.infinity,
height: double.infinity,
child: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 0),
child: Column(
children: [
Padding(
padding:
const EdgeInsets.symmetric(horizontal: kDefaultPadding / 2),
child: ProgressBar(),
),
Spacer(
flex: 1,
),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: kDefaultPadding / 2),
child: BlocConsumer<QuizInfoBloc, QuizInfoState>(
listener: (context, state) {
// TODO: implement listener
},
builder: (context, state) {
if (state is QuizInfoLoaded) {
return PageView.builder(
itemCount: state.quiz.questions.length,
itemBuilder: (context, index) => QuestionCard(
question: state.quiz.questions[index]));
} else {
return Container(
height: 0,
width: 0,
);
}
},
),
),
Spacer(
flex: 4,
),
BottomButtons(),
SizedBox(
height: 20,
),
// AnswerExplanation(
// correctOrWrong: kGreenColor,
// ),
],
),
)),
),
);
}
}
I've tried with wrapping PageView.Builder with Expanded which was wrapped with Column. But still getting a different error
Padding(
padding:
const EdgeInsets.symmetric(horizontal: kDefaultPadding / 2),
child: BlocConsumer<QuizInfoBloc, QuizInfoState>(
listener: (context, state) {
// TODO: implement listener
},
builder: (context, state) {
if (state is QuizInfoLoaded) {
return Column(
children: [
Expanded(
child: PageView.builder(
itemCount: state.quiz.questions.length,
itemBuilder: (context, index) => QuestionCard(
question: state.quiz.questions[index])),
),
],
);
} else {
return Container(
height: 0,
width: 0,
);
}
},
),
),
RenderFlex children have non-zero flex but incoming height constraints
are unbounded.
QuestionCard
class _QuestionCardState extends State<QuestionCard> {
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(kDefaultPadding / 2),
child: Column(
children: [
Text(
this.widget.question.questionText,
style: Theme.of(context)
.textTheme
.headline5
?.copyWith(color: Colors.white, fontWeight: FontWeight.bold),
),
SizedBox(
height: 30,
),
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: this.widget.question.options.length,
itemBuilder: (BuildContext context, int index) {
return OptionUI(option: this.widget.question.options[index]);
})
],
),
);
}
}
Since you already have a kSecondaryColor as backgroundColor of your Scaffold, you don't need a Container as body of your Scaffold:
Scaffold(
extendBodyBehindAppBar: true,
backgroundColor: kSecondaryColor,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
actions: [],
),
body: SafeArea(
// child: ...
),
)
A SafeArea widget is meant to be used on the top-level widget tree:
SafeArea(
Scaffold(
extendBodyBehindAppBar: true,
backgroundColor: kSecondaryColor,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
actions: [],
),
body: Padding(
// child: ...
),
)
)
Wrap an Expanded into the Padding of your BlocConsumer:
Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: kDefaultPadding / 2),
child: ProgressBar(),
),
Spacer(flex: 1),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: kDefaultPadding / 2),
child: BlocConsumer<QuizInfoBloc, QuizInfoState>(
listener: (context, state) {
// TODO: implement listener
},
builder: (context, state) {
if (state is QuizInfoLoaded) {
return PageView.builder(
itemCount: state.quiz.questions.length,
itemBuilder: (context, index) =>
QuestionCard(question: state.quiz.questions[index]));
} else {
return Container(height: 0, width: 0);
}
},
),
),
),
Spacer(flex: 4),
BottomButtons(),
SizedBox(height: 20),
// AnswerExplanation(correctOrWrong: kGreenColor),
],
);
You didn't provide the ProgressBar, QuestionCard and BottomButtons widgets, so if the error persists you should check them, but I think these changes should suffice.

Future builder not updating once i have resposne

I have a page where once i have response i need to display items
here is my code
It keeps on showing loader and futureBuilder never gets triggered
#override
void initState() {
super.initState();
helper.getString(TOKEN_ID).then((value) {
userResponseFuture = repos.getUserDetails(value);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: EdgeInsets.all(10),
alignment: Alignment.center,
color: Colors.white,
child: FutureBuilder<UserResponse>(
future: userResponseFuture,
builder: (context, snapShot) {
if (snapShot.hasData) {
return Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
CircleAvatar(
radius: 50.0,
backgroundImage: NetworkImage(snapShot
.data.profilePictureURL ??
"https://cdn.mos.cms.futurecdn.net/5e7ehPZf5RT6Jt2H9cQP6k-1024-80.jpg.webp"),
backgroundColor: Colors.brown,
),
FlatButton(
child: Row(
children: [
Icon(Icons.edit),
Text("Edit profile Image"),
],
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
ProfilePicScreen()));
},
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
snapShot.data.firstName +
" " +
snapShot.data.lastName,
style: TextStyle(color: Colors.blue.shade900)),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(snapShot.data.email,
style: TextStyle(color: Colors.blue.shade900)),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(snapShot.data.phoneNo ?? "",
style: TextStyle(color: Colors.blue.shade900)),
)
],
);
} else {
return SizedBox(
height: 30.0,
width: 30.0,
child: CircularProgressIndicator(
strokeWidth: 2.0,
));
}
},
)),
);
}
}
You need to add setState after assign a value to userResponseFuture;
helper.getString(TOKEN_ID).then((value) {
userResponseFuture = repos.getUserDetails(value);
setState((){})
});
because it is being after build method and your widget can't call the right future function.

A RenderFlex overflowed by 1443 pixels on the bottom

I am trying to make it scrollable...enter image description here For some reason its not not scrolling and i tried adding singleChildScrollview still not working.... Pls look at the picture to understand better... so i posted the full code so that you guys can help me better... This was the error i got "Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the RenderFlex to fit within the available space instead of being sized to their natural size. This is considered an error condition because it indicates that there is content that cannot be seen. If the content is legitimately bigger than the available space, consider clipping it with a ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex, like a ListView."
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:memoryblog/helper/authenticate.dart';
import 'package:memoryblog/services/auth.dart';
import 'package:memoryblog/services/database.dart';
import 'package:memoryblog/views/create_blog.dart';
class MemoryRoom extends StatefulWidget {
#override
_MemoryRoomState createState() => _MemoryRoomState();
}
class _MemoryRoomState extends State<MemoryRoom> {
AuthMethod authMethod = new AuthMethod();
DatabaseMethods databaseMethod = new DatabaseMethods();
Stream blogsStream;
Widget BlogsList(){
return Container(
child: blogsStream != null ? Column(
children: <Widget>[
StreamBuilder(
stream: blogsStream,
builder: (context, snapshot){
if(snapshot.data == null) return CircularProgressIndicator();
return ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 16),
itemCount: snapshot.data.documents.length,
shrinkWrap: true,
itemBuilder: (context, index){
return BlogsTile(
authorName: snapshot.data.documents[index].data['memoryName'],
title: snapshot.data.documents[index].data['title'],
description: snapshot.data.documents[index].data['desc'],
imgUrl: snapshot.data.documents[index].data['imgUrl'],
);
}
);
},
)
],
) : Container(
alignment: Alignment.center,
child: CircularProgressIndicator(),
)
);
}
#override
void initState() {
// TODO: implement initState
databaseMethod.getData().then((result){
setState(() {
blogsStream = result;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Row(
children: <Widget>[
Text(
"Memory"
),
Text(
"Blog",
style: TextStyle(
color: Colors.blue
),
)
],
),
backgroundColor: Colors.transparent,
elevation: 0.0,
actions: <Widget>[
GestureDetector(
onTap: (){
authMethod.signOut();
Navigator.pushReplacement(context, MaterialPageRoute(
builder: (context) => Authenticate()
));
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Icon(Icons.power_settings_new)),
)
],
),
body: BlogsList(),
floatingActionButton: Container(
padding: EdgeInsets.symmetric(vertical: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FloatingActionButton(
onPressed: (){
Navigator.push(context, MaterialPageRoute(
builder: (context) => CreateBlog()
));
},
child: Icon(Icons.add),
)
],
),
),
);
}
}
class BlogsTile extends StatelessWidget {
String imgUrl, title, description, authorName;
BlogsTile({#required this.imgUrl, #required this.title, #required this.description, #required this.authorName,});
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(bottom: 16),
height: 170,
child: Stack(
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.circular(6),
child: CachedNetworkImage(
imageUrl: imgUrl,
width: MediaQuery.of(context).size.width,
fit: BoxFit.cover,
)
),
Container(
height: 170,
decoration: BoxDecoration(
color: Colors.black45.withOpacity(0.3),
borderRadius: BorderRadius.circular(6)
),
),
Container(
width: MediaQuery.of(context).size.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
title,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 25, fontWeight: FontWeight.w500),
),
SizedBox(height: 4,),
Text(
description,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w400),
),
SizedBox(height: 4,),
Text(authorName)
],
),
)
],
),
);
}
}
Use ListView in place of the column. OR
Wrap Column with SingleChildScrollView
return Container(
child: blogsStream != null
? ListView(
children: <Widget>[
StreamBuilder(
stream: blogsStream,
builder: (context, snapshot) {
if (snapshot.data == null) return CircularProgressIndicator();
return ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 16),
itemCount: snapshot.data.documents.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return BlogsTile(
authorName:
snapshot.data.documents[index].data['memoryName'],
title: snapshot.data.documents[index].data['title'],
description:
snapshot.data.documents[index].data['desc'],
imgUrl: snapshot.data.documents[index].data['imgUrl'],
);
});
},
)
],
)
: Container(
alignment: Alignment.center,
child: CircularProgressIndicator(),
),
);