diff --git a/packages/flutter/lib/src/rendering/paragraph.dart b/packages/flutter/lib/src/rendering/paragraph.dart index cc3407fa3fe..7f0fc516076 100644 --- a/packages/flutter/lib/src/rendering/paragraph.dart +++ b/packages/flutter/lib/src/rendering/paragraph.dart @@ -25,6 +25,9 @@ enum TextOverflow { /// Use an ellipsis to indicate that the text has overflowed. ellipsis, + + /// Render overflowing text outside of its container. + visible, } const String _kEllipsis = '\u2026'; @@ -268,7 +271,7 @@ class RenderParagraph extends RenderBox { span?.recognizer?.addPointer(event); } - bool _hasVisualOverflow = false; + bool _needsClipping = false; ui.Shader _overflowShader; /// Whether this paragraph currently has a [dart:ui.Shader] for its overflow @@ -297,15 +300,21 @@ class RenderParagraph extends RenderBox { // visual overflow when there actually is visual overflow. This can become // a problem if we start having horizontal overflow and introduce a clip // that affects the actual (but undetected) vertical overflow. - _hasVisualOverflow = didOverflowWidth || didOverflowHeight; - if (_hasVisualOverflow) { + final bool hasVisualOverflow = didOverflowWidth || didOverflowHeight; + if (hasVisualOverflow) { switch (_overflow) { + case TextOverflow.visible: + _needsClipping = false; + _overflowShader = null; + break; case TextOverflow.clip: case TextOverflow.ellipsis: + _needsClipping = true; _overflowShader = null; break; case TextOverflow.fade: assert(textDirection != null); + _needsClipping = true; final TextPainter fadeSizePainter = TextPainter( text: TextSpan(style: _textPainter.text.style, text: '\u2026'), textDirection: textDirection, @@ -341,6 +350,7 @@ class RenderParagraph extends RenderBox { break; } } else { + _needsClipping = false; _overflowShader = null; } } @@ -369,7 +379,7 @@ class RenderParagraph extends RenderBox { return true; }()); - if (_hasVisualOverflow) { + if (_needsClipping) { final Rect bounds = offset & size; if (_overflowShader != null) { // This layer limits what the shader below blends with to be just the text @@ -381,7 +391,7 @@ class RenderParagraph extends RenderBox { canvas.clipRect(bounds); } _textPainter.paint(canvas, offset); - if (_hasVisualOverflow) { + if (_needsClipping) { if (_overflowShader != null) { canvas.translate(offset.dx, offset.dy); final Paint paint = Paint() diff --git a/packages/flutter/lib/src/widgets/icon.dart b/packages/flutter/lib/src/widgets/icon.dart index 459f922ada3..c1d12a86d2e 100644 --- a/packages/flutter/lib/src/widgets/icon.dart +++ b/packages/flutter/lib/src/widgets/icon.dart @@ -21,10 +21,13 @@ import 'icon_theme_data.dart'; /// Typically this is introduced automatically by the [WidgetsApp] or /// [MaterialApp]. /// +/// This widget assumes that the rendered icon is squared. Non-squared icons may +/// render incorrectly. +/// /// {@tool sample} /// /// This example shows how to use [Icon] to create an addition icon, in the -/// color pink, and 30 pixels in size. +/// color pink, and 30 x 30 pixels in size. /// /// ```dart /// Icon( @@ -148,6 +151,7 @@ class Icon extends StatelessWidget { iconColor = iconColor.withOpacity(iconColor.opacity * iconOpacity); Widget iconWidget = RichText( + overflow: TextOverflow.visible, // Never clip. textDirection: textDirection, // Since we already fetched it for the assert... text: TextSpan( text: String.fromCharCode(icon.codePoint), diff --git a/packages/flutter/test/widgets/text_test.dart b/packages/flutter/test/widgets/text_test.dart index a519c84a4bf..504ddadced7 100644 --- a/packages/flutter/test/widgets/text_test.dart +++ b/packages/flutter/test/widgets/text_test.dart @@ -298,6 +298,26 @@ void main() { expect(find.byType(Text), isNot(paints..clipRect())); }); + + testWidgets('Overflow is clipping correctly - long text with overflow: visible', (WidgetTester tester) async { + await _pumpTextWidget( + tester: tester, + overflow: TextOverflow.visible, + text: 'a long long long long text, should be clip', + ); + + expect(find.byType(Text), isNot(paints..clipRect())); + }); + + testWidgets('Overflow is clipping correctly - short text with overflow: visible', (WidgetTester tester) async { + await _pumpTextWidget( + tester: tester, + overflow: TextOverflow.visible, + text: 'Hi', + ); + + expect(find.byType(Text), isNot(paints..clipRect())); + }); } Future _pumpTextWidget({ WidgetTester tester, String text, TextOverflow overflow }) {