Upgrade dependencies and fix lints
Remove unnecessary floats
Revert bottomnavybar version
Tidy up to wrap in 80 chars
Use final where possible
Add test for implicit dynamic
Remove lint rules that are already in pedantic
Minor idiomatic changes
Replace implicit dynamic lists with List<Object>
Improve inclusive language
Clean up naming
Grammar cleanup on property validation text
Prefer final locals
Minor cleanup
Showing 2 of 24 files from the diff.
lib/src/auto_size_group.dart
changed.
lib/src/auto_size_text.dart
changed.
Other files ignored by Codecov
test/utils.dart
has changed.
pubspec.yaml
has changed.
demo/lib/sync_demo.dart
has changed.
demo/lib/step_granularity.dart
has changed.
demo/lib/overflow_replacement_demo.dart
has changed.
test/group_test.dart
has changed.
test/text_fits_test.dart
has changed.
test/basic_test.dart
has changed.
analysis_options.yaml
has changed.
example/main.dart
has changed.
demo/lib/preset_font_sizes_demo.dart
has changed.
test/wrap_words_test.dart
has changed.
demo/lib/min_font_size_demo.dart
has changed.
demo/lib/animated_input.dart
has changed.
example/pubspec.yaml
has changed.
lib/auto_size_text.dart
has changed.
demo/lib/text_card.dart
has changed.
demo/lib/max_lines_demo.dart
has changed.
demo/lib/utils.dart
has changed.
test/overflow_replacement_test.dart
has changed.
demo/pubspec.yaml
has changed.
demo/lib/main.dart
has changed.
@@ -4,21 +4,21 @@
Loading
4 | 4 | class AutoSizeGroup { |
|
5 | 5 | final _listeners = <_AutoSizeTextState, double>{}; |
|
6 | 6 | var _widgetsNotified = false; |
|
7 | - | double _fontSize = double.infinity; |
|
7 | + | var _fontSize = double.infinity; |
|
8 | 8 | ||
9 | - | _register(_AutoSizeTextState text) { |
|
9 | + | void _register(_AutoSizeTextState text) { |
|
10 | 10 | _listeners[text] = double.infinity; |
|
11 | 11 | } |
|
12 | 12 | ||
13 | - | _updateFontSize(_AutoSizeTextState text, double maxFontSize) { |
|
14 | - | var oldFontSize = _fontSize; |
|
13 | + | void _updateFontSize(_AutoSizeTextState text, double maxFontSize) { |
|
14 | + | final oldFontSize = _fontSize; |
|
15 | 15 | if (maxFontSize <= _fontSize) { |
|
16 | 16 | _fontSize = maxFontSize; |
|
17 | 17 | _listeners[text] = maxFontSize; |
|
18 | 18 | } else if (_listeners[text] == _fontSize) { |
|
19 | 19 | _listeners[text] = maxFontSize; |
|
20 | 20 | _fontSize = double.infinity; |
|
21 | - | for (var size in _listeners.values) { |
|
21 | + | for (final size in _listeners.values) { |
|
22 | 22 | if (size < _fontSize) _fontSize = size; |
|
23 | 23 | } |
|
24 | 24 | } else { |
@@ -31,21 +31,21 @@
Loading
31 | 31 | } |
|
32 | 32 | } |
|
33 | 33 | ||
34 | - | _notifyListeners() { |
|
34 | + | void _notifyListeners() { |
|
35 | 35 | if (_widgetsNotified) { |
|
36 | 36 | return; |
|
37 | 37 | } else { |
|
38 | 38 | _widgetsNotified = true; |
|
39 | 39 | } |
|
40 | 40 | ||
41 | - | for (var textState in _listeners.keys) { |
|
41 | + | for (final textState in _listeners.keys) { |
|
42 | 42 | if (textState.mounted) { |
|
43 | 43 | textState._notifySync(); |
|
44 | 44 | } |
|
45 | 45 | } |
|
46 | 46 | } |
|
47 | 47 | ||
48 | - | _remove(_AutoSizeTextState text) { |
|
48 | + | void _remove(_AutoSizeTextState text) { |
|
49 | 49 | _updateFontSize(text, double.infinity); |
|
50 | 50 | _listeners.remove(text); |
|
51 | 51 | } |
@@ -1,6 +1,7 @@
Loading
1 | 1 | part of auto_size_text; |
|
2 | 2 | ||
3 | - | /// Flutter widget that automatically resizes text to fit perfectly within its bounds. |
|
3 | + | /// Flutter widget that automatically resizes text to fit perfectly within its |
|
4 | + | /// bounds. |
|
4 | 5 | /// |
|
5 | 6 | /// All size constraints as well as maxLines are taken into account. If the text |
|
6 | 7 | /// overflows anyway, you should check if the parent widget actually constraints |
@@ -80,22 +81,22 @@
Loading
80 | 81 | ||
81 | 82 | /// If non-null, the style to use for this text. |
|
82 | 83 | /// |
|
83 | - | /// If the style's 'inherit' property is true, the style will be merged with |
|
84 | + | /// If the style's "inherit" property is true, the style will be merged with |
|
84 | 85 | /// the closest enclosing [DefaultTextStyle]. Otherwise, the style will |
|
85 | 86 | /// replace the closest enclosing [DefaultTextStyle]. |
|
86 | 87 | final TextStyle style; |
|
87 | 88 | ||
88 | 89 | // The default font size if none is specified. |
|
89 | - | static const double _defaultFontSize = 14.0; |
|
90 | + | static const double _defaultFontSize = 14; |
|
90 | 91 | ||
91 | 92 | /// The strut style to use. Strut style defines the strut, which sets minimum |
|
92 | 93 | /// vertical layout metrics. |
|
93 | 94 | /// |
|
94 | 95 | /// Omitting or providing null will disable strut. |
|
95 | 96 | /// |
|
96 | - | /// Omitting or providing null for any properties of [StrutStyle] will result in |
|
97 | - | /// default values being used. It is highly recommended to at least specify a |
|
98 | - | /// font size. |
|
97 | + | /// Omitting or providing null for any properties of [StrutStyle] will result |
|
98 | + | /// in default values being used. It is highly recommended to at least specify |
|
99 | + | /// a font size. |
|
99 | 100 | /// |
|
100 | 101 | /// See [StrutStyle] for details. |
|
101 | 102 | final StrutStyle strutStyle; |
@@ -171,6 +172,8 @@
Loading
171 | 172 | final bool wrapWords; |
|
172 | 173 | ||
173 | 174 | /// How visual overflow should be handled. |
|
175 | + | /// |
|
176 | + | /// Defaults to retrieving the value from the nearest [DefaultTextStyle] ancestor. |
|
174 | 177 | final TextOverflow overflow; |
|
175 | 178 | ||
176 | 179 | /// If the text is overflowing and does not fit its bounds, this widget is |
@@ -212,7 +215,7 @@
Loading
212 | 215 | /// text value: |
|
213 | 216 | /// |
|
214 | 217 | /// ```dart |
|
215 | - | /// Text(r'$$', semanticsLabel: 'Double dollars') |
|
218 | + | /// AutoSizeText(r'$$', semanticsLabel: 'Double dollars') |
|
216 | 219 | /// ``` |
|
217 | 220 | final String semanticsLabel; |
|
218 | 221 |
@@ -222,7 +225,7 @@
Loading
222 | 225 | ||
223 | 226 | class _AutoSizeTextState extends State<AutoSizeText> { |
|
224 | 227 | @override |
|
225 | - | initState() { |
|
228 | + | void initState() { |
|
226 | 229 | super.initState(); |
|
227 | 230 | ||
228 | 231 | if (widget.group != null) { |
@@ -243,7 +246,7 @@
Loading
243 | 246 | @override |
|
244 | 247 | Widget build(BuildContext context) { |
|
245 | 248 | return LayoutBuilder(builder: (context, size) { |
|
246 | - | var defaultTextStyle = DefaultTextStyle.of(context); |
|
249 | + | final defaultTextStyle = DefaultTextStyle.of(context); |
|
247 | 250 | ||
248 | 251 | var style = widget.style; |
|
249 | 252 | if (widget.style == null || widget.style.inherit) { |
@@ -253,13 +256,13 @@
Loading
253 | 256 | style = style.copyWith(fontSize: AutoSizeText._defaultFontSize); |
|
254 | 257 | } |
|
255 | 258 | ||
256 | - | var maxLines = widget.maxLines ?? defaultTextStyle.maxLines; |
|
259 | + | final maxLines = widget.maxLines ?? defaultTextStyle.maxLines; |
|
257 | 260 | ||
258 | - | _sanityCheck(style, maxLines); |
|
261 | + | _validateProperties(style, maxLines); |
|
259 | 262 | ||
260 | - | var result = _calculateFontSize(size, style, maxLines); |
|
261 | - | var fontSize = result[0] as double; |
|
262 | - | var textFits = result[1] as bool; |
|
263 | + | final result = _calculateFontSize(size, style, maxLines); |
|
264 | + | final fontSize = result[0] as double; |
|
265 | + | final textFits = result[1] as bool; |
|
263 | 266 | ||
264 | 267 | Widget text; |
|
265 | 268 |
@@ -278,55 +281,57 @@
Loading
278 | 281 | }); |
|
279 | 282 | } |
|
280 | 283 | ||
281 | - | void _sanityCheck(TextStyle style, int maxLines) { |
|
284 | + | void _validateProperties(TextStyle style, int maxLines) { |
|
282 | 285 | assert(widget.overflow == null || widget.overflowReplacement == null, |
|
283 | - | 'Either overflow or overflowReplacement have to be null.'); |
|
286 | + | 'Either overflow or overflowReplacement must be null.'); |
|
284 | 287 | assert(maxLines == null || maxLines > 0, |
|
285 | - | 'MaxLines has to be grater than or equal to 1.'); |
|
288 | + | 'MaxLines must be greater than or equal to 1.'); |
|
286 | 289 | assert(widget.key == null || widget.key != widget.textKey, |
|
287 | - | 'Key and textKey cannot be the same.'); |
|
290 | + | 'Key and textKey must not be equal.'); |
|
288 | 291 | ||
289 | 292 | if (widget.presetFontSizes == null) { |
|
290 | - | assert(widget.stepGranularity >= 0.1, |
|
291 | - | 'StepGranularity has to be greater than or equal to 0.1. It is not a good idea to resize the font with a higher accuracy.'); |
|
293 | + | assert( |
|
294 | + | widget.stepGranularity >= 0.1, |
|
295 | + | 'StepGranularity must be greater than or equal to 0.1. It is not a ' |
|
296 | + | 'good idea to resize the font with a higher accuracy.'); |
|
292 | 297 | assert(widget.minFontSize >= 0, |
|
293 | - | 'MinFontSize has to be greater than or equal to 0.'); |
|
298 | + | 'MinFontSize must be greater than or equal to 0.'); |
|
294 | 299 | assert(widget.maxFontSize > 0, 'MaxFontSize has to be greater than 0.'); |
|
295 | 300 | assert(widget.minFontSize <= widget.maxFontSize, |
|
296 | - | 'MinFontSize has to be smaller or equal than maxFontSize.'); |
|
301 | + | 'MinFontSize must be smaller or equal than maxFontSize.'); |
|
297 | 302 | assert(widget.minFontSize / widget.stepGranularity % 1 == 0, |
|
298 | - | 'MinFontSize has to be multiples of stepGranularity.'); |
|
303 | + | 'MinFontSize must be a multiple of stepGranularity.'); |
|
299 | 304 | if (widget.maxFontSize != double.infinity) { |
|
300 | 305 | assert(widget.maxFontSize / widget.stepGranularity % 1 == 0, |
|
301 | - | 'MaxFontSize has to be multiples of stepGranularity.'); |
|
306 | + | 'MaxFontSize must be a multiple of stepGranularity.'); |
|
302 | 307 | } |
|
303 | 308 | } else { |
|
304 | 309 | assert(widget.presetFontSizes.isNotEmpty, |
|
305 | - | 'PresetFontSizes has to be nonempty.'); |
|
310 | + | 'PresetFontSizes must not be empty.'); |
|
306 | 311 | } |
|
307 | 312 | } |
|
308 | 313 | ||
309 | 314 | List _calculateFontSize(BoxConstraints size, TextStyle style, int maxLines) { |
|
310 | - | var span = TextSpan( |
|
315 | + | final span = TextSpan( |
|
311 | 316 | style: widget.textSpan?.style ?? style, |
|
312 | 317 | text: widget.textSpan?.text ?? widget.data, |
|
313 | 318 | children: widget.textSpan?.children, |
|
314 | 319 | recognizer: widget.textSpan?.recognizer, |
|
315 | 320 | ); |
|
316 | 321 | ||
317 | - | var userScale = |
|
322 | + | final userScale = |
|
318 | 323 | widget.textScaleFactor ?? MediaQuery.textScaleFactorOf(context); |
|
319 | 324 | ||
320 | 325 | int left; |
|
321 | 326 | int right; |
|
322 | 327 | ||
323 | - | var presetFontSizes = widget.presetFontSizes?.reversed?.toList(); |
|
328 | + | final presetFontSizes = widget.presetFontSizes?.reversed?.toList(); |
|
324 | 329 | if (presetFontSizes == null) { |
|
325 | - | var defaultFontSize = |
|
330 | + | final defaultFontSize = |
|
326 | 331 | style.fontSize.clamp(widget.minFontSize, widget.maxFontSize); |
|
327 | - | var defaultScale = defaultFontSize * userScale / style.fontSize; |
|
332 | + | final defaultScale = defaultFontSize * userScale / style.fontSize; |
|
328 | 333 | if (_checkTextFits(span, defaultScale, maxLines, size)) { |
|
329 | - | return [defaultFontSize * userScale, true]; |
|
334 | + | return <Object>[defaultFontSize * userScale, true]; |
|
330 | 335 | } |
|
331 | 336 | ||
332 | 337 | left = (widget.minFontSize / widget.stepGranularity).floor(); |
@@ -338,7 +343,7 @@
Loading
338 | 343 | ||
339 | 344 | var lastValueFits = false; |
|
340 | 345 | while (left <= right) { |
|
341 | - | var mid = (left + (right - left) / 2).toInt(); |
|
346 | + | final mid = (left + (right - left) / 2).floor(); |
|
342 | 347 | double scale; |
|
343 | 348 | if (presetFontSizes == null) { |
|
344 | 349 | scale = mid * userScale * widget.stepGranularity / style.fontSize; |
@@ -364,15 +369,15 @@
Loading
364 | 369 | fontSize = presetFontSizes[right] * userScale; |
|
365 | 370 | } |
|
366 | 371 | ||
367 | - | return [fontSize, lastValueFits]; |
|
372 | + | return <Object>[fontSize, lastValueFits]; |
|
368 | 373 | } |
|
369 | 374 | ||
370 | 375 | bool _checkTextFits( |
|
371 | 376 | TextSpan text, double scale, int maxLines, BoxConstraints constraints) { |
|
372 | 377 | if (!widget.wrapWords) { |
|
373 | - | var words = text.toPlainText().split(RegExp('\\s+')); |
|
378 | + | final words = text.toPlainText().split(RegExp('\\s+')); |
|
374 | 379 | ||
375 | - | var wordWrapTp = TextPainter( |
|
380 | + | final wordWrapTextPainter = TextPainter( |
|
376 | 381 | text: TextSpan( |
|
377 | 382 | style: text.style, |
|
378 | 383 | text: words.join('\n'), |
@@ -385,15 +390,15 @@
Loading
385 | 390 | strutStyle: widget.strutStyle, |
|
386 | 391 | ); |
|
387 | 392 | ||
388 | - | wordWrapTp.layout(maxWidth: constraints.maxWidth); |
|
393 | + | wordWrapTextPainter.layout(maxWidth: constraints.maxWidth); |
|
389 | 394 | ||
390 | - | if (wordWrapTp.didExceedMaxLines || |
|
391 | - | wordWrapTp.width > constraints.maxWidth) { |
|
395 | + | if (wordWrapTextPainter.didExceedMaxLines || |
|
396 | + | wordWrapTextPainter.width > constraints.maxWidth) { |
|
392 | 397 | return false; |
|
393 | 398 | } |
|
394 | 399 | } |
|
395 | 400 | ||
396 | - | var tp = TextPainter( |
|
401 | + | final textPainter = TextPainter( |
|
397 | 402 | text: text, |
|
398 | 403 | textAlign: widget.textAlign ?? TextAlign.left, |
|
399 | 404 | textDirection: widget.textDirection ?? TextDirection.ltr, |
@@ -403,11 +408,11 @@
Loading
403 | 408 | strutStyle: widget.strutStyle, |
|
404 | 409 | ); |
|
405 | 410 | ||
406 | - | tp.layout(maxWidth: constraints.maxWidth); |
|
411 | + | textPainter.layout(maxWidth: constraints.maxWidth); |
|
407 | 412 | ||
408 | - | return !(tp.didExceedMaxLines || |
|
409 | - | tp.height > constraints.maxHeight || |
|
410 | - | tp.width > constraints.maxWidth); |
|
413 | + | return !(textPainter.didExceedMaxLines || |
|
414 | + | textPainter.height > constraints.maxHeight || |
|
415 | + | textPainter.width > constraints.maxWidth); |
|
411 | 416 | } |
|
412 | 417 | ||
413 | 418 | Widget _buildText(double fontSize, TextStyle style, int maxLines) { |
Files | Coverage |
---|---|
lib/src | 98.70% |
Project Totals (2 files) | 98.70% |
381892867
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file.
The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files.
The size and color of each slice is representing the number of statements and the coverage, respectively.