mirror of
https://github.com/flutter/flutter
synced 2024-10-02 22:44:13 +00:00
Allow ClipRRect.borderRadius to support BorderRadiusDirectional (#101200)
This commit is contained in:
parent
8ff3640c9f
commit
074ee4b2f4
|
@ -1504,11 +1504,13 @@ class RenderClipRRect extends _RenderCustomClip<RRect> {
|
|||
/// [Clip.none], no clipping will be applied.
|
||||
RenderClipRRect({
|
||||
RenderBox? child,
|
||||
BorderRadius borderRadius = BorderRadius.zero,
|
||||
BorderRadiusGeometry borderRadius = BorderRadius.zero,
|
||||
CustomClipper<RRect>? clipper,
|
||||
Clip clipBehavior = Clip.antiAlias,
|
||||
TextDirection? textDirection,
|
||||
}) : assert(clipBehavior != null),
|
||||
_borderRadius = borderRadius,
|
||||
_textDirection = textDirection,
|
||||
super(child: child, clipper: clipper, clipBehavior: clipBehavior) {
|
||||
assert(_borderRadius != null || clipper != null);
|
||||
}
|
||||
|
@ -1519,9 +1521,9 @@ class RenderClipRRect extends _RenderCustomClip<RRect> {
|
|||
/// exceed width/height.
|
||||
///
|
||||
/// This value is ignored if [clipper] is non-null.
|
||||
BorderRadius get borderRadius => _borderRadius;
|
||||
BorderRadius _borderRadius;
|
||||
set borderRadius(BorderRadius value) {
|
||||
BorderRadiusGeometry get borderRadius => _borderRadius;
|
||||
BorderRadiusGeometry _borderRadius;
|
||||
set borderRadius(BorderRadiusGeometry value) {
|
||||
assert(value != null);
|
||||
if (_borderRadius == value)
|
||||
return;
|
||||
|
@ -1529,8 +1531,18 @@ class RenderClipRRect extends _RenderCustomClip<RRect> {
|
|||
_markNeedsClip();
|
||||
}
|
||||
|
||||
/// The text direction with which to resolve [borderRadius].
|
||||
TextDirection? get textDirection => _textDirection;
|
||||
TextDirection? _textDirection;
|
||||
set textDirection(TextDirection? value) {
|
||||
if (_textDirection == value)
|
||||
return;
|
||||
_textDirection = value;
|
||||
_markNeedsClip();
|
||||
}
|
||||
|
||||
@override
|
||||
RRect get _defaultClip => _borderRadius.toRRect(Offset.zero & size);
|
||||
RRect get _defaultClip => _borderRadius.resolve(textDirection).toRRect(Offset.zero & size);
|
||||
|
||||
@override
|
||||
bool hitTest(BoxHitTestResult result, { required Offset position }) {
|
||||
|
|
|
@ -743,7 +743,7 @@ class ClipRRect extends SingleChildRenderObjectWidget {
|
|||
/// exceed width/height.
|
||||
///
|
||||
/// This value is ignored if [clipper] is non-null.
|
||||
final BorderRadius? borderRadius;
|
||||
final BorderRadiusGeometry? borderRadius;
|
||||
|
||||
/// If non-null, determines which clip to use.
|
||||
final CustomClipper<RRect>? clipper;
|
||||
|
@ -759,6 +759,7 @@ class ClipRRect extends SingleChildRenderObjectWidget {
|
|||
borderRadius: borderRadius!,
|
||||
clipper: clipper,
|
||||
clipBehavior: clipBehavior,
|
||||
textDirection: Directionality.maybeOf(context),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -767,13 +768,14 @@ class ClipRRect extends SingleChildRenderObjectWidget {
|
|||
renderObject
|
||||
..borderRadius = borderRadius!
|
||||
..clipBehavior = clipBehavior
|
||||
..clipper = clipper;
|
||||
..clipper = clipper
|
||||
..textDirection = Directionality.maybeOf(context);
|
||||
}
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(DiagnosticsProperty<BorderRadius>('borderRadius', borderRadius, showName: false, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<BorderRadiusGeometry>('borderRadius', borderRadius, showName: false, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<CustomClipper<RRect>>('clipper', clipper, defaultValue: null));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -883,4 +883,90 @@ void main() {
|
|||
..restore(),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('ClipRRect supports BorderRadiusDirectional', (WidgetTester tester) async {
|
||||
const Radius startRadius = Radius.circular(15.0);
|
||||
const Radius endRadius = Radius.circular(30.0);
|
||||
|
||||
Widget buildClipRRect(TextDirection textDirection) {
|
||||
return Directionality(
|
||||
textDirection: textDirection,
|
||||
child: const ClipRRect(
|
||||
borderRadius: BorderRadiusDirectional.horizontal(
|
||||
start: startRadius,
|
||||
end: endRadius,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
for (final TextDirection textDirection in TextDirection.values) {
|
||||
await tester.pumpWidget(buildClipRRect(textDirection));
|
||||
final RenderClipRRect renderClip = tester.allRenderObjects.whereType<RenderClipRRect>().first;
|
||||
final bool isRtl = textDirection == TextDirection.rtl;
|
||||
expect(renderClip.borderRadius.resolve(textDirection).topLeft, isRtl ? endRadius : startRadius);
|
||||
expect(renderClip.borderRadius.resolve(textDirection).topRight, isRtl ? startRadius : endRadius);
|
||||
expect(renderClip.borderRadius.resolve(textDirection).bottomLeft, isRtl ? endRadius : startRadius);
|
||||
expect(renderClip.borderRadius.resolve(textDirection).bottomRight, isRtl ? startRadius : endRadius);
|
||||
}
|
||||
});
|
||||
|
||||
testWidgets('ClipRRect is direction-aware', (WidgetTester tester) async {
|
||||
const Radius startRadius = Radius.circular(15.0);
|
||||
const Radius endRadius = Radius.circular(30.0);
|
||||
TextDirection textDirection = TextDirection.ltr;
|
||||
|
||||
Widget buildClipRRect(TextDirection textDirection) {
|
||||
return Directionality(
|
||||
textDirection: textDirection,
|
||||
child: const ClipRRect(
|
||||
borderRadius: BorderRadiusDirectional.horizontal(
|
||||
start: startRadius,
|
||||
end: endRadius,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildStatefulClipRRect() {
|
||||
return StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return Directionality(
|
||||
textDirection: textDirection,
|
||||
child: SizedBox(
|
||||
width: 100.0,
|
||||
height: 100.0,
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadiusDirectional.horizontal(
|
||||
start: startRadius,
|
||||
end: endRadius,
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
textDirection = TextDirection.rtl;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
for (final TextDirection textDirection in TextDirection.values) {
|
||||
await tester.pumpWidget(buildClipRRect(textDirection));
|
||||
final RenderClipRRect renderClip = tester.allRenderObjects.whereType<RenderClipRRect>().first;
|
||||
final bool isRtl = textDirection == TextDirection.rtl;
|
||||
expect(renderClip.textDirection, isRtl ? TextDirection.rtl : TextDirection.ltr);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(buildStatefulClipRRect());
|
||||
final RenderClipRRect renderClip = tester.allRenderObjects.whereType<RenderClipRRect>().first;
|
||||
expect(renderClip.textDirection, TextDirection.ltr);
|
||||
await tester.tapAt(Offset.zero);
|
||||
await tester.pump();
|
||||
expect(renderClip.textDirection, TextDirection.rtl);
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue