Grey screen in release mode (IOS - Flutter) - ios

I am getting a grey screen on two pages in my app, I m facing this problem only in release mode when I installed it from TestFlight. there is no error in debug mode, and it works fine also when I run it in release mode from android studio.
this is my code on two screens:
First screen:
ViewModelBuilder<TraineeCoachViewModel>.nonReactive(
builder: (context, model, child) => Layout(
title: coachFullName,
body:
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(Assets.rightBackground),
fit: BoxFit.cover,
colorFilter: ColorFilter.mode(
Colors.black.withOpacity(0.2), BlendMode.dstATop),
),
),
child:
SingleChildScrollView(
child: Column(
children: [
FutureBuilder(
future: model.getCoachModel,
initialData: null,
builder: (BuildContext context,
AsyncSnapshot<CoachModel?> snapshot) {
if (!snapshot.hasData || snapshot.data == null) {
return const Loading();
}
final CoachModel coachmodel = snapshot.data!;
final List<String> additionalPhotos = coachmodel.album ?? [];
final String profilePhoto = coachmodel.profilePhoto ?? "";
final List<String?> imagesToSlide = [
profilePhoto,
...additionalPhotos
];
final _slideImageItemwidth =
MediaQuery.of(context).size.width / 2;
final _slideImageItemHeight =
MediaQuery.of(context).size.width / 2.5;
return
SingleChildScrollView(
padding: const EdgeInsets.all(10.0),
child:
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Container(
height: _slideImageItemwidth,
width: _slideImageItemHeight,
decoration: BoxDecoration(
border: Border.all(
color: Colors.yellowAccent,
width: 1.0,
)),
child: PageView.builder(
itemCount: imagesToSlide.length,
itemBuilder: (_, index) {
final String? image = imagesToSlide[index];
return Hero(
tag: index.toString() + "S",
child: GestureDetector(
onTap: () => Navigator.push(
context,
MaterialPageRoute(
fullscreenDialog: true,
builder: (BuildContext
context) =>
HeroPhoto(
imageUrl: image,
tag:
index.toString() +
"S"))),
child: CardItemProfilePhoto(
iconSize: 50,
imageUrl: image,
withBorderDecoration: false,
size: Size(_slideImageItemwidth,
_slideImageItemwidth),
),
));
}),
),
),
verticalSpaceMedium,
additionalPhotos.isNotEmpty
? GridView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: additionalPhotos.length,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
childAspectRatio: 0.7,
mainAxisSpacing: 5.0,
crossAxisSpacing: 5.0),
itemBuilder: (_, index) {
return Hero(
tag: "${index + 1}",
child: GestureDetector(
onTap: () => Navigator.push(
context,
MaterialPageRoute(
fullscreenDialog: true,
builder: (BuildContext context) =>
HeroPhoto(
imageUrl:
additionalPhotos[
index],
tag: "${index + 1}"),
)),
child: LayoutBuilder(
builder: (BuildContext context,
BoxConstraints constraints) {
return CardItemProfilePhoto(
iconSize: 20,
imageUrl: additionalPhotos[index],
size: constraints.biggest,
);
},
),
),
);
})
: Container(),
coachmodel.bio != null
? verticalSpaceMediumS
: Container(),
coachmodel.bio != null
? AppText.headingTwo(
localizations.bio + ":",
)
: Container(),
verticalSpaceNormal,
Text(
coachmodel.bio ?? "",
style: captionStyle,
),
coachmodel.bio != null
? verticalSpaceMediumS
: Container(),
StreamBuilder(
stream: model.coursesStream,
builder: (BuildContext context,
AsyncSnapshot<List<CourseModel>> snapshot) {
if (!snapshot.hasData || snapshot.data == null) {
return const Loading(
showBackgroundColor: false,
);
}
final courses = snapshot.data
?.where((element) =>
element.isSameType(courseType))
.toList();
if (model.isBusy) {
WidgetsBinding.instance!
.addPostFrameCallback((timeStamp) {
model.setBusy(false);
});
}
return ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: courses!.length,
itemBuilder: (_, index) {
final courseModel = courses[index];
bool found = false;
if (courses[index].traineesIn != null &&
model.userId != '') {
found = courses[index]
.traineesIn!
.contains(model.userId);
}
///Subscription button
return SizedBox(
height: screenHeightPercentage(context,
percentage: 0.10),
width: double.infinity,
child: SubscriptionItemShaped(
params: getParams(courseModel,
model, localizations,
traineeIdFound: found,
context: context)));
});
},
),
]),
);
},
),
],
),
),
),
resizeToAvoidBottomInset: true,
),
viewModelBuilder: () => getIt<TraineeCoachViewModel>()
..coachId = coachID
..coachName = coachFullName
..init(),
);
Second screen:
ViewModelBuilder<NotificationsViewModel>.nonReactive(
builder: (context, model, child) {
return Layout(
title: localizations.subs_detail,
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(Assets.rightBackground),
fit: BoxFit.cover,
colorFilter: ColorFilter.mode(
Colors.black.withOpacity(0.2), BlendMode.dstATop),
),
),
child: SingleChildScrollView(
child: Container(
padding: EdgeInsets.only(
top: screenHeightPercentage(context, percentage: 0.03)),
child: Column(
children: [
FutureBuilder<TraineeModel?>(
future: model.getTraineeModel(subsModel.traineeId!),
initialData: null,
builder: (BuildContext context,
AsyncSnapshot<TraineeModel?> snapshot) {
if (!snapshot.hasData || snapshot.data == null) {
return const Loading();
}
final TraineeModel userModel = snapshot.data!;
return Padding(
padding: EdgeInsets.only(
left: screenWidthPercentage(context,
percentage: 0.05)),
child: Column(
children: [
Text(localizations.trainee_detail.toUpperCase(),
style:
heading1Style.copyWith(fontSize: 20)),
verticalSpaceMedium,
CircularProfilePhoto(
imageurl: userModel.profilePhoto,
iconSize: 30,
height: screenHeightPercentage(context,
percentage: 0.17),
width: screenHeightPercentage(context,
percentage: 0.17),
),
verticalSpaceMedium,
Padding(
padding: langauge.appLocal.languageCode ==
'ar'
? EdgeInsets.only(
left: screenWidthPercentage(context,
percentage: 0.20),
right: screenWidthPercentage(context,
percentage: 0.2),
)
: EdgeInsets.only(
left: screenWidthPercentage(context,
percentage: 0.23),
),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Column(
children: [
Text(
userModel.fullName!.toUpperCase(),
style: heading1Style.copyWith(
fontSize: 15,
color: kcWhiteColor),
),
verticalSpaceMedium,
Text(
userModel.gender.toUpperCase(),
style: heading1Style.copyWith(
fontSize: 15,
color: kcWhiteColor),
),
],
),
Column(
children: [
userModel.height != null
? verticalSpaceMedium
: Container(),
// userModel.height != null ?
Container(
margin: EdgeInsets.only(
right: screenWidthPercentage(
context,
percentage: 0.25)),
child: Text(
userModel.height != null
? '${userModel.height!.toString()} ${localizations.cm}'
: '0.0 ${localizations.cm}',
style: heading1Style.copyWith(
fontSize: 15,
color: kcWhiteColor),
),
),
//: Container(),
verticalSpaceMedium,
Container(
margin: EdgeInsets.only(
right: screenWidthPercentage(
context,
percentage: 0.25)),
child: Text(
userModel.weight != null
? '${userModel.weight!.toString()} ${localizations.kg}'
: '0.0 ${localizations.kg}',
style: heading1Style.copyWith(
fontSize: 15,
color: kcWhiteColor),
),
)
],
)
],
),
),
],
),
);
}),
verticalSpaceMedium,
Container(
height: 1,
color: kcWhiteColor,
margin: EdgeInsets.symmetric(horizontal: 30),
),
verticalSpaceMedium,
Text(localizations.course_detail.toUpperCase(),
style: heading1Style.copyWith(fontSize: 20)),
verticalSpaceMedium,
Text(subsModel.courseName!.toUpperCase(),
style: heading1Style.copyWith(
fontSize: 25, color: kcWhiteColor)),
verticalSpaceMedium,
Text(
'${subsModel.coursePrice} ${localizations.currency_code}',
style: heading1Style.copyWith(
fontSize: 25, color: kcWhiteColor)),
StreamBuilder<SubscriptionModel>(
stream: model.getSubscription(subsModel.id!),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Loading(
showBackgroundColor: false,
);
}
return Container(
margin: EdgeInsets.only(
top: screenHeightPercentage(context,
percentage: 0.1)),
child: snapshot.data!.subscriptionStatus.value ==
SUBSCRIPTION_STATUS
.WAITING_PAYMENT.value ||
snapshot.data!.subscriptionStatus.value ==
SUBSCRIPTION_STATUS.REJECTED.value ||
snapshot.data!.subscriptionStatus.value ==
SUBSCRIPTION_STATUS.BLOCKED.value
? StatusText(
status: snapshot
.data!.subscriptionStatus.value,
subscriptionModel: snapshot.data!,
localizations: localizations,
notificationsViewModel: model,
)
: Row(
children: [
Expanded(
child: ButtonWidget(
subscriptionModel: snapshot.data!,
localizations: localizations,
notificationsViewModel: model,
text: localizations.accept
.toUpperCase(),
color: Colors.green,
onPressed: () {
model.accept(snapshot.data!);
},
),
),
// ),
Expanded(
child: ButtonWidget(
subscriptionModel: snapshot.data!,
localizations: localizations,
notificationsViewModel: model,
text: localizations.chat_status
.toUpperCase(),
color: Colors.blueGrey,
onPressed: () {
model.chat(snapshot.data!);
},
),
),
Expanded(
child: ButtonWidget(
subscriptionModel: snapshot.data!,
localizations: localizations,
notificationsViewModel: model,
color: Colors.redAccent,
onPressed: () {
model.reject(
snapshot.data!, context);
},
text: localizations.reject
.toUpperCase(),
),
),
Expanded(
child: ButtonWidget(
subscriptionModel: snapshot.data!,
localizations: localizations,
notificationsViewModel: model,
color: Colors.red,
onPressed: () {
model.block(
snapshot.data!, context);
},
text: localizations.block
.toUpperCase(),
),
),
],
));
})
],
),
),
),
),
);
},
viewModelBuilder: () => getIt<NotificationsViewModel>()..init(),
);
I have been testing it on various devices, and I got the same problem.

As mentioned by #Amina Bekir, the issue was that they had two copies of the project, so Android Studio had the new copy while Xcode has the old one.
Then the old code was uploaded to TestFlight making this behavior to appear.

Related

Add more fields after a listview.builder

I have a statefull layout with a listview.builder inside the builder I have a couple of expansionTile widgets
How do I show the entire list on the screen and add some textform widget below the list?
I have added a Expanded widget around the list to allow for more widgets below it but the list gets cut at a certain point where I want to show the entire list and then the text widgets after
class ContactUsScreen extends StatefulWidget {
const ContactUsScreen({Key? key}) : super(key: key);
static const String contactRouteName = "/contactScreen";
#override
State<ContactUsScreen> createState() => _ContactUsScreenState();
}
class _ContactUsScreenState extends State<ContactUsScreen> {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text("Contact Us"),
centerTitle: true,
),
body: CustomScrollView(
slivers: [
SliverFillRemaining(
hasScrollBody: true,
child: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: salesList.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
elevation: 5,
child: ExpansionTile(
key: PageStorageKey<ContactPeople>(salesList[index]),
controlAffinity: ListTileControlAffinity.leading,
childrenPadding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
expandedCrossAxisAlignment: CrossAxisAlignment.end,
maintainState: true,
title: Text(
salesList[index].regionDescription,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
children: //[Text("Test")],
salesList[index].people!.map(
(peopleRecord) {
return ExpansionTile(
expandedCrossAxisAlignment: CrossAxisAlignment.start,
key: PageStorageKey<ContactUsScreen>(peopleRecord),
title: Align(
alignment: Alignment.topLeft,
child: Row(
children: [
ClipOval(
child: Image.asset(
"assets/images/people/${peopleRecord.avatarImage}",
fit: BoxFit.cover,
width: 60,
height: 60,
),
),
SizedBox(
width: 10,
),
Text(
peopleRecord.name,
style: const TextStyle(fontSize: 15),
),
],
),
),
children: [
Text(
peopleRecord.title,
style: const TextStyle(fontWeight: FontWeight.bold),
),
Text(peopleRecord.cellPhoneNumber),
Text(
peopleRecord.emailAddress,
),
const SizedBox(
height: 5,
),
],
);
},
).toList(),
),
),
);
}),
),
SizedBox(height: 15,),
Text("Contact us directly",
style: TextStyle(fontWeight: FontWeight.w700,
fontSize: 20,
color: Colors.black),),
Form(
key: formKey,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextFormField(controller: fullNameController,
keyboardType: TextInputType.text,
decoration: InputDecoration(labelText: "Full Name",
hintText: "Full Name",
),
validator: (inputFieldFullName)
{
if(inputFieldFullName!.isEmpty)
{
return "Please enter your Full Name";
}
else
{
return null;
}
},
),
TextFormField(controller: contactNumberController,
keyboardType: TextInputType.number,
decoration: InputDecoration(labelText: "Contact Number",
hintText: "Contact Number",
),
validator: (inputFieldContactNumber)
{
if(inputFieldContactNumber!.isEmpty)
{
return "Please enter your contact number";
}
else
{
return null;
}
},
),
SizedBox(height: 5,),
ElevatedButton(
onPressed: () {
if(formKey.currentState!.validate())
{
//Send the email
}
else
{
const SnackBar snackBar = SnackBar(duration: Duration(seconds: 2), content: Text("Please correct the errors"));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
},
child: Text("Submit"),
),
SizedBox(height: 20,),
],
),
),
),
//getContactForm(context, formKey),
],
),
)
],
)
),
);
}
}
The end result should be that we display the entire list of parent expansion tile, and then only after the textform fields
Regards
You have to use this structure:
CustomScrollView(
slivers: <Widget>[
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return ** first listview **
},
childCount: top.length,
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return ** second listview **
},
childCount: bottom.length,
),
),
],
),

iOS Flutter- How to size string emoji?

My application does not get the alignment problem in the examples I will show below while running on android devices. When I want to run it on my iOS device, I have the following alignment problem.
Problematic alignment starts here. My app experiences a completely symmetrical change when I choose the Persian or Arabic language and some emojis are aligned properly while others appear distorted.
My Code :
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: ortaMavi,
leading: IconButton(
onPressed: () {
Navigator.of(context).pop();
},
icon: Icon(
Icons.arrow_back_ios,
size: 20,
color: Colors.white,
)),
title: Center(child: Text(titleHolder)),
actions: <Widget>[
Center(
child: Container(
margin: EdgeInsets.all(15),
child: Text(
flagHolder,
style: TextStyle(fontSize: 25),
)),
)
],
),
body: SafeArea(
child: ListView.builder(
padding: const EdgeInsets.symmetric(vertical: 5),
itemCount: countries.length,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
EasyLocalizationProvider.of(context)
.data
.changeLocale(langs[index]);
setState(() {
titleHolder = countries[index];
flagHolder = flags[index];
selectedLangIndex = index;
});
},
child: Container(
decoration: BoxDecoration(
color:
selectedLangIndex != null && selectedLangIndex == index
? ortaMavi.withOpacity(0.2)
: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.lightBlueAccent.withOpacity(0.5),
spreadRadius: 2,
blurRadius: 3,
offset: Offset(0, 3), // changes position of shadow
),
],
),
height: 50,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'${countries[index]}',
style: TextStyle(
fontSize: 20,
color: selectedLangIndex != null &&
selectedLangIndex == index
? Colors.white
: Colors.black),
),
Text(
flags[index],
style: TextStyle(fontSize: 25),
)
],
),
),
),
);
}),
),
);
}
You can put the flags String inside a SizedBox
SizedBox(
width: 200.0,
height: 200.0,
child:Text(
flags[index],
),
)

Flutter app crashes very often after populating it with data and no errors are showed, just lost connection to device

I have a flutter app that is complex enough and i have been developing it for a while.
the problem is after finishing up with the design code , i started implementing API's to receive actual data and populate the app with it. the app is now crashing quite a lot ( although a little less in release mode).
I am thinking it might be because the android device runs out of memory because of all the complex widgets I display in the app.
I have build all of my widgets Stateful I don't know if that could be a related factor (I am a beginner with flutter programming).
Please I have spent a lot of time in developing this app and it's my first enterprise level flutter app.
I haven't had experience with flutter before and I knew this kind of problems would arise and have no solution I would have gone with Java and Swift to develop the app.
Any help is appreciated guys. Thanks.
the app only displays about a 30-40 images, I don't know where all the data coming from.
Here is the code :
import 'package:flutter/material.dart';
import 'package:bestiee/componenets/constants.dart';
import 'package:bestiee/componenets/cards/single-item-hot-screen-card.dart';
import 'package:bestiee/componenets/buttons/small-round-more-button.dart';
import 'package:bestiee/componenets/cards/single-place-hot-screen-card.dart';
import 'package:bestiee/componenets/cards/single-person-hot-screen-card.dart';
import 'package:bestiee/componenets/cards/single-place-large-hot-screen-card.dart';
import 'package:bestiee/screens/hotScreenSingleScreens/more-hot-items-screen.dart';
import 'package:bestiee/screens/hotScreenSingleScreens/more-hot-places-screen.dart';
import 'package:bestiee/screens/hotScreenSingleScreens/more-hot-people-screen.dart';
import 'package:bestiee/translations.dart';
import 'package:bestiee/models/models.dart';
import 'package:bestiee/networking.dart';
import 'package:bestiee/constants.dart';
import 'dart:convert';
import 'package:http/http.dart';
class HotScreen extends StatefulWidget {
static List<Item> items = [];
static List<Place> places = [];
static List<Person> people = [];
static bool isFirstRun = true;
#override
_HotScreenState createState() => _HotScreenState();
}
class _HotScreenState extends State<HotScreen> {
String getTranslation(String text) {
try {
String translation = Translations.of(context).text(text);
return translation;
} catch (ex) {
print(ex);
return '';
}
}
getAllPlaces() async {
HotScreen.places.removeRange(0, HotScreen.places.length);
Response response = await getRequest(devBaseURL + plainPlaceAPI);
var allPlacesMap = jsonDecode(response.body);
print(allPlacesMap.length);
for (int i = 0; i < allPlacesMap.length; i++) {
var json = allPlacesMap[i];
Place place = Place.fromJson(json);
setState(() {
HotScreen.places.add(place);
});
}
}
getAllItems() async {
HotScreen.items.removeRange(0, HotScreen.items.length);
Response response = await getRequest(devBaseURL + plainItemAPI);
var allItemsMap = jsonDecode(response.body);
for (int i = 0; i < allItemsMap.length; i++) {
var json = allItemsMap[i];
Item item = Item.fromJson(json);
setState(() {
HotScreen.items.add(item);
});
}
}
getAllPeople() async {
HotScreen.people.removeRange(0, HotScreen.people.length);
Response response = await getRequest(devBaseURL + plainPersonAPI);
var allPeopleMap = jsonDecode(response.body);
for (int i = 0; i < allPeopleMap.length; i++) {
var json = allPeopleMap[i];
Person person = Person.fromJson(json);
setState(() {
HotScreen.people.add(person);
});
}
}
#override
void initState() {
super.initState();
if(HotScreen.isFirstRun == true){
getAllItems();
getAllPlaces();
getAllPeople();
HotScreen.isFirstRun = false;
}
}
#override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return Scaffold(
body: Container(
decoration: kPageMainBackgroundColorBoxDecoration,
child: SafeArea(
child: Padding(
padding: const EdgeInsets.all(8.0),
//main screen scrollable widgets
child: ListView(
shrinkWrap: true,
children: <Widget>[
Text(
getTranslation('Bestiee'),
style: kBazarGalleryTitleStyle,
),
SizedBox(
height: 20,
),
Padding(
padding: const EdgeInsets.only(bottom: 10),
child: Text('Featured Items', style: kFeatureTitleTextStyle),
),
Container(
height: 700 / 3.5,
child: ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: HotScreen.items.length,
itemBuilder: (contet, int index) {
return SingleItemCard(
item: HotScreen.items[index],
isPersonItem: false,
moduleName: HotScreen.items[index].moduleName,
);
}),
),
SizedBox(
height: 10,
),
//more button
Align(
alignment: Alignment.topLeft,
child: Container(
width: 80,
height: 30,
child: SmallRoundMoreButton(onPressed: () {
Navigator.pushNamed(context, MoreHotItemsScreen.id);
}),
),
),
SizedBox(
height: 20,
),
//second hand section
Padding(
padding: const EdgeInsets.only(bottom: 10),
child: Text('Second Hand', style: kFeatureTitleTextStyle),
),
// Container(
// height: 700 / 3.5,
// child: ListView.builder(
// scrollDirection: Axis.horizontal,
// shrinkWrap: true,
// itemCount: 9,
// itemBuilder: (contet, int index) {
// return SingleItemCard();
// }),
// ),
SizedBox(
height: 10,
),
Align(
alignment: Alignment.topLeft,
child: Container(
width: 80,
height: 30,
child: SmallRoundMoreButton(
onPressed: () {
Navigator.pushNamed(context, MoreHotItemsScreen.id);
},
),
),
),
SizedBox(
height: 30,
),
//places section
Text(
'Featured Plces',
style: kFeatureTitleTextStyle,
),
Container(
height: 140,
child: ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: HotScreen.places.length,
itemBuilder: (context, int index) {
return Container(
width: 190,
height: 100,
child: SinglePlaceCard(
place: HotScreen.places[index],
));
},
),
),
//
Align(
alignment: Alignment.topLeft,
child: Container(
width: 80,
height: 30,
child: SmallRoundMoreButton(
onPressed: () {
Navigator.pushNamed(context, MoreHotPlacesScreen.id);
},
),
),
),
SizedBox(
height: 30,
),
//people section
Padding(
padding: const EdgeInsets.only(bottom: 10.0),
child: Text(
'People',
style: kFeatureTitleTextStyle,
),
),
Container(
height: 120,
child: ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: HotScreen.people.length,
itemBuilder: (context, int index) {
return Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(right: 8.0),
child: SinglePersonHotScreenCard(
person: HotScreen.people[index],
),
),
);
},
),
),
Align(
alignment: Alignment.topLeft,
child: Container(
width: 80,
height: 30,
child: SmallRoundMoreButton(
onPressed: () {
Navigator.pushNamed(context, MoreHotPeopleScreen.id);
},
),
),
),
SizedBox(
height: 60,
),
//single shops section
Container(
height: 100.0 * 3,
child: Column(
children: List.generate(5, (index) {
return Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(right: 8.0),
child: SinglePlaceLargeHotCard(place: HotScreen.places[index],)
),
);
}),
)
),
],
),
),
),
),
);
}
}
code for SingleItemCard :
class SingleItemCard extends StatelessWidget {
SingleItemCard({
this.cardHeight = 300,
this.cardWidth = 200,
this.color = kAppOrangeColor,
this.isExtraInfoShowen = true,
this.item,
this.isPersonItem,
this.moduleName});
final double cardHeight;
final double cardWidth;
final Color color;
final bool isExtraInfoShowen;
final Item item;
final bool isPersonItem;
final String moduleName;
#override
Widget build(BuildContext context) {
String imageURL ;
//remove the null part in production
if(item.moduleName == 'item' || item.moduleName == null ){
imageURL = imageBaseURLPlaces + item.imageVariants[0].imageURL;
}else if (item.moduleName == 'person' ){
imageURL = imageBaseURLPeople + item.imageVariants[0].imageURL;
print(imageURL);
}
int ratingUserCount = item.ratingUserCount;
return FittedBox(
child: Padding(
padding: const EdgeInsets.only(right: 7),
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SingleItemScreen(
item: item,
),
),
);
},
child: Stack(
alignment: Alignment.bottomRight,
children: <Widget>[
//upper item description
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Visibility(
visible: isExtraInfoShowen,
child: CircleRater(
isRatingDisabled: true,
rating: item.rating,
ratingUserCount: item.ratingUserCount != null ? ratingUserCount : 0,
),
),
SizedBox(
width: 150,
child: Text(
// 'Item Name Here no. 1',
item.name,
overflow: TextOverflow.clip,
style: TextStyle(
fontSize: 15,
color: Colors.black,
fontWeight: FontWeight.w500),
softWrap: false,
),
),
//item card
Container(
height: cardHeight,
width: cardWidth,
child: Container(
width: 100,
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.all(Radius.circular(10)),
),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(10)),
// child: Image.asset(
// 'images/item-image1.jpeg',
// width: 180,
// fit: BoxFit.fill,
// ),
child: CachedNetworkImage(imageUrl: imageURL, fit: BoxFit.fill,)
),
),
),
],
),
//lower price widget
Visibility(
visible: isExtraInfoShowen,
child: Align(
alignment: Alignment.bottomLeft,
child: Container(
width: 100,
height: 20,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(10),
topLeft: Radius.circular(5)),
color: color),
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 3, horizontal: 4),
child: Align(
alignment: Alignment.bottomRight,
child: Text(
// '1000000 IQD',
item.priceIQD.toString() + ' IQD',
style: TextStyle(
fontSize: 12,
color: Colors.white,
),
textAlign: TextAlign.start,
),
),
),
),
),
)
],
),
),
),
);
}
}
SinglePlaceCard :
class SinglePlaceCard extends StatelessWidget {
SinglePlaceCard({this.place});
Place place;
#override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
double widgetWidth = screenWidth / 2.3;
int ratingUserCount = place.ratingUserCount;
String imageURL = place.coverImages != null
? imageBaseURLPlaces +
place.coverImages[0].imageURL
: '';
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SinglePlaceScreen(place: place, isScreenCalledFromOwnerSelfRegistrationScreen: false,),
),
);
},
child: FittedBox(
child: Padding(
padding: const EdgeInsets.only(right: 10),
child: Container(
child: Stack(
alignment: Alignment.bottomRight,
children: <Widget>[
Column(
//upper place name and rating
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
CircleRater(
isRatingDisabled: true,
rating: place.rating,
ratingUserCount: place.ratingUserCount != null ? ratingUserCount : 0,
),
SizedBox(
width: widgetWidth,
child: Text(
place.name,
overflow: TextOverflow.clip,
style: TextStyle(
fontSize: 12,
color: Colors.black,
fontWeight: FontWeight.w500),
softWrap: false,
),
),
//place card image
Container(
height: 80,
width: 170,
child: Container(
width: 150,
decoration: BoxDecoration(
color: kAppMainDarkGreenColor,
borderRadius: BorderRadius.all(Radius.circular(10)),
),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(10)),
child: place.coverImages == null
? Image.asset(
'images/blank-placeholder-images/blank-image-placeholder.png',
width: screenWidth / 4,
fit: BoxFit.fill,
)
: CachedNetworkImage(
imageUrl: imageURL,
fit: BoxFit.fill,
),
),
),
),
],
),
//lower tag
Align(
alignment: Alignment.bottomLeft,
child: Container(
width: 100,
height: 20,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(3),
bottomRight: Radius.circular(8)),
color: Colors.black54),
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 3, horizontal: 4),
child: Align(
alignment: Alignment.bottomRight,
child: FittedBox(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
EyeIconWithText(
size: 13,
),
Padding(
padding: const EdgeInsets.only(right: 5),
child: Container(
width: 10,
height: 10,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(8),
),
color: place.isOnline != null &&
place.isOnline == true
? Colors.green
: Colors.red),
),
),
Text(
place.isOpen != null
? place.isOpen ? 'Open Now' : 'Colosed Now'
: 'Closed Now',
style: TextStyle(
fontSize: 12,
color: Colors.white,
),
textAlign: TextAlign.start,
),
],
),
),
),
),
),
)
],
),
),
),
),
);
}
}
SinglePersonHotScreenCard :
class SinglePersonHotScreenCard extends StatelessWidget {
SinglePersonHotScreenCard(
{ this.isExtraInfoShowen = false, this.person});
final bool isExtraInfoShowen;
final Person person;
#override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
final ratingPersonCount = person.ratingUserCount;
return Padding(
padding: const EdgeInsets.only(bottom: 10),
child: GestureDetector(
onTap: () {
Navigator.pushNamed(context, SinglePersonScreen.id);
},
child: FittedBox(
child: Column(
children: <Widget>[
//upper label and rating
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
CircleRater(
isRatingDisabled: true,
rating: person.rating,
ratingUserCount: person.ratingUserCount != null ? ratingPersonCount : 0,
),
Text(
person.name,
style: TextStyle(color: Colors.black),
),
],
),
Stack(
alignment: Alignment.center,
children: <Widget>[
Container(
decoration: BoxDecoration(
color: Colors.black54,
borderRadius: BorderRadius.all(Radius.circular(1000)),
),
width: screenWidth / 3.6,
height: screenWidth / 3.6,
),
Visibility(
visible: person != null,
child: CircleAvatar(
radius: 50,
backgroundImage: NetworkImage(imageBaseURLPeople + person.profileImageURL,)
),
),
Visibility(
visible: person == null,
child: ClipOval(
child: SizedBox(
width: screenWidth / 4,
child:
Image.asset('images/blank-placeholder-images/person-placeholder.jpg'),
),
),
),
],
),
Text(
person.jobTitle,
style: TextStyle(color: Colors.black),
),
Padding(
padding: const EdgeInsets.only(top: 2.0),
child: Container(
width: 15,
height: 15,
decoration: kOnlineOfflineIndicatorBoxDecoration,
),
),
Padding(
padding: const EdgeInsets.all(4.0),
child: Visibility(
visible: this.isExtraInfoShowen,
child: ThumbsUpWithLabel(),
),
)
],
),
),
),
);
}
}
I have ran the devtool, the app uses too much m memory, I am not sure why.
I changed the code there is a lot less crashes. I use this code
getAllPlaces() async {
List<Place> places = widget.places;
places.removeRange(0, places.length);
List<Place> _places = [];
Response response = await getRequest(devBaseURL + plainPlaceAPI);
var allPlacesMap = jsonDecode(response.body);
for (int i = 0; i < allPlacesMap.length; i++) {
var json = allPlacesMap[i];
Place place = Place.fromJson(json);
_places.add(place);
}
setState(() {
places.addAll(_places );
print('all added');
});
}
The app crash seems to be caused by Out Of Memory issue. Checking on the snippets you've provided, memory issues were caused by nested ListViews rendering Widgets that displays images. While the widgets in ListViews are only rendered when near the viewport, multiple ListViews still adds up to the total memory consumed. I suggest trimming down the images displayed and nest ListViews sparingly to prevent these issues.

How to display data under padding in flutter?

Map item;
List data;
Future getdata() async{
http.Response response= await http.get(Uri.encodeFull("https://talaikis.com/api/quotes/"));
item=json.decode(response.body);
setState(() {
data=item["quotes"];
});
debugPrint(data.toString());
}
I want to display this request in stateful widget which is like this
#override
Widget build(BuildContext context) {
return new Scaffold(
drawer: drawerLeft(),
appBar: AppBar(
title: Text(
"IN TIME",
style: TextStyle(color: Colors.black, fontWeight: FontWeight.w700),
),
backgroundColor: clr,
elevation: 0.0,
leading: MaterialButton(
child: Icon(
Icons.view_headline,
color: Colors.black,
),
onPressed: () {
scaffoldKey.currentState.openDrawer();
},
)),
key: scaffoldKey,
body: AnimatedContainer(
padding: EdgeInsets.only(top: 50.0),
duration: Duration(milliseconds: 1000),
curve: Curves.ease,
color: clr,
child: PageView.builder(
itemCount: 7, //7days
onPageChanged: (int page) {
this.setState(() {
Random rnd;
rnd = new Random();
int r = 0 + rnd.nextInt(_colors.length - 0);
clr = _colors[r];
});
},
controller: pageViewController,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.only(left: 10.0),
child: Stack(
children: <Widget>[
Container(
decoration: new BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
color: Colors.white,
),
height:
MediaQuery.of(scaffoldKey.currentContext).size.height -
150.0,
width:
MediaQuery.of(scaffoldKey.currentContext).size.width -
20.0,
child: Stack(
children: <Widget>[
Positioned(
width: MediaQuery.of(scaffoldKey.currentContext)
.size
.width -
100.0,
left: index != currentPage
? getMappedValue(20.0, 100.0, 160.0, 20.0, pos)
: getMappedValue(20.0, 100.0, 20.0, -120.0, pos),
top: 20.0,
child: Opacity(
opacity: index != currentPage
? getMappedValue(20.0, 100.0, 0.0, 01.0, pos)
: getMappedValue(20.0, 100.0, 01.0, 00.0, pos),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
_days[index],
maxLines: 1,
softWrap: true,
style: TextStyle(
color: Colors.deepOrange,
fontSize: 22.0,
fontWeight: FontWeight.w600),
),
],
),
Padding(
padding: const EdgeInsets.only(top: 15.0),
child: Text(
'Quote for the day',
softWrap: true,
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w300),
),
),
],
),
),
),
],
),
),
],
),
);
},
),
),
);
}
}
*Please help me out *
If I understand, you want to display the quotes under some padding that are being retrieved to your List which I'll assume to be an inferenced List<String>. If so, you could just use a ListView within your widget tree to display every fetched item in that list, like so:
(...)
data != null
? Padding(
padding: const EdgeInsets.only(top: 15.0),
child: ListView.builder(
itemCount: data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(data[index]),
);
},
),
)
: Container(),
(...)

Flutter - widget testing for the Cupertino picker in flutter/Dart

i am testing the Cupertino picker,for which i am writing widget testing and i am struggling to implement how the onselectItemChanged in testing and accordingly the values chosen by the wheeling of the cupertino picker. The testing has to be done so that the value when user chooses accordingly the test case has to written in such a way that it suits to different values chosen
List<String> ages1 = ["-- select --"];
List<String> ages2 = List<String>.generate(
45, (int index) => (21 + index).toString(),
growable: false);
List<String> ages = [ages1, ages2].expand((f) => f).toList();
picker.dart:
Widget _buildAgePicker(BuildContext context) {
final FixedExtentScrollController scrollController =
FixedExtentScrollController(initialItem: _selectedAgeIndex);
return GestureDetector(
key: Key("Age Picker"),
onTap: () async {
await showCupertinoModalPopup<void>(
context: context,
builder: (BuildContext context) {
return _buildBottomPicker(
CupertinoPicker(
key: Key("Age picker"),
scrollController: scrollController,
itemExtent: dropDownPickerItemHeight,
backgroundColor: Theme.of(context).canvasColor,
onSelectedItemChanged: (int index) {
setState(() {
_selectedAgeIndex = index;
ageValue = ages[index];
if (ageValue == S.of(context).pickerDefaultValue) {
ageDividerColor = Theme.of(context).errorColor;
errorText = S.of(context).pickerErrorMessage;
ageDividerWidth = 1.2;
} else {
ageDividerColor = Colors.black87;
errorText = "";
ageDividerWidth = 0.4;
}
});
},
children: List<Widget>.generate(ages.length, (int index) {
return Center(
child: Text(ages[index]),
);
}),
),
);
},
);
},
child: _buildMenu(
<Widget>[
Text(
S.of(context).Age,
style: TextStyle(fontSize: 17.0),
),
Text(
ages[_selectedAgeIndex],
),
],
),
);
}
Widget _buildMenu(List<Widget> children) {
return Container(
decoration: BoxDecoration(
color: Theme.of(context).canvasColor,
),
height: 44.0,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: SafeArea(
top: false,
bottom: false,
child: DefaultTextStyle(
style: const TextStyle(
color: Colors.black,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: children,
),
),
),
),
);
}
Widget _buildBottomPicker(Widget picker) {
return Container(
height: dropDownPickerSheetHeight,
padding: const EdgeInsets.only(top: 6.0),
color: Theme.of(context).canvasColor,
child: DefaultTextStyle(
style: const TextStyle(
color: Colors.black,
fontSize: 22.0,
),
child: GestureDetector(
key: Key("picker"),
onTap: () {},
child: SafeArea(
top: false,
child: picker,
),
),
),
);
}
widget_test.dart:
testWidgets("picker test",(WidgetTester tester)async{
await tester.tap(find.byKey(Key("Age Picker")));
await tester.drag(find.byKey(Key("Age Picker")), Offset(0.0,70.0));
await tester.pumpAndSettle();
expect(ages[1], "21");
});

Resources