selection_action_button_widget.dart 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import "package:flutter/material.dart";
  2. import "package:photos/theme/ente_theme.dart";
  3. class SelectionActionButton extends StatefulWidget {
  4. final String labelText;
  5. final IconData icon;
  6. final VoidCallback? onTap;
  7. const SelectionActionButton({
  8. required this.labelText,
  9. required this.icon,
  10. required this.onTap,
  11. super.key,
  12. });
  13. @override
  14. State<SelectionActionButton> createState() => _SelectionActionButtonState();
  15. }
  16. class _SelectionActionButtonState extends State<SelectionActionButton> {
  17. static const minWidth = 64.0;
  18. late double widthOfButton;
  19. Color? backgroundColor;
  20. @override
  21. Widget build(BuildContext context) {
  22. widthOfButton = getWidthOfButton();
  23. final colorScheme = getEnteColorScheme(context);
  24. return GestureDetector(
  25. onTap: widget.onTap,
  26. onTapDown: (details) {
  27. setState(() {
  28. backgroundColor = colorScheme.fillFaintPressed;
  29. });
  30. },
  31. onTapUp: (details) {
  32. setState(() {
  33. backgroundColor = null;
  34. });
  35. },
  36. onTapCancel: () {
  37. setState(() {
  38. backgroundColor = null;
  39. });
  40. },
  41. child: Container(
  42. decoration: BoxDecoration(
  43. borderRadius: BorderRadius.circular(8),
  44. color: backgroundColor,
  45. ),
  46. child: Padding(
  47. padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 8),
  48. child: SizedBox(
  49. width: widthOfButton,
  50. child: Column(
  51. mainAxisAlignment: MainAxisAlignment.center,
  52. mainAxisSize: MainAxisSize.min,
  53. children: [
  54. Icon(
  55. widget.icon,
  56. size: 24,
  57. color: getEnteColorScheme(context).textMuted,
  58. ),
  59. const SizedBox(height: 4),
  60. Text(
  61. widget.labelText,
  62. textAlign: TextAlign.center,
  63. //textTheme in [getWidthOfLongestWord] should be same as this
  64. style: getEnteTextTheme(context).miniMuted,
  65. ),
  66. ],
  67. ),
  68. ),
  69. ),
  70. ),
  71. );
  72. }
  73. getWidthOfButton() {
  74. final widthOfWidestWord = getWidthOfWidestWord(
  75. widget.labelText,
  76. );
  77. if (widthOfWidestWord > minWidth) return widthOfWidestWord;
  78. return minWidth;
  79. }
  80. double computeWidthOfWord(String text, TextStyle style) {
  81. final textPainter = TextPainter(
  82. text: TextSpan(text: text, style: style),
  83. maxLines: 1,
  84. textDirection: TextDirection.ltr,
  85. textScaleFactor: MediaQuery.of(context).textScaleFactor,
  86. )..layout();
  87. return textPainter.size.width;
  88. }
  89. double getWidthOfWidestWord(String labelText) {
  90. final words = labelText.split(RegExp(r'\s+'));
  91. if (words.isEmpty) return 0.0;
  92. double maxWidth = 0.0;
  93. for (String word in words) {
  94. final width =
  95. computeWidthOfWord(word, getEnteTextTheme(context).miniMuted);
  96. if (width > maxWidth) {
  97. maxWidth = width;
  98. }
  99. }
  100. return maxWidth;
  101. }
  102. }