Unverified Commit 528a281a authored by hangyu's avatar hangyu Committed by GitHub

Update alwaysNeedsCompositing in RenderParagraph (#135076)

fix #111370

According to 

https://github.com/flutter/flutter/blob/5b47fef613e2d74ae44e1e22c2a3495294db180e/packages/flutter/lib/src/rendering/box.dart#L1259
: A [RenderBox] that uses methods on [PaintingContext] that introduce
new
/// layers should override the [alwaysNeedsCompositing] getter and set
it to
/// true.

set [alwaysNeedsCompositing] to true when RenderParagraph introduces
LeaderLayer for selection handles.



## Pre-launch Checklist

- [ ] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [ ] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [ ] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [ ] I signed the [CLA].
- [ ] I listed at least one issue that this PR fixes in the description
above.
- [ ] I updated/added relevant documentation (doc comments with `///`).
- [ ] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [ ] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#overview
[Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene
[test-exempt]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes
[Discord]: https://github.com/flutter/flutter/wiki/Chat
parent 45e4a0e5
......@@ -388,6 +388,9 @@ class RenderParagraph extends RenderBox with ContainerRenderObjectMixin<RenderBo
}
_lastSelectableFragments ??= _getSelectableFragments();
_lastSelectableFragments!.forEach(_registrar!.add);
if (_lastSelectableFragments!.isNotEmpty) {
markNeedsCompositingBitsUpdate();
}
}
void _removeSelectionRegistrarSubscription() {
......@@ -425,6 +428,9 @@ class RenderParagraph extends RenderBox with ContainerRenderObjectMixin<RenderBo
_lastSelectableFragments = null;
}
@override
bool get alwaysNeedsCompositing => _lastSelectableFragments?.isNotEmpty ?? false;
@override
void markNeedsLayout() {
_lastSelectableFragments?.forEach((_SelectableFragment element) => element.didChangeParagraphLayout());
......
......@@ -70,6 +70,63 @@ void main() {
expect(tester.takeException(), isNull);
});
// Regression test for https://github.com/flutter/flutter/issues/111370
testWidgetsWithLeakTracking('Handle is correctly transformed when the text is inside of a FittedBox ',(WidgetTester tester) async {
final Key textKey = UniqueKey();
await tester.pumpWidget(
MaterialApp(
color: const Color(0xFF2196F3),
home: Scaffold(
body: SelectionArea(
child: SizedBox(
height: 100,
child: FittedBox(
fit: BoxFit.fill,
child: Text('test', key: textKey),
),
),
),
),
),
);
final TestGesture longpress = await tester.startGesture(const Offset(10, 10));
addTearDown(longpress.removePointer);
await tester.pump(const Duration(milliseconds: 500));
await longpress.up();
// Text box is scaled by 5.
final RenderBox textBox = tester.firstRenderObject(find.byKey(textKey));
expect(textBox.size.height, 20.0);
final Offset textPoint = textBox.localToGlobal(const Offset(0, 20));
expect(textPoint, equals(const Offset(0, 100)));
// Find handles and verify their sizes.
expect(find.byType(Overlay), findsOneWidget);
expect(find.descendant(of: find.byType(Overlay),matching: find.byType(CustomPaint),),findsNWidgets(2));
final Iterable<RenderBox> handles = tester.renderObjectList(find.descendant(
of: find.byType(Overlay),
matching: find.byType(CustomPaint),
));
// The handle height is determined by the formula:
// textLineHeight + _kSelectionHandleRadius * 2 - _kSelectionHandleOverlap .
// The text line height will be the value of the fontSize.
// The constant _kSelectionHandleRadius has the value of 6.
// The constant _kSelectionHandleOverlap has the value of 1.5.
// The handle height before scaling is 20.0 + 6 * 2 - 1.5 = 30.5.
final double handleHeightBeforeScaling = handles.first.size.height;
expect(handleHeightBeforeScaling, 30.5);
final Offset handleHeightAfterScaling = handles.first.localToGlobal(const Offset(0, 30.5)) - handles.first.localToGlobal(Offset.zero);
// The handle height after scaling is 30.5 * 5 = 152.5
expect(handleHeightAfterScaling, equals(const Offset(0.0, 152.5)));
},
skip: isBrowser, // [intended]
variant: const TargetPlatformVariant(<TargetPlatform>{TargetPlatform.iOS}),
);
testWidgetsWithLeakTracking('builds the default context menu by default', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment