This is strange, the Wrap widget, containing FilterChips, is centering inside it's parent a ExpansionPanel. I've tried wrapping the Wrap Widget in a Flexible widget, no reaction, I've tried wrapping in an Expanded widget, no reaction.
There doesn't appear to be a property on the Expansion panel to left align body: Widgets. It's important because some of the ExpansionPanels are aligning to the left, when the Wrap widget has been forced to full width, but others, like pictured, center. Ultimately I'm going to wrap all the children widgets in the ExpansionPanel in a Padding widget, but I need the child Wrap widgets aligning left first.
bool travelSack;
ExpansionPanelRadio backpackingPanel = ExpansionPanelRadio(
value: "Backpacking",
headerBuilder: (BuildContext context, bool isExpanded) {
return ListTile(
leading: FaIcon(
FontAwesomeIcons.globeEurope,
size: 19,
),
title: Text("Backpacking"),
);
},
body: Expanded(child:
Wrap(spacing: 4, children: [
FilterChip(
showCheckmark: false,
label: Text('Travel rucksack'),
labelStyle: TextStyle(
color: travelSack ? Colors.black : Colors.white,
),
selected: travelSack,
onSelected: (bool selected) {
setState(() {
travelSack = !travelSack;
});
},
selectedColor: Colors.green.shade500,
backgroundColor: Colors.grey.shade500,
),
])
);
I'm Scoobied, help appreciated.
I solved this by nesting the Wrap widget inside an Align widget:
Align(
alignment: Alignment.topLeft,
child: Wrap(....
I do not like my solution, I'm wary of so much nestings effect on performance and sprawling code harms legibility, so if you have a better solution I'm all eyes. x Sam.
Wrap has an alignment property that you can use to align the children.
https://api.flutter.dev/flutter/widgets/Wrap/Wrap.html
Wrap(
...
alignment: WrapAlignment.center,
children: [],
),
I had the same problem and resolve with SizedBox:
ExpansionPanelRadio backpackingPanel = ExpansionPanelRadio(
value: "Backpacking",
headerBuilder: (BuildContext context, bool isExpanded) {},
body: SizedBox(
width: double.infinity, // Use when direction: Axis.horizontal
height: double.infinity, // Use when direction: Axis.vertical
child: Wrap(
spacing: 4,
children: [
FilterChip(
showCheckmark: false,
label: Text('Travel rucksack'),
labelStyle: TextStyle(
color: travelSack ? Colors.black : Colors.white,
),
selected: travelSack,
onSelected: (bool selected) {
setState(() {
travelSack = !travelSack;
});
},
selectedColor: Colors.green.shade500,
backgroundColor: Colors.grey.shade500,
),
],
),
),
);
Remember to not use width and height SizedBox property at same time, only one for each Wrap.direction.
Reference
Related
How to prevent OverFlow of the Trailing widget using Column widget to occupy all the children elements inside of a ListTile widget ?
Thanks and appreiciate you help.
body: ListView.builder(
restorationId: 'sampleItemListView',
itemCount: items.length,
itemBuilder: (BuildContext context, int index) {
final item = items[index];
return Padding(
padding: const EdgeInsets.only(top: 8, left: 8, right: 8),
child: Container(
color: Colors.grey.shade400,
height: 200,
child: ListTile(
isThreeLine: true,
leading: const CircleAvatar(
// Display the Flutter Logo image asset.
foregroundImage:
AssetImage('assets/images/flutter_logo.png'),
),
title: Text('Title ${item.id}'),
subtitle: Text('Subtitle ${item.id}'),
How to expand the column in the Trailing component of the
ListTile to prevent Overflow?
trailing: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const [
Icon(
Icons.emoji_emotions,
color: Colors.green,
),
Icon(
Icons.emoji_emotions,
color: Colors.orange,
),
Icon(
Icons.emoji_emotions,
color: Colors.red,
),
],
),
onTap: () {
Navigator.restorablePushNamed(
context,
SampleItemDetailsView.routeName,
);
}),
),
);
},
),
ERROR:
════════ Exception caught by rendering library ═════════════════════════════════
A RenderFlex overflowed by 16 pixels on the bottom.
The relevant error-causing widget was
Column
Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the RenderFlex to fit within the available space instead of being sized to their natural size.
This is considered an error condition because it indicates that there is content that cannot be seen. If the content is legitimately bigger than the available space, consider clipping it with a ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex, like a ListView.
In your case there r many answers like
1: ListTile( visualDensity: VisualDensity(vertical: 4))
2: ListTile(
trailing: FittedBox(
child: Column( children: const [Icon(),Icon(),Icon()]),
),
)
** But best solution in my opinion, In such extensive cases use "Row" than "ListTile" it gives u way more control over ur UI widgets.
I am new to the flutter and trying to fill the empty space in the listtile. I tried to use dense and visualDensity but with that, I am not getting the required result. Any support and suggestions will be appreciated.
here is my code and output:
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
SizedBox(
height: isLargeScreen ? 300 : 200,
child: ListView.builder(
physics: const ScrollPhysics(),
shrinkWrap: true,
itemCount: tags.length,
itemBuilder: (context, index) {
return CheckboxListTile(
value: tempSelectedTags.contains(tags[index].id),
onChanged: (e) {
setState(() {
if (tempSelectedTags.contains(tags[index].id)) {
tempSelectedTags.remove(tags[index].id);
} else {
tempSelectedTags.add(tags[index].id);
}
});
},
title: Text(
tags[index].name,
style: !tempSelectedTags.contains(tags[index].id)
? theme.textTheme.labelMedium?.copyWith(
color: ThemeConfig.colorTertiary)
: theme.textTheme.titleSmall?.copyWith(
color: ThemeConfig.colorTertiary),
),
);
}),
),
const Spacer(),
Padding(
padding: const EdgeInsets.only(bottom:sdPaddingMedium),
child: SdPrimaryButton(
title: appLocalizations.btnApply,
onPressed: () {
viewModel.setTags(tempSelectedTags);
Navigator.pop(context);
},
),
),
],
)
Output can be seen here
There are two important things that determine the vertical layout in your column.
The whole box has a fixed size
SizedBox(
height: isLargeScreen ? 300 : 200,
There is a flexible space between the checkbox options and the bottom-right button
const Spacer(),
So if you want to remove the space, you can either
reduce the overall box size or
replace the const Spacer with a constant spacing like
SizedBox(height: 50) and also remove the SizedBox, so that the whole box will be content-sized
I have an ExpansionTile within my Drawer widget. When I expand this item, it automatically adds a divider line above and below. I want these divider lines permanently.
So I'd either like to know how to show the ExpansionTile's divider lines always (expanded and unexpanded), or I can add my own divider lines and tell the ExpansionTile to never show divider lines.
Is this possible? Thanks.
you can hide divider lines by wrapping the ExpansionTile widget in Theme Widget,
your code will look like this after you add Theme widget
Theme(
data: Theme.of(context).copyWith(dividerColor: Colors.transparent),
child:ExpansionTile(
title:...,
children:[],
),
),
check this Github Issue
#RJB, I had the same issue, I resolved wrapping the ExpansionTile with a column, like this:
Theme(
data: Theme.of(context).copyWith(dividerColor: Colors.transparent),
child: Column(
children: [
ExpansionTile(
title: Text(
'My title',
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
trailing: Icon(
_showContent
? Icons.expand_less_rounded
: Icons.expand_more_rounded,
),
onExpansionChanged: (bool expanded) {
setState(() => _showContent = expanded);
},
children: <Widget>[
Text('My content'),
],
),
const Divider(
color: Colors.amber,
thickness: 1,
height: 0,
)
],
),
);
I know it isn't pretty, but I could't find an Expansion component that I could personalize every aspect of its appearance.
Another option is that instead of wrapping the ExpansionTile widget with Theme, you can pass the shape directly to ExpansionTile as follows:
shape: RoundedRectangleBorder(
side: BorderSide(color: Colors.transparent),
),
I have a certain Text widget , when it overflows I have 3 options. Either fade ,visible, ellipsis or clip. But I don't want to choose between them . I want if a text has overflow then don't show the text.
Edit :
I'm working on a code clone to this design
Assuming that the textStyle is unknown.
How could I achieve that?
Code:
class SwipeNavigationBar extends StatefulWidget {
final Widget child;
SwipeNavigationBar({this.child});
#override
_SwipeNavigationBarState createState() => _SwipeNavigationBarState();
}
class _SwipeNavigationBarState extends State<SwipeNavigationBar> {
#override
Widget build(BuildContext context) {
return Consumer<Controller>(
builder: (_, _bloc, __) {
return SafeArea(
child: AnimatedContainer(
duration: Duration(seconds: 01),
color: Colors.white,
curve: Curves.easeIn,
height: !_bloc.x ? 50 : 200,
child: Row(
children: [
Column(
verticalDirection: VerticalDirection.up,
children: [
Expanded(child: Icon(Icons.dashboard)),
Expanded(
child: RotatedBox(
quarterTurns: -45,
child: Text(
'data',
softWrap: false,
style: TextStyle(
textBaseline: TextBaseline.alphabetic
),
),
),
),
],
)
],
),
),
);
},
);
}
}
To mimic the design you might want to look into using the Stack widget. However, to answer your question, you'd want to set softWrap to false.
Align(
alignment: Alignment.topLeft,
child: SizedBox(
width: 100,
child: Text(
'Some text we want to overflow',
softWrap: false,
),
),
)
softWrap is really the key here. Although, I added the Align and SizedBox widgets to allow this to be used anywhere, regardless of what parent widget you are using (since some widgets set tight constraints on their children and will override their children's size preference).
CodePen Example
Edit: 5/6/2020
With the release of Flutter v1.17 you now have access to a new Widget called NavigationRail which may help you with the design you're looking for.
Use ternary operator to check the length of the text that you are passing to the Text widget and based on that pass the text itself or an empty string.
String yourText;
int desiredLengthToShow = 10; //Change this according to you.
...
Text(
child: yourText.length > desiredLengthToShow ? "" : yourText,
);
I have two rowCell's inside a Row widget in my app and I want to assign them different pages. I've tried putting the rowCell's in a GestureDetector, a FlatButton but neither of them have worked (as they should be linked to the Row widget and they need separate links for separate pages.)
Here is the part of my code:
...
new Divider(
height: _height / 20,
color: Colors.grey,
),
new Row(
children: <Widget>[
rowCell(10250, 'MEETUPS'),
rowCell(1520, 'FRIENDS'),
],
),
new Divider(height: _height / 20, color: Colors.grey),
...
Any solutions?
Just wrap the rowCell with GestureDetectorthen you will get separate onTap function with the same design.
Otherwise, you can use GestureDetector inside the rowCell(). And pass a function to the rowCell() to attach to the GestureDetector.
Widget rowSell(<your parameters>, Function onTapFunction) {
return GestureDetector(
onTap: onTapFunction,
child: <Your child>
),
}
And pass the function like:
new Row(
children: <Widget>[
rowCell(10250, 'MEETUPS', (){ <on Tap code> }),
rowCell(1520, 'FRIENDS', (){ <on Tap code> }),
],
),
The GestureDetector probably isn't working because you're wrapping it around the text and in that scenario, it's rare that it will work because you the onTap space is relative to space the text covers on the screen.
Try giving some padding inside the rowCell and then wrap it in a gesture detector, it will probably break your layout but at least you will know the problem and adjust accordingly.
Please try this...
If rowCell is return widget then wrap rowCell with GestureDetector and get click of that...
...
new Divider(
height: _height / 20,
color: Colors.grey,
),
new Row(
children: <Widget>[
GestureDetector(onTap: () {}, child: rowCell(10250, 'MEETUPS')),
GestureDetector(onTap: (){},child: rowCell(1520, 'FRIENDS')),
],
),
new Divider(height: _height / 20, color: Colors.grey),
...
From the comment from above you mention, I assume your rowCell function returns an Expanded widget.
So in rowCell function, inside Expanded widget add Inkwell widget. Also add one more argument which tells the page that you want to navigate to (onTap).
Widget rowCell(int count, String title, Widget navTo){
return Expanded(
child: Inkwell(
onTap: () => _navToPage(navTo)
child: .... //Your child widget
),
);
}
void _navToPage(Widget navTo){
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => navTo,
),
);
}
new Divider(height: _height / 20, color: Colors.grey),
new Row(
children: <Widget>[
GestureDetector(onTap: () {}, child: rowCell(10250, 'MEETUPS', MeetupsPage())),
GestureDetector(onTap: (){},child: rowCell(1520, 'FRIENDS', FriendsListPage())),
],
),
new Divider(height: _height / 20, color: Colors.grey),