I'm implementing a chat on my flutter app, and I want my chat-time to be align at the right side of the column (all other widgets should be align left).
My problem is that when I'm using alignment.bottomRight in my column, it extends the column width to max (and I want to keep it min).
The problem:
What I'm trying to achieve:
my column:
return Bubble(
margin: BubbleEdges.only(top: 5, bottom: 5),
elevation: 0.6,
alignment: Alignment.topLeft,
nip: BubbleNip.leftTop,
radius: Radius.circular(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
getUserChatTitle(document['userId']),
Padding(
padding: const EdgeInsets.only(top: 3, bottom: 5),
child: SelectableLinkify(
onOpen: onOpenLink,
text: "Text Text Text",
textAlign:
intl.Bidi.detectRtlDirectionality(document['content'])
? TextAlign.right
: TextAlign.left,
textDirection:
intl.Bidi.detectRtlDirectionality(document['content'])
? ui.TextDirection.rtl
: ui.TextDirection.ltr,
style: TextStyle(
fontSize: 16,
height: 1.35,
letterSpacing: -0.1,
fontFamily: 'Arimo',
),
),
),
Align(
alignment: Alignment.bottomRight,
child: Text(
formatTimestampToString(document['timestamp']),
textAlign: TextAlign.left,
style: TextStyle(
color: Colors.grey,
fontSize: 12,
),
),
),
],
),
);
This is indeed not as easy, because you want the bubble to have an "undefined" width - it should adapt to the length of the actual message which is not known before actually placing / drawing the widget on runtime. My suggestion would be to make use of a Stack - I also used it inside a ListView.builder which will probably be the desired use case. Make sure to read my comments in the code block as well:
ListView.builder(
itemCount: 5,
itemBuilder: (context, index) => UnconstrainedBox(
/// Decide whether a message has been received or written by yourself (left or right side)
alignment:
index % 2 == 0 ? Alignment.centerLeft : Alignment.centerRight,
/// ConstrainedBox to make sure chat bubbles don't go from left to right if they are too big - you can change it or even remove it if it's not what you want
child: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width / 1.5),
child: Bubble(
margin: BubbleEdges.only(top: 5, bottom: 5),
elevation: 0.6,
/// Alignment and nip has to be adjusted here too
alignment:
index % 2 == 0 ? Alignment.topLeft : Alignment.topRight,
nip: index % 2 == 0 ? BubbleNip.leftTop : BubbleNip.rightTop,
radius: Radius.circular(10),
child: Stack(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('TestUser'),
Padding(
padding: const EdgeInsets.only(top: 3, bottom: 5),
child: Text(
'Text ' * Random().nextInt(50),
style: TextStyle(
fontSize: 16,
height: 1.35,
letterSpacing: -0.1,
),
),
),
/// Adjust the space you want between the actual message and the timestamp here, you could also use a Text widget to use the same height as the actual timestamp - as you like
SizedBox(height: 18.0),
],
),
Positioned(
bottom: 0,
right: 0,
child: Text(
'08.09.2021',
style: TextStyle(
color: Colors.grey,
fontSize: 12,
),
),
),
],
),
),
),
),
),
Replace this:
Align(
alignment: Alignment.bottomRight,
child: Text(
formatTimestampToString(document['timestamp']),
textAlign: TextAlign.right,
style: TextStyle(
color: Colors.grey,
fontSize: 12,
),
),
),
With:
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [Text(
formatTimestampToString(document['timestamp']),
textAlign: TextAlign.right,
style: TextStyle(
color: Colors.grey,
fontSize: 12,
),
)],
),
Related
Widget myPost(double screenH, BuildContext context, double screenW) {
String sampleSrc =
"https://images.unsplash.com/photo-1475924156734-496f6cac6ec1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2070&q=80";
return Container(
margin: const EdgeInsets.symmetric(vertical: 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
constraints: BoxConstraints(minWidth: screenW * 0.1),
height: screenH * 0.1,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
const CircleAvatar(
radius: 30,
),
SizedBox(
width: screenW * 0.01,
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"QWE QWE",
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"27 min",
),
const Icon(
Icons.enhanced_encryption_sharp,
size: 12,
),
],
),
],
),
],
),
const Icon(Icons.more_vert_sharp),
]),
),
),
ReadMoreText(
"text" * 800,
trimCollapsedText: "Read More...",
trimExpandedText: "Read less",
trimLines: 3,
style: const TextStyle(fontSize: 20),
trimMode: TrimMode.Line,
moreStyle: const TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
),
lessStyle: const TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
InkWell(
onTap: () {},
child: Container(
constraints: BoxConstraints.loose(Size.fromHeight(screenH * 0.5)),
child: Image.network(
sampleSrc,
fit: BoxFit.fitWidth,
width: double.infinity,
),
),
),
],
),
);
}
My design
I'm using the responsive_framework package, but when I reduce the height, all the widgets resizing, and I get overflows. The design I'm trying to make is like the following GIF the design that I want
Just like in responsive sites, I want the widgets to be fixed and only scrollable, no matter how much the height decreases.
Any trick or document to do this ?
The overall height on shrink is greater than height: screenH * 0.1, you can include extra pixels like height: 10+ (screenH * 0.1) But you can just include fixed height here. Like on item, you can choose minimum fixed height like 64, and you don't to have to worry about making larger. You can also check your attached GIF row height doesn't change.
Second option is wrapping Text with FittedBox widget, or using auto_size_text.
I am using a ListWheelScrollView that is using physics: FixedExtentScrollPhysics(),. I have used various other ScrollControllers in my app. I want to supply a parameter to my ListWheelScrollView so that it uses the same ScrollController as the rest of my widgets. However it does not allow me to supply the controller:mainController parameter along with FixedExtentScrollPhysics(). How can I solve this?
Here this is the declaration of mainController, the on that I'm trying to call in ListWheelScrollView :
final mainController = ScrollController();
The code for my list is :
ListWheelScrollView.useDelegate(
itemExtent: 90,
perspective: 0.0025,
magnification: 1.2,
physics: FixedExtentScrollPhysics(),
diameterRatio: 4,
// controller: mainController,
offAxisFraction: 0.42,
useMagnifier: true,
childDelegate: ListWheelChildBuilderDelegate(
builder: (
context,
index,
) {
return Column(
children: [
ListTile(
isThreeLine: false,
trailing: indexTrailing(index, duration, true),
title: Row(
children: <Widget>[
Padding(
padding: EdgeInsets.only(
right: 10, top: 5, bottom: 5),
child: ClipRRect(
borderRadius: BorderRadius.circular(12.0),
child: Container(
height: 60,
width: 60,
child: Image.network(
'https://www.ikea.com/in/en/images/products/smycka-artificial-flower-rose-red__0903311_PE596728_S5.JPG'),
),
),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Hello',
style: GoogleFonts.montserrat(
wordSpacing: 0,
letterSpacing: 0,
textStyle: kTasksStyle.copyWith(
fontSize: 15,
color: kDarkBlue,
fontWeight: FontWeight.w500),
),
),
SizedBox(
height: 5,
),
SizedBox(
width: MediaQuery.of(context).size.width *
0.62,
child: RichText(
maxLines: 2,
overflow: TextOverflow.ellipsis,
text: TextSpan(
text: "This is a rose",
style: GoogleFonts.montserrat(
textStyle: kTasksStyle.copyWith(
fontSize: 12,
color: kGrey,
fontWeight: FontWeight.normal),
),
),
),
)
],
),
),
],
),
),
Padding(
padding: const EdgeInsets.only(
left: 18.0, right: 18, top: 5, bottom: 5),
child: Divider(
height: 1,
color: Colors.grey.withOpacity(0.2),
thickness: 1,
),
),
],
);
},
childCount: 9),
),
This is the error that I get when I supply the controller parameter along with FixedExtentScrollPhysics():
'package:flutter/src/widgets/scroll_position.dart': Failed assertion: line 504 pos 12: 'haveDimensions == (_lastMetrics != null)': is not true.
The relevant error-causing widget was
ListWheelScrollView
and
The following assertion was thrown during performLayout():
FixedExtentScrollPhysics can only be used with Scrollables that uses the FixedExtentScrollController
'package:flutter/src/widgets/list_wheel_scroll_view.dart':
Failed assertion: line 485 pos 7: 'position is _FixedExtentScrollPosition'
Just use;
FixedExtentScrollController();
instead of
ScrollController();
I am trying to make my UI scrollable but when i add the SingleChildScrollView i get this white screen not showing anything at all.I should erase the Column from the begining?Use a container?I already search on internet but i don't know what to add.
Here is my code, please tell me what i can erase or add to make it work ..
class _UserProfilesState extends State<UserProfiles> {
#override
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Expanded(
child: Stack(
children: <Widget>[
Padding(
padding:
EdgeInsets.symmetric(horizontal: 10.0, vertical: 40.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(Icons.arrow_back),
iconSize: 30.0,
color: Colors.black,
onPressed: () => Navigator.pop(context),
),
])),
Positioned(
left: 24,
top: MediaQuery.of(context).size.height / 6.5 - 28,
child: Container(
height: 84,
width: 84,
//profilepic
child: CircleAvatar(
radius: 10,
backgroundImage: NetworkImage(widget.avatarUrl != null
? widget.avatarUrl
: "https://icon-library.com/images/add-image-icon/add-image-icon-14.jpg"),
),
),
),
Positioned(
right: 24,
top: MediaQuery.of(context).size.height / 6.5 + 16,
child: Row(
children: <Widget>[
Container(
height: 32,
width: 100,
child: RaisedButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => ChatScreen(
serviceProviderId:
widget.serviceProviderId,
userName: widget.userName,
avatarUrl: widget.avatarUrl,
)));
},
color: Colors.black,
textColor: Colors.white,
child: Text(
"Message",
style: TextStyle(fontWeight: FontWeight.bold),
)),
),
SizedBox(
width: 16,
),
Container(
height: 32,
width: 32,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
"https://lh3.googleusercontent.com/Kf8WTct65hFJxBUDm5E-EpYsiDoLQiGGbnuyP6HBNax43YShXti9THPon1YKB6zPYpA"),
fit: BoxFit.cover),
shape: BoxShape.circle,
color: Colors.blue),
),
],
),
),
Positioned(
left: 24,
top: MediaQuery.of(context).size.height / 4.3,
bottom: 0,
right: 0,
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(widget.userName,
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 22,
)),
SizedBox(
height: 4,
),
Padding(
padding: const EdgeInsets.all(1.0),
child: Text(
widget.address == "default"
? "No Address yet"
: "${widget.address}",
style: TextStyle(
color: Colors.black,
fontSize: 12,
),
)),
Padding(
padding: const EdgeInsets.all(1.0),
child: Text(
"${widget.categoryName}",
style: TextStyle(
color: Colors.black,
fontSize: 12,
),
)),
],
),
))
],
))
],
),
),
);
}
}
Using Spacer() might also cause this issue
The reason why your UI became white is that SingleChildScrollView allows it child to take as much space as possible. In your Column, one of your children is Expanded, Expanded tries to take as much space as possible. You are making your UI take an infinite amount of space because of that. That's the reason why you are seeing a white screen. The solution here would be to remove Expanded.
according to me and the knowledge I have this happened because the singlechildscrollview here tries to take as much height as it can take so It is creating an issue to solve this wrap the singlechildscrollview in a container and give height&width to the container it solved in my case
Thanks...
I faced similar issues, but after much research I got it working, by ensuring that the body of the scaffold be a Container that defines it's height and width, or Column. After which you can wrapped your any of these with a SingleChildScrollView.
However, in an attempt to insert an Expanded widget as child element, the expanded widget will look for bounded heights of it's parents/root element. And if it doesn't found any, it will thrown an error. A good example is if the root element is a column or a container with an unbounded height. Which is your case, looking at your code
I want to add space between "Radio Frequency" and "Propagation" vertically i.e something like margin. and also make sure that text does not cut from top or bottom if I increase the font size.
Below is my code, I tried with spacing of letters, words and also decoration param but it did not get desired results. Thank you for your patience :)
#override
Widget build(BuildContext context) {
return Scaffold(
body: GridView.count(
padding: const EdgeInsets.fromLTRB(0, 20, 0, 0),
childAspectRatio: 1.5,
mainAxisSpacing: 30,
crossAxisCount: 3,
children: List.generate(
12,
(index) {
return Center(
child: Column(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 5),
child: CircleAvatar(
child: Transform.scale(
scale: 1,
child: Image.asset(
'assets/icons/radar_icon.png',
height: 30,
width: 30,
fit: BoxFit.fitWidth,
),
),
backgroundColor: Colors.grey.shade300,
radius: 30,
)),
Flexible(
child: Text(
"Radio Frequency Propagation",
textAlign: TextAlign.center,
style: GoogleFonts.roboto(color: Colors.black87, fontSize: 14,height: 0.8),
),
),
],
));
},
),
));
}
You are using height is correct. But I think the problem is the placement of the style parameters.
It should be like this:
Flexible(
child: Text(
"Radio Frequency \nPropagation",
textAlign: TextAlign.center,
style: GoogleFonts.roboto(
textStyle: TextStyle(
color: Colors.black87,
fontSize: 14,
height: 1.5,
),
),
),
);
}
I have a row with a steps and separators. Each step is wrapped in an Expand; the separator has a fixed size.
The Expanded causes the containers to have a fine white line between them
When i remove the Expanded, the lines are gone
Anybody know a fix or workaround?
The code looks similar to this
Row(
children: <Widget>[
Expanded(
child: Container(
height: height,
color: AppTheme.blue,
child: Center(
child: Text(
"Define",
style: TextStyle(
color: AppTheme.white,
fontSize: 13,
),
),
),
),
),
Container(
height: height,
width: height/2.0,
color: AppTheme.blue
),
Expanded(
child: Container(
height: height,
color: AppTheme.grey,
child: Center(
child: Text(
"Mix 1",
style: TextStyle(
color: AppTheme.black,
fontSize: 13,
),
),
),
),
),
Container(
height: height,
width: height/2.0,
color: AppTheme.grey
),
...
]
)
EDIT 1:
The reason why i am doing all this is that the final separator need to be custom pained.
I now do custom paint the steps, so the container is gone.
The code now looks similar to this
Expanded(
child: CustomPaint(
painter: StepPainter(
isActive: isActive,
height: height,
text: TextSpan(
text: text,
style: TextStyle(
color: isActive ? AppTheme.white : AppTheme.darkGrey,
fontSize: 13,
),
),
),
),
)
since you didn't provide the code of StepPainter, what if you just apply white border to the object?