How to put space in a text loop - flutter

I want to give some width or space in "Your Likes" section between the users. How can I put some space, please give some suggestion and example.
children: [
UserImageSmall(
height: 64,
width: 64,
url: inactiveMatches[index].matchedUser.imageUrls),
Text(
inactiveMatches[index].matchedUser.name,
style: Theme.of(context).textTheme.bodyText1,
),
],
How can I remove the error showed in the "Your Chats" section here I want some help. Please let me know how can I do it. Please check the code and image below.
Text('Your Chats',
style: Theme.of(context).textTheme.headline5),
ListView.builder(
shrinkWrap: true,
itemCount: activeMatches.length,
itemBuilder: (context, index) {
return InkWell (
onTap: () {
Navigator.push(
context, MaterialPageRoute(
builder: (context) => ChatScreen(userMatch: userMatch,),
),
);
},
child: Row(children: [
UserImageSmall(
height: 60,
width: 60,
url: activeMatches[index].matchedUser.imageUrls,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
activeMatches[index].matchedUser.name,
style: Theme.of(context).textTheme.headline6,
),
SizedBox(height: 10),
Text(
activeMatches[index].chat![0].messages[0].message,
style: Theme.of(context).textTheme.bodyText1,
),
],
),
],
),
);
}
)
This is the exact emulator screen running with this given code.

In Your Likes section, give width to UserImageSmall Widget such as:
Container( width: 16, child: UserImageSmall())
Check index 0 exists or not, as in the image seems like null on index: 0
activeMatches[index].chat![0].messages[0].message
I have modified the code, hope this helps!
Text('Your Chats',
style: Theme.of(context).textTheme.headline5),
ListView.builder(
shrinkWrap: true,
itemCount: activeMatches.length,
itemBuilder: (context, index) {
return InkWell (
onTap: () {
Navigator.push(
context, MaterialPageRoute(
builder: (context) => ChatScreen(userMatch: userMatch,),
),
);
},
child: Row(children: [
UserImageSmall(
height: 60,
width: 60,
url: activeMatches[index].matchedUser.imageUrls,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
activeMatches[index].matchedUser.name,
style: Theme.of(context).textTheme.headline6,
),
SizedBox(height: 10),
Text(
activeMatches[index].chat![0]==null ? ""
: activeMatches[index].chat![0].messages[0].message,
style: Theme.of(context).textTheme.bodyText1,
),
],
),
],
),
);
}
)

Related

I can't see the error, but it says "Null check operator used on a null value"

when I go to this page I see this error (Null check operator used on a null value) instead of the content.
I have read questions that had the same error and in the answers they talked about one ! too many, but I could not figure out where the problem is in my code, perhaps the error refers to something else?
Can you help me find it please?
class PastTasksView extends GetView<HomeController> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: Get.height,
width: Get.width,
color: Theme.of(context).scaffoldBackgroundColor,
//padding: EdgeInsets.symmetric(horizontal: 30, vertical: 50),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(top: 50, left: 25, right: 25),
child: Text(
'Attività svolte',
style: kSubHeadTextStyle.copyWith(
color: Theme.of(context).primaryColorDark),
),
),
SizedBox(height: Get.height * 0.012),
GetBuilder<HomeController>(
id: 1,
builder: (controller) {
return Expanded(
child: ListView.builder(
itemBuilder: (context, index) {
final task = controller.pastTasks[index]!;
return Slidable(
// actionPane: SlidableBehindActionPane(),
// actionExtentRatio: 0.2,
// controller: controller.slideC,
child: ExpandedContainer(
icon: task.taskImage,
title: task.tasktitle,
time: task.startTime,
desc: task.taskDesc,
ifDate: true,
date: DateFormat.yMMMd().format(task.taskDate!),
),
startActionPane: ActionPane(
motion: BehindMotion(),
children: [
SlidableAction(
onPressed: (context) {
// controller.slideC.activeState?.close();
Slidable.of(context)?.close();
controller.preUpdateTask(task);
showModalBottomSheet(
backgroundColor: Colors.transparent,
isScrollControlled: true,
context: context,
builder: (context) {
return BottomSheetContent(
buttonText: 'Update Task',
onSubmit: () {
controller.updateTask(task);
},
);
},
) as IconData;
},
label: "Update",
),
],
),
endActionPane: ActionPane(
motion: BehindMotion(),
children: [
SlidableAction(
onPressed: (context) {
// controller.slideC.activeState?.close();
Slidable.of(context)?.close();
controller.deleteTask(task);
},
label: "Delete",
),
],
),
);
},
itemCount: controller.pastTasks.length,
),
);
},
),
],
),
),
);
}
}
Replying to comments:
1-Ok I pasted it here https://pastecode.io/s/92fo20qh
2- In logcat there is only this
======== Exception caught by widgets library =======================================================
The following _CastError was thrown building GetBuilder(dirty, state: GetBuilderState#d36d0):
Null check operator used on a null value
3- to check the presence of contents

Flutter: Make all screen scrollable with GridView.builder inside

In my home screen my app shows carousel first then a vertical list of challenges cards retrieved from Cloud Firestore using GridView.builder as follows:
GridView.builder(
scrollDirection: Axis.vertical,
itemCount: _challenges.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 1,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 4),
),
itemBuilder: (context, index) {
return InkWell(
onTap: () {
if (_challenges[index]["isLocked"] == "true") {
showLockedDialog();
} else {
checkParticipation(index);
if (checkPart == true) {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) =>
ChallengeDetails(_challenges[index])));
}
checkPart = true;
}
},
child: Stack(
children: [
Center(
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Image(
image: NetworkImage(_challenges[index]["image-path"]),
fit: BoxFit.cover,
height: 150,
width: 350,
opacity: _challenges[index]["isLocked"] == "true"
? AlwaysStoppedAnimation(.4)
: null,
),
),
),
Center(
child: Text(
"${_challenges[index]["name"]}\n",
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
),
),
Center(
child: Text(
"\n${_challenges[index]["date"]}",
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
textDirection: TextDirection.ltr,
)),
Center(
child: SizedBox(
height: 130,
width: 130,
child: _challenges[index]["isLocked"] == "true"
? Image.asset("assets/lock-icon.jpg")
: null,
),
)
],
),
);
});
Everything retrieving fine and it is rendered in my home_screen as follows:
body: Column(
children: [
AdsBanner(),
SizedBox(
height: 30,
),
Padding(
padding: const EdgeInsets.only(right: 8, left: 8, bottom: 5),
child: Row(
children: [
Text(
AppLocalizations.of(context)!.challenges + " ",
style: TextStyle(fontSize: 20),
),
Text(
AppLocalizations.of(context)!.clickToParticipate,
style: TextStyle(fontSize: 15),
)
],
),
),
Expanded(child: ChallengeCard()),
],
),
The problem is that only the GridView area is scrolling and what am seeking for is to scroll the whole screen with the GridView area, I was trying to use the CustomScrollView() but its not working properly.
I'll be thankful for any help.
First in your GridView.builder add these:
GridView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
...
)
then in your home_screen wrap your column with SingleChildScrollView:
SingleChildScrollView(
child: Column(
children: [
AdsBanner(),
SizedBox(
height: 30,
),
Padding(
...
),
),
You can provide physics: NeverScrollableScrollPhysics() on GridView to disable scroll effect. If you want scrollable as secondary widget use primary: false, to have Full Page scrollable, you can use body:SingleChildScrollView(..) or better using body:CustomScrollView(..)

ListView with Expanded when not scrollable

I want to make a menu with list of ExpansionTile and a footer, when the ExpansionTile is not expanded (not scrollable) the footer stay on the bottom of screen, but when the ExpansionTile is expanded (scrollable) the children of ExpansionTile push the footer out of screen.
For a clearer illustration, please see the following image
this my current code, but it's not a best way I think
checking is scrollable or not
checkIsScrollable(BuildContext context) {
if (Scrollable.of(context).position.minScrollExtent >=
Scrollable.of(context).position.maxScrollExtent) {
setState(() {
scrollable = false;
});
} else {
setState(() {
scrollable = true;
});
}
this the listview
ListView(
padding: EdgeInsets.symmetric(horizontal: 16),
children: [
LimitedBox(
maxHeight: !scrollable
? MediaQuery.of(context).size.height - 84
: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 24,
),
Text(
"Account".toUpperCase(),
style: ThemeApp.appBarTextStyle(),
),
SizedBox(
height: 24,
),
photoProfile(),
SizedBox(
height: 40,
),
menuProfile(),
SizedBox(
height: 40,
),
AccountContent.customerCare1(
context: context,
onExpansionChanged: (_) {
Future.delayed(
Duration(milliseconds: 101),
() {
checkIsScrollable(context);
},
);
},
),
AccountContent.sellWithUs(
context: context,
onExpansionChanged: (_) {
Future.delayed(
Duration(milliseconds: 101),
() {
checkIsScrollable(context);
},
);
},
),
AccountContent.customerCare2(
context: context,
onExpansionChanged: (_) {
Future.delayed(
Duration(milliseconds: 101),
() {
checkIsScrollable(context);
},
);
},
),
!scrollable
? Expanded(
child: Container(),
)
: Container(),
Container(
padding: EdgeInsets.symmetric(vertical: 16),
child: Column(
children: [
InkWell(
child: Row(
children: [
Container(
height: 18,
width: 18,
color: ThemeApp.borderColor,
),
SizedBox(width: 10),
Text(
"LOGOUT",
style: ThemeApp.subTitleTextStyle(),
),
],
),
onTap: () {},
),
SizedBox(
height: 20,
),
Row(
children: [
Expanded(
child: BorderedButton(
child: SvgPicture.asset(
"assets/icons/icon_whatsapp.svg",
color: ThemeApp.primaryColor,
),
onTap: () {
openWhatsapp();
},
),
),
SizedBox(
width: 17,
),
Expanded(
child: BorderedButton(
child: SvgPicture.asset(
"assets/icons/icon_instagram.svg",
color: ThemeApp.primaryColor,
),
onTap: () {
openInstagram();
},
),
),
SizedBox(
width: 17,
),
Expanded(
child: BorderedButton(
child: SvgPicture.asset(
"assets/icons/icon_mail.svg",
color: ThemeApp.primaryColor,
),
onTap: () {
openMail();
},
),
),
],
),
],
),
)
],
),
),
],
);
You should use a Column inside of LayoutBuilder and with a ConstrainedBox, set The minHeight of the Column to maxHeight of LayoutBuilder:
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
YourListView(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
),
YourFooter(),
],
),
),
);
},
);
}
I didn't get your question correctly but i guess you need too use Stack widget which always stays your footer on it's place even your page is Scrollable.
The footer you don't want to scroll, make the Column having two children and inside the column add another column and put the scrollable data inside that and wrap that with the SingleChildScrolView.
Column(
children: [
SingleChildScrollView(
child: Column(
children: [
// your scrollable data here
],
Column(
children: [
// Footer not scrollable
],),
],

Flutter: How to get a value to use for reference

I'm just new to android programming. and now I have a problem in flutter / dart. So, I have a list of cards that has data showing in it, and that data is coming from the firestore database, and in the card there's also a button named "view". So I want to do is, If I click the "view" button it will show a dialog with the details of the card that I clicked. Im having a problem in getting the details and show it in a dialog. Please help :(
Here is my UI:
My UI
Here is my code when retrieving the data Im using a stream builder:
StreamBuilder<QuerySnapshot>(
stream: db.collection('HELP REQUEST').snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
children: snapshot.data.documents
.map((doc) => buildItem(doc))
.toList());
} else {
return SizedBox();
}
})
and Here I put the data in a card and output it:
return Card(
elevation: 5,
child: Padding(
padding: const EdgeInsets.all(8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Name of Requestor: ${doc.data['Name_ofUser']}',
style: TextStyle(fontSize: 20),
),
Text(
'Help description: ${doc.data['Help_Description']}',
style: TextStyle(fontSize: 20),
),
Text(
'Type of help needed: ${doc.data['Help_TypeNeeded']}',
style: TextStyle(fontSize: 20),
),
Text(
'Help location: ${doc.data['Help_Location']}',
style: TextStyle(fontSize: 20),
),
SizedBox(
height: 12,
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FlatButton(
onPressed: () {},
child: Text('View'),
)
],
),
],
),
),
);
Please help :(
Let's say you have a list of Card called list
you can use #mertcan answer to display a dialog like this.
return Card(
elevation: 5,
child: Padding(
padding: const EdgeInsets.all(8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Name of Requestor: ${doc.data['Name_ofUser']}',
style: TextStyle(fontSize: 20),
),
Text(
'Help description: ${doc.data['Help_Description']}',
style: TextStyle(fontSize: 20),
),
Text(
'Type of help needed: ${Text('Help description: $help')}',
style: TextStyle(fontSize: 20),
),
Text(
'Help location: ${doc.data['Help_Location']}',
style: TextStyle(fontSize: 20),
),
SizedBox(
height: 12,
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FlatButton(
onPressed: () {
//Note change here
_showMydialog(doc.data)
},
child: Text('View'),
)
],
),
],
),
),
)
void _showMydialog(dynamic data){
showDialog<void>(
context: context,
builder: (context) {
return SimpleDialog(
children: [
Text(Name of Requestor: ${data['Name_ofUser']),
Text('Help description: ${doc.data['Help_Description'])
],
);
},
);
}
There is a built-in function in flutter called showDialog and various dialog widgets that you can use according to your need(https://api.flutter.dev/flutter/material/Dialog-class.html). So it needs to look something like this
showDialog<void>(
context: context,
builder: (context) {
return SimpleDialog(
children: [
Text('Name of requester: $name'),
Text('Help description: $help')
],
);
},
);
Your View button click should call this function.

Flutter dynamic height of ListView

I am developing a Flutter application and I want to dynamically adjust the height of the ListView.
I want the list to have a maximum height of 200. If the height is more than that, user will have to scroll to reach the bottom. If height is below 200, it will take only as much space as needed.
Preview of application: Screenshot. As you can see Restaurants nearby is pushed to the very bottom of the page. I want the ListView to only take height of 200 or less so that the content below isn't pushed to the bottom.
Here is my current code:
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Restaurants nearby',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text('Enter restaurant manually'),
onPressed: () {
print('Button pressed');
},
),
],
),
Flexible(
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: CircleAvatar(
backgroundColor: Colors.cyan,
),
title: Text('Test restaurant'),
subtitle: Text('80m'),
);
},
itemCount: 15,
),
),
Text(
'Restaurants nearby',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
],
),
);
}
You are using Flexible widget, that's why your ListView expands. You have to change Flexible to ConstrainedBox and add shrinkWrap: true to your ListView.
ConstrainedBox(
constraints: BoxConstraints(maxHeight: 200, minHeight: 56.0),
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: CircleAvatar(
backgroundColor: Colors.cyan,
),
title: Text('Test restaurant'),
subtitle: Text('80m'),
);
},
itemCount: 15,
),
),
More info here: https://api.flutter.dev/flutter/widgets/ConstrainedBox-class.html
You can use LimitedBox
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(...),
Divider(),
Row(...),
LimitedBox(
maxHeight: 200.0,
child: ListView.builder(...),
),
Text(...),
],
),
Recommended solution in case when the incoming constraints are unbounded
Consider wrapping the ListView into this
LimitedBox(
maxHeight: 200,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: CircleAvatar(
backgroundColor: Colors.cyan,
),
title: Text('Test restaurant'),
subtitle: Text('80m'),
);
},
itemCount: _itemsCount,
),
),
]
)
),
Note that:
shrinkWrap of ListView is set to true
mainAxisSize of Column is set to MainAxisSize.min
maxHeight of LimitedBox is set to 200
A complete snippet:
import 'package:flutter/material.dart';
class DebugWidget extends StatefulWidget {
#override
_DebugWidgetState createState() => _DebugWidgetState();
}
class _DebugWidgetState extends State<DebugWidget> {
int _itemsCount = 1;
#override
Widget build(BuildContext context) {
Widget child = Container(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Restaurants nearby',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text('Enter restaurant manually'),
onPressed: () {
print('Button pressed');
},
),
RaisedButton(
child: Text('+1'),
onPressed: () {
setState(() {
_itemsCount += 1;
});
},
),
RaisedButton(
child: Text('-1'),
onPressed: () {
setState(() {
_itemsCount -= 1;
});
},
),
],
),
LimitedBox(
maxHeight: 200,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: CircleAvatar(
backgroundColor: Colors.cyan,
),
title: Text('Test restaurant'),
subtitle: Text('80m'),
);
},
itemCount: _itemsCount,
),
),
]
)
),
Text(
'Restaurants nearby',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
],
),
);
return Scaffold(
body: child,
);
}
}
I found a solution to this problem. you should wrap your ListView with LimittedBox or ConstraintBox and give them maxHeight and set shrinkWrap property of ListView to true. the solution would be something like this.
LimitedBox(
maxHeight: 200,
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: CircleAvatar(
backgroundColor: Colors.cyan,
),
title: Text('Test restaurant'),
subtitle: Text('80m'),
);
},
itemCount: 15,
),
),
I see that this question has never been answered only with giving a fixed height, so here is what works for me.
For some reason if you set the shrinkwrap to true it doesn't look like it is working but it does, the problem is in the padding settings of the ListView, set the padding to edgeinstets.zero. That fixes it for me.
Wrap inside a Flexible
ShrinkWrap true
Padding, zero
and if needed the column to MainAxisSize.min.
Hope it helps some people.
Example of my code:
Flexible(
child: Container(
decoration: BStyles.cardDecoration1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const Text(
'PRODUCTION TASKS',
),
const SizedBox(
height: textVerticalSpacing,
),
Flexible(
child: ListView.builder(
itemCount: recentTasks.length,
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return TaskCard(
task: recentTasks[index],
widthInfo: MediaQuery.of(context).size.width * 0.6,
);
},
),
),
const SizedBox(
height: itemSpacing,
),
Align(
alignment: Alignment.centerRight,
child: InkWell(
onTap: () { },
child: const Text(
'View more',
),
),
),
const SizedBox(
height: textVerticalSpacing,
),
],
),
),
),
),
ConstrainedBox(
constraints: BoxConstraints(maxHeight: 200.0),
child: [your child here],
)
This make your child's height not bigger than 200.0
You can always size the ListView container as % of the viewport (assuming of course that the other widgets also are sized in the same manner):
return Container(
height: MediaQuery.of(context).size.height * 0.75,
child: ListView.builder(
itemBuilder: (ctx, index) {
return Card(...