refactor size calculation

This commit is contained in:
Fabian Freund
2025-07-30 22:05:25 +02:00
parent 6bc93f7b7d
commit 28a8588051
2 changed files with 49 additions and 40 deletions
@@ -21,6 +21,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:nullability/nullability.dart'; import 'package:nullability/nullability.dart';
import 'package:weblibre/utils/text_field_line_count.dart';
class AutoSuggestTextField extends HookWidget { class AutoSuggestTextField extends HookWidget {
final TextEditingController controller; final TextEditingController controller;
@@ -83,54 +84,26 @@ class AutoSuggestTextField extends HookWidget {
controller.text.isNotEmpty && controller.text.isNotEmpty &&
suggestion!.startsWith(controller.text); suggestion!.startsWith(controller.text);
static int _getLineCountUsingBoxes(
String text,
TextStyle style,
double maxWidth,
) {
final textSpan = TextSpan(text: text, style: style);
final textPainter = TextPainter(
text: textSpan,
textDirection: TextDirection.ltr,
);
textPainter.layout(maxWidth: maxWidth);
// Select all text
final selection = TextSelection(baseOffset: 0, extentOffset: text.length);
// Each box represents one line
final lines = textPainter.getBoxesForSelection(selection);
return lines.length;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final textFieldKey = useMemoized(() => GlobalKey()); final textFieldKey = useMemoized(() => GlobalKey());
final showSuggestion = useListenableSelector(controller, () { final showSuggestion = useListenableSelector(controller, () {
if (maxLines != 1) { if (maxLines != 1) {
final box = textFieldKey.currentContext?.findRenderObject(); final lines = getTextFieldLineCount(
if (box case final RenderBox box) { textFieldKey,
final width = box.size.width; controller.text,
style ?? Theme.of(context).textTheme.bodyLarge!,
final lines = _getLineCountUsingBoxes( );
controller.text, final suggestionLines = suggestion.mapNotNull(
(suggestion) => getTextFieldLineCount(
textFieldKey,
suggestion,
style ?? Theme.of(context).textTheme.bodyLarge!, style ?? Theme.of(context).textTheme.bodyLarge!,
width, ),
); );
final suggestionLines = suggestion.mapNotNull( return lines == 1 && suggestionLines == 1;
(suggestion) => _getLineCountUsingBoxes(
suggestion,
style ?? Theme.of(context).textTheme.bodyLarge!,
width,
),
);
return lines == 1 && suggestionLines == 1;
}
} }
return true; return true;
@@ -149,6 +122,12 @@ class AutoSuggestTextField extends HookWidget {
decoration: baseDecoration.copyWith( decoration: baseDecoration.copyWith(
floatingLabelBehavior: FloatingLabelBehavior.never, floatingLabelBehavior: FloatingLabelBehavior.never,
border: InputBorder.none, border: InputBorder.none,
suffixIcon: baseDecoration.suffixIcon.mapNotNull(
(_) => const SizedBox.square(dimension: 48),
),
prefixIcon: baseDecoration.prefixIcon.mapNotNull(
(_) => const SizedBox.square(dimension: 48),
),
label: HookBuilder( label: HookBuilder(
builder: (context) { builder: (context) {
final text = useListenableSelector( final text = useListenableSelector(
+30
View File
@@ -0,0 +1,30 @@
import 'package:flutter/material.dart';
int _getLineCountUsingBoxes(String text, TextStyle style, double maxWidth) {
final textSpan = TextSpan(text: text, style: style);
final textPainter = TextPainter(
text: textSpan,
textDirection: TextDirection.ltr,
);
textPainter.layout(maxWidth: maxWidth);
// Select all text
final selection = TextSelection(baseOffset: 0, extentOffset: text.length);
// Each box represents one line
final lines = textPainter.getBoxesForSelection(selection);
return lines.length;
}
int? getTextFieldLineCount(GlobalKey key, String text, TextStyle style) {
final box = key.currentContext?.findRenderObject();
if (box case final RenderBox box) {
final width = box.size.width;
return _getLineCountUsingBoxes(text, style, width);
}
return null;
}