I have a list of items that I want to display in non-scrollable horizontal layout.
In the example below, I have 5 items, 2 of them are fully displayed and the other 3 do not fit, hence the ' 3' label.
I do not mind if there is some empty space after the label, but the important thing is that we only display items that fully fit in the row.
I guess the main problem is how can I test that a widget fits based on it's width into a row?
I thought about VisibilityDetector, but I will ended up rendering all widgets, then removing the ones that are not 100% visible, and the entire logic seems quite flawed for this use case.
Any ideas? Thanks
CodePudding user response:
EDIT: Included dynamic width based in label length
Try this, with defined width of item container and the label or with dynamic calculating the width based on font size.
Change useFixedWidth to true or false if you want dynamic or static width.
Example in a Stateless widget:
class MyWidget extends StatelessWidget {
final double itemWidth = 100; //maxwidth if item container
final double labelWidth = 40; //maxWidth of label
List<String> items = List.generate(
10, (index) => 'Name ${index 1}'); //replace with a real list of items
final bool useFixedWidth =
false; // define if want to calculate dynamic with of each item
final double letterWidth =
12; // defined width of a letter || change depending on font size
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
int totalItems = items.length;
int maxDisplayItems = 0;
List<double> dynamicItemsWidth = []; //if want to use dynamic width
if (useFixedWidth) {
//if want to use fixed width
maxDisplayItems =
(((constraints.maxWidth - labelWidth) / itemWidth).floor()).clamp(
0, totalItems); //check how many items fit including the label
} else {
//if want to calculate based on string length
dynamicItemsWidth = items
.map((e) => e.length * letterWidth)
.toList(); //calculate individual item width
double _acumWidth = 0.0;
for (var width in dynamicItemsWidth) {
_acumWidth = _acumWidth width;
if (_acumWidth < (constraints.maxWidth - labelWidth)) {
maxDisplayItems ;
}
}
}
bool showPlusSign =
maxDisplayItems < totalItems; //check if all items can be shown
return Row(children: [
Row(
children: List.generate(maxDisplayItems, (index) {
return SizedBox(
height: itemWidth,
width: useFixedWidth ? itemWidth : dynamicItemsWidth[index],
child: Container(
//color: Colors.red,
//width: itemWidth,
child: Center(child: Text('Name ${index 1}'))));
}).toList()),
if (showPlusSign)
SizedBox(
width: labelWidth,
height: itemWidth,
child: Center(child: Text(' ${totalItems - maxDisplayItems}')))
]);
});
}
}
shows this dynamic layout for 10 items:
CodePudding user response:
https://pub.dev/packages/auto_size_text
Please use this package and it will resize the text based on the available space
AutoSizeText(
'Name1, Name2, 3',
style: TextStyle(fontSize: 20),
maxLines: 1,
)