I have a Wrap
widget that wraps three InkWell
. Each InkWell contains a Text
widget. They are meant to be like TabBars to filter my ListView data. When a tab is selected, its FontWeight
property is set to bold (w700), when it's not selected, it becomes normal weight.
Here is my code:
Align(
alignment: Alignment.topLeft,
child: Wrap(
spacing: 8,
runSpacing: 8,
children: [
InkWell(
borderRadius: BorderRadius.circular(24),
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 16, vertical: 8),
decoration: ShapeDecoration(
color: semuaKolamBackgroundColor,
shape: RoundedRectangleBorder(
side: BorderSide(
width: 0.8,
style: BorderStyle.solid,
color: semuaKolamBorderColor),
borderRadius: BorderRadius.all(Radius.circular(24.0)),
),
),
child: Text(
"Semua",
style: TextStyle(
fontFamily: "NotoSans", color: semuaKolamTextColor,
fontWeight: _selectedJenisKolam == 0 ? FontWeight.w700 : FontWeight.normal),
),
),
onTap: () {
if (_selectedJenisKolam != 0) {
setState(() {
_selectedJenisKolam = 0;
changeKolamType(0);
});
}
},
),
InkWell(
borderRadius: BorderRadius.circular(24),
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 16, vertical: 8),
decoration: ShapeDecoration(
color: kolamNormalBackgroundColor,
shape: RoundedRectangleBorder(
side: BorderSide(
width: 0.8,
style: BorderStyle.solid,
color: kolamNormalBorderColor),
borderRadius: BorderRadius.all(Radius.circular(24.0)),
),
),
child: Text(
"Kolam Normal",
style: TextStyle(
fontFamily: "NotoSans",
color: kolamNormalTextColor,
fontWeight: _selectedJenisKolam == 1 ? FontWeight.w700 : FontWeight.normal),
),
),
onTap: () {
if (_selectedJenisKolam != 1) {
setState(() {
_selectedJenisKolam = 1;
changeKolamType(1);
});
}
},
),
InkWell(
borderRadius: BorderRadius.circular(24),
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 16, vertical: 8),
decoration: ShapeDecoration(
color: kolamKendalaBackgroundColor,
shape: RoundedRectangleBorder(
side: BorderSide(
width: 0.8,
style: BorderStyle.solid,
color: kolamKendalaBorderColor),
borderRadius:
BorderRadius.all(Radius.circular(24.0)),
),
),
child: Text(
"Kolam Kendala",
style: TextStyle(
fontFamily: "NotoSans",
color: kolamKendalaTextColor,
fontWeight: _selectedJenisKolam == 2 ? FontWeight.w700 : FontWeight.normal),
)),
onTap: () {
if (_selectedJenisKolam != 2) {
setState(() {
_selectedJenisKolam = 2;
changeKolamType(2);
});
}
},
)
],
),
),
Problem is whenever I move from first tab Semua
to other tab, the first tab width size is getting decreased (wrap content).
It is not clear to see with screenshots. But what actually happening is Kolam Normal
tab moved a little to left because Semua
tab is getting smaller.
CodePudding user response:
This requires you to specify a width
to your Container
. But as you probably want a way where the Container
always follows the length of text, the code below will solve your issue.
The solution requires you to use the TextPainter
to calculate the width that the text would require post build, and we use the style of the higher fontWeight to take the max width and make a constant for both weights (as seen in the style provided to the span
in the LayoutBuilder
). To use this calculated value almost immediately, we use the LayoutBuilder
Also its not good practice to repeat similar widgets as you've done in your question, but instead to create a function to reproduce them with different variables (also shown in code)
Widget returnNewThing() {
return Align(
alignment: Alignment.topLeft,
child: Wrap(
spacing: 8,
runSpacing: 8,
children: [
// add the colors and other params into the method if needed
createInkWell(buttonText: 'Semua', currentIndex: 0),
createInkWell(buttonText: 'Kolam Normal', currentIndex: 1),
createInkWell(buttonText: 'Kolam Kendala', currentIndex: 2),
],
),
);
}
InkWell createInkWell(
{Color shapeColor = kolanNormalBackgroundColor,
Color borderColor = kolanNormalBorderColor,
required String buttonText,
required int currentIndex,
Color textColor = kolamNormalTextColor}) {
return InkWell(
borderRadius: BorderRadius.circular(24),
child: LayoutBuilder(builder: (context, size) {
final span = TextSpan(text: buttonText, style: TextStyle(
fontFamily: "NotoSans",
color: textColor,
fontWeight: FontWeight.w700));
final tp = TextPainter(
text: span,
textDirection: TextDirection.ltr,
textAlign: TextAlign.start,
maxLines: 1)
..layout(maxWidth: size.maxWidth);
var widthNeeded = tp.width; //may need to add some padding i.e. 4
return Container(
width: widthNeeded,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: ShapeDecoration(
color: shapeColor,
shape: RoundedRectangleBorder(
side: BorderSide(
width: 0.8, style: BorderStyle.solid, color: borderColor),
borderRadius: BorderRadius.all(Radius.circular(24.0)),
),
),
child: Text(
buttonText,
style: TextStyle(
fontFamily: "NotoSans",
color: textColor,
fontWeight: _selectedJenisKolam == currentIndex
? FontWeight.w700
: FontWeight.normal),
),
);
}),
onTap: () {
if (_selectedJenisKolam != currentIndex) {
setState(() {
_selectedJenisKolam = currentIndex;
changeKolamType(currentIndex);
});
}
},
);
}