Flutter Expandable leaves empty area after being collapsed - flutter

I have a long text in a CustomScrollView that I have wrapped in an Expandable widget.
When the text is collapsed I show the first 7 rows, and when it's expanded I show the entire text which can be long.
After I expand the text and then collapse it again I get a long area of nothing under the collapsed view.
Here is a screenshot of the expanded and collapsed text:
as you can see the Feature text widget is no longer directly beneath the text widget.
Here is the widget:
import 'package:expandable/expandable.dart';
import 'package:flutter/material.dart';
import 'package:My_ui/My_ui.dart';
import 'package:listing_detail_page/generated/l10n.dart';
import 'package:listing_detail_page/network/models/listing_detail.dart';
import '../../../generic_components/bottom_fade.dart';
class DescriptionView extends StatelessWidget {
const DescriptionView({
Key? key,
required this.details,
required this.expandableController,
}) : super(key: key);
final ListingDetails details;
final ExpandableController expandableController;
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(
left: Spacing.x2,
right: Spacing.x2,
top: Spacing.x3,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
S.of(context).descriptionView_title_description,
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
fontWeight: FontWeight.w600,
color: MyColors.grey25,
),
),
const SizedBox(height: Spacing.x1),
ExpandableNotifier(
controller: expandableController,
child: ScrollOnExpand(
child: Expandable(
collapsed: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
BottomFade(
height: 80,
child: Text(
details.description ?? '',
maxLines: 7,
overflow: TextOverflow.fade,
style: Theme.of(context)
.textTheme
.bodyLarge
?.copyWith(height: 1.5),
),
),
const SizedBox(height: Spacing.x1),
ExpandableButton(
child: Row(
children: [
const Icon(
Icons.add,
color: MyColors.blue,
size: 22,
),
const SizedBox(width: Spacing.x1),
Text(
S
.of(context)
.descriptionView_button_readTheFullDescription,
textAlign: TextAlign.start,
style:
Theme.of(context).textTheme.bodyLarge?.copyWith(
color: MyColors.blue,
height: 1.5,
),
),
],
),
),
],
),
expanded: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
details.description ?? '',
style: Theme.of(context)
.textTheme
.bodyLarge
?.copyWith(height: 1.5),
),
const SizedBox(height: Spacing.x1),
ExpandableButton(
child: Row(
children: [
const Icon(
Icons.remove,
color: MyColors.blue,
size: 22,
),
const SizedBox(width: Spacing.x1),
Text(
S.of(context).descriptionView_button_showLess,
textAlign: TextAlign.start,
style:
Theme.of(context).textTheme.bodyLarge?.copyWith(
color: MyColors.blue,
height: 1.5,
),
),
],
),
),
],
),
),
),
),
],
),
);
}
}
And here is how it is being used:
import 'package:expandable/expandable.dart';
import 'package:flutter/material.dart';
import 'package:My_ui/My_ui.dart';
import 'package:listing_detail_page/network/models/feature_section.dart';
import 'package:listing_detail_page/network/models/listing_detail.dart';
import 'package:listing_detail_page/ui/generic_components/My_sliver_app_bar.dart';
import 'package:listing_detail_page/ui/screens/listing_detail/components/address_section.dart';
import 'package:listing_detail_page/ui/screens/listing_detail/components/description_view.dart';
import 'package:listing_detail_page/ui/screens/listing_detail/components/price_tile.dart';
class ListingDetailBody extends StatefulWidget {
const ListingDetailBody({
Key? key,
required this.details,
required this.listingId,
required this.sections,
}) : super(key: key);
final ListingDetails details;
final String listingId;
final List<FeatureSection> sections;
#override
State<ListingDetailBody> createState() => _ListingDetailBodyState();
}
class _ListingDetailBodyState extends State<ListingDetailBody> {
final ExpandableController _descriptionExpandableController =
ExpandableController();
#override
void dispose() {
_descriptionExpandableController.dispose();
super.dispose();
}
Widget? _buildDescriptionView(BuildContext context) {
final description = widget.details.description;
if (description != null && description.isNotEmpty) {
return DescriptionView(
details: widget.details,
expandableController: _descriptionExpandableController,
);
}
return null;
}
#override
Widget build(BuildContext context) {
return CustomScrollView(
physics: const BouncingScrollPhysics(),
slivers: [
MySliverAppBar(
details: widget.details,
listingId: widget.listingId,
),
SliverList(
delegate: SliverChildListDelegate(
[
...
const SizedBox(height: Spacing.x3),
AddressSection(details: widget.details),
PriceTile(details: widget.details),
_buildDescriptionView(context),
...
].whereType<Widget>().toList(),
),
),
],
);
}
}

Related

Can someone tell me why I'm getting these errors and how do I resolve them?

class IconContent extends StatelessWidget {
const IconContent({Key? key, required this.icon, required this.label})
: super(key: key);
final IconData icon;
final String label;
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Icon(
icon,
size: 80.0,
),
SizedBox(
height: 15.0,
),
Text(
label,
style: TextStyle(
fontSize: 18.0,
color: Color(
0xFF8D8E98,
),
),
),
],
);
}
}
Im getting the error stated below multiple times. Can someone help me resolve them.
Arguments of a constant creation must be constant expressions.\nTry making the argument a valid constant, or use 'new' to call the constructor.
This is the code Im getting the errors on. Removing const didnt do anything :(
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
const Color midNightLight = Color(0xFF1D1E33);
class InputPage extends StatefulWidget {
const InputPage({super.key});
#override
State<InputPage> createState() => _InputPageState();
}
class _InputPageState extends State<InputPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Center(
child: Text('BMI Calculator'),
),
),
body: SafeArea(
child: Column(
children: [
Expanded(
child: Row(
// ignore: prefer_const_literals_to_create_immutables
children: [
// ignore: prefer_const_constructors
Expanded(
flex: 2,
// ignore: prefer_const_constructors
child: ReusableCard(
colour: midNightLight,
// ignore: prefer_const_constructors
cardChild: IconContent(
icon: FontAwesomeIcons.mars,
label: 'MALE',
),
),
),
// ignore: prefer_const_constructors
Expanded(
flex: 2,
// ignore: prefer_const_constructors
child: ReusableCard(
colour: midNightLight,
// ignore: prefer_const_constructors
cardChild: new IconContent(
icon: FontAwesomeIcons.venus,
label: 'FEMALE',
),
),
)
],
),
),
Expanded(
child: Row(
// ignore: prefer_const_literals_to_create_immutables
children: [
// ignore: prefer_const_constructors
Expanded(
flex: 2,
// ignore: prefer_const_constructors
child: ReusableCard(
colour: midNightLight,
),
),
],
),
),
Expanded(
child: Row(
// ignore: prefer_const_literals_to_create_immutables
children: [
// ignore: prefer_const_constructors
Expanded(
flex: 2,
// ignore: prefer_const_constructors
child: ReusableCard(
colour: midNightLight,
),
),
// ignore: prefer_const_constructors
Expanded(
flex: 2,
// ignore: prefer_const_constructors
child: ReusableCard(
colour: midNightLight,
),
)
],
),
),
],
),
),
);
}
}
class IconContent extends StatelessWidget {
const IconContent({Key? key, required this.icon, required this.label})
: super(key: key);
final IconData icon;
final String label;
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Icon(
icon,
size: 80.0,
),
SizedBox(
height: 15.0,
),
Text(
label,
style: TextStyle(
fontSize: 18.0,
color: Color(
0xFF8D8E98,
),
),
),
],
);
}
}
class ReusableCard extends StatelessWidget {
const ReusableCard({
Key? key,
required this.colour,
this.cardChild,
}) : super(key: key);
final Color? colour;
final Widget? cardChild;
#override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.all(15.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: colour,
),
child: cardChild,
);
}
}
label will get on runtime, therefore it cant be const
class IconContent extends StatelessWidget {
const IconContent({
Key? key,
required this.icon,
required this.label,
}) : super(key: key);
final IconData icon;
final String label;
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//remove const from here
Icon(
icon,
size: 80.0,
),
SizedBox(
height: 15.0,
),
Text(
label,
style: TextStyle(
fontSize: 18.0,
color: Color(
0xFF8D8E98,
),
),
),
],
);
}
}
Just remove the const from Column's children list. your lable and icon variable is not const and its value changes in different state because of that you can't use const for Column's children list. You also need to delete all those const from Row's children inside Expanded too.

how to show multiple comment_tree: ^0.3.0 in flutter , I want to show multiple comment in comment page Pleas help me

'here is comment widget i want to show this multiple comment widget in comment page and i also trying to lot of trying to put this comment widget in listview when i put this widget in listview my screeen is not rendered. but when i put this in gridview it is showing all comment properly plese help me'
import 'package:comment_tree/comment_tree.dart';
import 'package:comment_tree/widgets/comment_tree_widget.dart';
import 'package:ecllipsenew/data/repository/post_repo.dart';
import 'package:ecllipsenew/provider/PostProvider.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:provider/provider.dart';
import '../../../../util/app_constants.dart';
class Comments extends StatefulWidget {
final List<Comment> commentList;
Comments({this.commentList});
#override
State<Comments> createState() => _CommentsState();
}
class _CommentsState extends State<Comments> {
bool reply = false;
final List<Comment> commentLi = [
Comment(
avatar: 'nukkll',
userName: 'njjull',
content: 'I mkk interested',
),
Comment(
avatar: 'null',
userName: 'null',
content: 'I mjjj interested',
),
];
#override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(
child: Container(
child: CommentTreeWidget<Comment, Comment>(
commentLi[0],
[
commentLi[0],
commentLi[1],
],
treeThemeData:
TreeThemeData(lineColor: Colors.blue, lineWidth: 3),
avatarRoot: (context, data) => const PreferredSize(
child: CircleAvatar(
radius: 18,
backgroundColor: Colors.grey,
backgroundImage: NetworkImage(AppConstants.User_Url)),
preferredSize: Size.fromRadius(18),
),
avatarChild: (context, data) => const PreferredSize(
child: CircleAvatar(
radius: 12,
backgroundColor: Colors.grey,
backgroundImage: NetworkImage(AppConstants.User_Url)),
preferredSize: Size.fromRadius(12),
),
contentChild: (context, data) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(12)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'${data.userName}',
style: Theme.of(context)
.textTheme
.caption
?.copyWith(
fontWeight: FontWeight.w600,
color: Colors.black),
),
SizedBox(
height: 4,
),
Text(
'${data.content}',
style: Theme.of(context)
.textTheme
.caption
?.copyWith(
fontWeight: FontWeight.w300,
color: Colors.black),
),
],
),
),
DefaultTextStyle(
style: Theme.of(context).textTheme.caption.copyWith(
color: Colors.grey[700], fontWeight: FontWeight.bold),
child: Padding(
padding: EdgeInsets.only(top: 4),
child: Row(
children: [
SizedBox(
width: 8,
),
Text('5d'),
SizedBox(
width: 8,
),
Text('Like'),
SizedBox(
width: 24,
),
Text('Reply'),
],
),
),
)
],
);
},
contentRoot: (context, data) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(12)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Tina Chuhan',
style: Theme.of(context).textTheme.caption.copyWith(
fontWeight: FontWeight.w600,
color: Colors.black),
),
SizedBox(
height: 4,
),
Text(
'${data.content}',
style: Theme.of(context).textTheme.caption.copyWith(
fontWeight: FontWeight.w300,
color: Colors.black),
),
],
),
),
DefaultTextStyle(
style: Theme.of(context).textTheme.caption.copyWith(
color: Colors.grey[700], fontWeight: FontWeight.bold),
child: Padding(
padding: EdgeInsets.only(top: 4),
child: Row(
children: const [
SizedBox(
width: 8,
),
Text('5d'),
SizedBox(
width: 8,
),
Text('Like'),
SizedBox(
width: 24,
),
Text('Reply'),
],
),
),
)
],
);
},
),
padding: EdgeInsets.symmetric(vertical: 12, horizontal: 16),
),
),
],
);
// }
// );
// });
}
}
and here is my comment show page
import 'package:comment_tree/comment_tree.dart';
import 'package:ecllipsenew/screen/home/pages/comment/Comments.dart';
import 'package:ecllipsenew/screen/home/pages/comment/new_message.dart';
import 'package:ecllipsenew/util/app_constants.dart';
import 'package:flutter/material.dart';
class CommentPage extends StatefulWidget {
static const routeName = '/Comment_Page';
const CommentPage({Key key}) : super(key: key);
#override
State<CommentPage> createState() => _CommentPageState();
}
class _CommentPageState extends State<CommentPage> {
// final List<Comments> commentList = [
// Comments(
// commentId: "3",
// commentUserId: "11",
// commentUserName: "Himanshu",
// commentUserProfileImage: AppConstants.User_Url,
// commentType: "text",
// commentFile: "jjjj",
// commentDate: "12/12/12",
// commentTime: "12:30",
// commentReacts: "hhh",
// letestReplys: "jjjj")
// ];
final List<Comment> commentLi = [
Comment(
avatar: 'null',
userName: 'null',
content: 'I m interested',
),
Comment(
avatar: 'null',
userName: 'null',
content: 'I m interested',
),
];
#override
Widget build(BuildContext context) {
return
// Scaffold(
// appBar: AppBar(
// title: Text("Comment"),
// ),
// body:
SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
//when I add this line my screen is not rendered
for (int i = 0; i < 3; i++) Comments(commentList: commentLi),
Expanded(
child: Comments(commentList: commentLi),
),
NewMessage()
],
),
),
);
// );
}
}
The main cause of render error is using Expanded widget inside Column, without having a fixed height for that Column.
If you want to use Expanded widget inside Column, you should wrap the column with a sizedbox and give it a fixed height as shown below:
SizedBox(
height: MediaQuery.of(context).size.height * 0.8,
child: Column(
children: [
Text('Header'),
Expanded(
child: Container(
child: Center(
child: Text('I take the remaining space'),
),
),
)
],
)
I could render the same code by removing the Expanded widgets wherever you have used them. They seem unnecessary too.
Screenshot of commentPage by removing Expanded widget everywhere
Please find full code as you have asked for in previous answer. Still, I recommend you to know the basic of flutter-layout to understand working with Expanded widget before using this code.
import 'package:flutter/material.dart';
import 'package:test/view.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const CommentPage());
}
}
Comments page code
import 'package:comment_tree/comment_tree.dart';
import 'package:flutter/material.dart';
import 'package:test/test.dart';
class CommentPage extends StatefulWidget {
static const routeName = '/Comment_Page';
const CommentPage({Key? key}) : super(key: key);
#override
State<CommentPage> createState() => _CommentPageState();
}
class _CommentPageState extends State<CommentPage> {
// final List<Comments> commentList = [
// Comments(
// commentId: "3",
// commentUserId: "11",
// commentUserName: "Himanshu",
// commentUserProfileImage: AppConstants.User_Url,
// commentType: "text",
// commentFile: "jjjj",
// commentDate: "12/12/12",
// commentTime: "12:30",
// commentReacts: "hhh",
// letestReplys: "jjjj")
// ];
final List<Comment> commentLi = [
Comment(
avatar: 'null',
userName: 'null',
content: 'I m interested',
),
Comment(
avatar: 'null',
userName: 'null',
content: 'I m interested',
),
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Comment"),
),
body: SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
for (int i = 0; i < 3; i++) Comments(commentList: commentLi),
// Comments(commentList: commentLi),
// NewMessage()
],
),
),
),
);
// );
}
}
Comments tree page
import 'package:comment_tree/comment_tree.dart';
import 'package:flutter/material.dart';
class Comments extends StatefulWidget {
final List<Comment> commentList;
const Comments({Key? key, required this.commentList}) : super(key: key);
#override
State<Comments> createState() => _CommentsState();
}
class _CommentsState extends State<Comments> {
bool reply = false;
final List<Comment> commentLi = [
Comment(
avatar: 'nukkll',
userName: 'njjull',
content: 'I mkk interested',
),
Comment(
avatar: 'null',
userName: 'null',
content: 'I mjjj interested',
),
];
#override
Widget build(BuildContext context) {
return Column(
children: [
Container(
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
child: CommentTreeWidget<Comment, Comment>(
commentLi[0],
[
commentLi[0],
commentLi[1],
],
treeThemeData:
const TreeThemeData(lineColor: Colors.blue, lineWidth: 3),
avatarRoot: (context, data) => const PreferredSize(
preferredSize: Size.fromRadius(18),
child: CircleAvatar(
radius: 18,
backgroundColor: Colors.grey,
backgroundImage: NetworkImage(
"https://i.pinimg.com/736x/6f/de/85/6fde85b86c86526af5e99ce85f57432e.jpg")),
),
avatarChild: (context, data) => const PreferredSize(
preferredSize: Size.fromRadius(12),
child: CircleAvatar(
radius: 12,
backgroundColor: Colors.grey,
backgroundImage: NetworkImage(
"https://i.pinimg.com/736x/6f/de/85/6fde85b86c86526af5e99ce85f57432e.jpg")),
),
contentChild: (context, data) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding:
const EdgeInsets.symmetric(vertical: 8, horizontal: 8),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(12)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'${data.userName}',
style: Theme.of(context).textTheme.caption?.copyWith(
fontWeight: FontWeight.w600, color: Colors.black),
),
const SizedBox(
height: 4,
),
Text(
'${data.content}',
style: Theme.of(context).textTheme.caption?.copyWith(
fontWeight: FontWeight.w300, color: Colors.black),
),
],
),
),
DefaultTextStyle(
style: Theme.of(context).textTheme.caption!.copyWith(
color: Colors.grey[700], fontWeight: FontWeight.bold),
child: Padding(
padding: const EdgeInsets.only(top: 4),
child: Row(
children: const [
SizedBox(
width: 8,
),
Text('5d'),
SizedBox(
width: 8,
),
Text('Like'),
SizedBox(
width: 24,
),
Text('Reply'),
],
),
),
)
],
);
},
contentRoot: (context, data) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding:
const EdgeInsets.symmetric(vertical: 8, horizontal: 8),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(12)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Tina Chuhan',
style: Theme.of(context).textTheme.caption!.copyWith(
fontWeight: FontWeight.w600, color: Colors.black),
),
const SizedBox(
height: 4,
),
Text(
'${data.content}',
style: Theme.of(context).textTheme.caption!.copyWith(
fontWeight: FontWeight.w300, color: Colors.black),
),
],
),
),
DefaultTextStyle(
style: Theme.of(context).textTheme.caption!.copyWith(
color: Colors.grey[700], fontWeight: FontWeight.bold),
child: Padding(
padding: const EdgeInsets.only(top: 4),
child: Row(
children: const [
SizedBox(
width: 8,
),
Text('5d'),
SizedBox(
width: 8,
),
Text('Like'),
SizedBox(
width: 24,
),
Text('Reply'),
],
),
),
)
],
);
},
),
),
],
);
}
}

Flutter TextOverflow not working, and causing RenderOverflow

I'm trying to make a chat app UI, and thought of using TextOverflow to fix the problem where the last sent message exceedes the size of the screen and causes Render Overflow. So I simply modified my Text widget, adding these 3 lines-
Text(
widget.lastMessage,
overflow: TextOverflow.ellipsis,
maxLines: 1,
softWrap: true,
style: const TextStyle(
fontWeight: FontWeight.w200,
),
)
However, this made no difference-
Here's the code-
Main ListView-
import 'package:project_name/widgets/chat_preview_tile_widget.dart';
import 'package:flutter/material.dart';
class ChatPreviewTileCard extends StatefulWidget {
const ChatPreviewTileCard({Key? key}) : super(key: key);
#override
_ChatPreviewTileCardState createState() => _ChatPreviewTileCardState();
}
class _ChatPreviewTileCardState extends State<ChatPreviewTileCard> {
#override
Widget build(BuildContext context) {
return Expanded(
child: ListView.builder(
itemCount: 10,
itemBuilder: (context, n) {
//Individual List Tile
return const ChatPreviewTileWidget(
username: "Person",
imageUrl:
"https://www.nme.com/wp-content/uploads/2021/07/RickAstley2021.jpg",
time: "9:30PM",
hasUnreadMessage: true,
lastMessage:
"i am susssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssSSSSSSSSSSs",
);
},
),
);
}
}
Individual Tile Widget-
import 'package:airing/screens/chat_screen/user_chat/user_chat_screen.dart';
import 'package:airing/utils/color_themes.dart';
import 'package:flutter/material.dart';
class ChatPreviewTileWidget extends StatefulWidget {
final String username;
final String imageUrl;
final String time;
final bool hasUnreadMessage;
final String lastMessage;
const ChatPreviewTileWidget({
Key? key,
required this.username,
required this.imageUrl,
required this.time,
required this.hasUnreadMessage,
required this.lastMessage,
}) : super(key: key);
#override
_ChatPreviewTileWidgetState createState() => _ChatPreviewTileWidgetState();
}
class _ChatPreviewTileWidgetState extends State<ChatPreviewTileWidget> {
static int widgetsInScreen = 12;
static int pfpPadding = 10;
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return UserChatScreen(
imageUrl: widget.imageUrl, username: widget.username);
},
),
);
},
child: Column(
children: [
Container(
width: double.infinity,
height: MediaQuery.of(context).size.height / widgetsInScreen,
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 2.5),
//main row
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
//Pfp, username and last message row
Row(
mainAxisSize: MainAxisSize.min,
children: [
CircleAvatar(
backgroundColor: secondaryColor,
backgroundImage: NetworkImage(
widget.imageUrl,
),
radius: ((MediaQuery.of(context).size.height /
widgetsInScreen) -
(2 * pfpPadding)) /
2,
),
Padding(
padding: const EdgeInsets.only(
left: 10,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.username,
style: TextStyle(
fontWeight: FontWeight.bold,
color: secondaryMainThemeColor),
),
Text( //Here is the text message widget.
widget.lastMessage,
overflow: TextOverflow.ellipsis,
maxLines: 1,
softWrap: true,
style: const TextStyle(
fontWeight: FontWeight.w200,
),
)
],
),
)
],
),
//sent and notification Column
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
widget.time,
style: TextStyle(
color: secondaryMainThemeColor,
fontWeight: FontWeight.w200),
),
Icon(
Icons.circle_rounded,
color: mainThemeColor,
size: 15,
)
],
)
],
),
),
const Divider()
],
));
}
}
How do I fix this? Thanks in advance!
Wrap your Text Column with Expanded widget like this:
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.username,
style: TextStyle(
fontWeight: FontWeight.bold, color: secondaryMainThemeColor),
),
Text(
//Here is the text message widget.
widget.lastMessage,
overflow: TextOverflow.ellipsis,
maxLines: 1,
softWrap: true,
style: const TextStyle(
fontWeight: FontWeight.w200,
),
)
],
),
),
Hope It Works!
Change your code to this:
import 'package:airing/screens/chat_screen/user_chat/user_chat_screen.dart';
import 'package:airing/utils/color_themes.dart';
import 'package:flutter/material.dart';
class ChatPreviewTileWidget extends StatefulWidget {
final String username;
final String imageUrl;
final String time;
final bool hasUnreadMessage;
final String lastMessage;
const ChatPreviewTileWidget({
Key? key,
required this.username,
required this.imageUrl,
required this.time,
required this.hasUnreadMessage,
required this.lastMessage,
}) : super(key: key);
#override
_ChatPreviewTileWidgetState createState() => _ChatPreviewTileWidgetState();
}
class _ChatPreviewTileWidgetState extends State<ChatPreviewTileWidget> {
static int widgetsInScreen = 12;
static int pfpPadding = 10;
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return UserChatScreen(
imageUrl: widget.imageUrl, username: widget.username);
},
),
);
},
child: Column(
children: [
Container(
width: double.infinity,
height: MediaQuery.of(context).size.height / widgetsInScreen,
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 2.5),
//main row
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
//Pfp, username and last message row
Row(
mainAxisSize: MainAxisSize.min,
children: [
CircleAvatar(
backgroundColor: secondaryColor,
backgroundImage: NetworkImage(
widget.imageUrl,
),
radius: ((MediaQuery.of(context).size.height /
widgetsInScreen) -
(2 * pfpPadding)) /
2,
),
**//here is the changes**
Expanded(child: Padding(
padding: const EdgeInsets.only(
left: 10,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.username,
style: TextStyle(
fontWeight: FontWeight.bold,
color: secondaryMainThemeColor),
),
Text( //Here is the text message widget.
widget.lastMessage,
overflow: TextOverflow.ellipsis,
maxLines: 1,
softWrap: true,
style: const TextStyle(
fontWeight: FontWeight.w200,
),
)
],
),),
)
],
),
//sent and notification Column
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
widget.time,
style: TextStyle(
color: secondaryMainThemeColor,
fontWeight: FontWeight.w200),
),
Icon(
Icons.circle_rounded,
color: mainThemeColor,
size: 15,
)
],
)
],
),
),
const Divider()
],
));
}
}
Nevermind! Wrapping my text widget with a SizedBox with a defined width fixed it-
SizedBox(
width: MediaQuery.of(context).size.width / 2,
child: Text(
widget.lastMessage,
overflow: TextOverflow.ellipsis,
maxLines: 1,
softWrap: true,
style: const TextStyle(
fontWeight: FontWeight.w200,
),
),
),

Exception caught by gesture library, type 'Null' is not a subtype of type 'String' of 'function result'

Currently I am coding a shop application and trying to make the product card clickable, however there was an error that occurred:
Exception caught by gesture library, type 'Null' is not a subtype of type 'String' of 'function result'
Here is my code for the product card (button):
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:minimlst/components/product_card.dart';
import 'package:minimlst/constants.dart';
import 'package:minimlst/models/product.dart';
import 'package:minimlst/screens/details/details_screen.dart';
import 'package:minimlst/screens/home/components/discount_banner.dart';
import 'package:minimlst/screens/home/components/home_header.dart';
import 'package:minimlst/size_config.dart';
class Body extends StatelessWidget {
const Body({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return SafeArea(
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(height: getProportionateScreenWidth(20)),
HomeHeader(),
SizedBox(height: getProportionateScreenWidth(30)),
DiscountBanner(),
SizedBox(height: getProportionateScreenWidth(20)),
Column(children: [
Text(
"Our Catalog",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
]),
SizedBox(height: getProportionateScreenWidth(30)),
SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
...List.generate(
demoProducts.length,
(index) => ProductCard(
product: demoProducts[index],
press: () => Navigator.pushNamed(
context, DetailsScreen.routeName)),
),
SizedBox(width: getProportionateScreenWidth(20)),
],
),
),
],
),
),
);
}
}
and here is my code for the ProductCard:
import 'package:flutter/material.dart';
import 'package:minimlst/models/product.dart';
import '../constants.dart';
import '../size_config.dart';
class ProductCard extends StatelessWidget {
const ProductCard({
Key? key,
this.width = 140,
this.aspectRetio = 1.02,
required this.product,
required this.press,
}) : super(key: key);
final double width, aspectRetio;
final Product product;
final GestureTapCallback press;
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: press,
child: SizedBox(
width: getProportionateScreenWidth(width),
child: Padding(
padding: EdgeInsets.only(left: getProportionateScreenWidth(20)),
child: Column(
children: [
AspectRatio(
aspectRatio: aspectRetio,
child: Container(
padding: EdgeInsets.all(getProportionateScreenWidth(20)),
decoration: BoxDecoration(
color: kSecondaryColor.withOpacity(0.2),
borderRadius: BorderRadius.circular(15),
),
child: Image.asset(product.images[0])),
),
Text(
product.title,
style: TextStyle(color: Colors.black),
maxLines: 2,
),
Row(
children: [
Text(
"\$${product.price}",
style: TextStyle(
fontSize: getProportionateScreenWidth(18),
fontWeight: FontWeight.w600,
color: kPrimaryColor,
),
),
],
),
],
),
),
),
);
}
}
Please help if you can, any kind of help would be very much appreciated, if you need any other bits of the code lmk
the issue is that you are passing wrong function argument to press
As syntax is () => Navigator.pushNamed(
context, DetailsScreen.routeName)
as fat arrow refers return so you are returning Navigator.pushNamed as argument required function who's return type must be void etc
so the change is press:(){
Navigator.pushNamed(context, DetailsScreen.routeName)
}

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

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