Unverified Commit 9574d585 authored by Taha Tesser's avatar Taha Tesser Committed by GitHub

Fix `shape` and `collapsedShape` isn't applied to `ExpansionTile`'s splash ink (#141777)

This updates the previous attempt https://github.com/flutter/flutter/pull/135855 and removes the complications when testing M3 ink sparkle effect. 
Thanks to this [PR](https://github.com/flutter/flutter/pull/138757) by @Piinks 

fixes [ExpansionTile InkSplash doesn't respect Shape's borderRadius](https://github.com/flutter/flutter/issues/125779)
fixes [`ExpansionTile.backgroundColor` &  `ExpansionTile.collapsedBackgroundColor` removes splash effect](https://github.com/flutter/flutter/issues/107113)

### Code sample

<details>
<summary>expand to view the code sample</summary> 

```dart
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Example(),
    );
  }
}

class Example extends StatelessWidget {
  const Example({super.key});

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
          child: Padding(
        padding: EdgeInsets.symmetric(horizontal: 24.0),
        child: ExpansionTile(
          collapsedBackgroundColor: Color(0x25ff0000),
          backgroundColor: Color(0x250000ff),
          collapsedShape: RoundedRectangleBorder(
            borderRadius: BorderRadius.all(Radius.circular(30.0)),
            side: BorderSide(color: Colors.black, width: 2.0),
          ),
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.all(Radius.circular(30.0)),
            side: BorderSide(color: Colors.black, width: 2.0),
          ),
          clipBehavior: Clip.hardEdge,
          title: Text('Expansion Tile'),
          children: <Widget>[
            FlutterLogo(size: 50),
            FlutterLogo(size: 50),
            FlutterLogo(size: 50),
            FlutterLogo(size: 50),

          ],
        ),
      )),
    );
  }
}
```

</details>

### Before

<img width="789" alt="Screenshot 2024-01-18 at 18 16 15" src="https://github.com/flutter/flutter/assets/48603081/8c6a6f1e-6986-4acf-8dec-e223a682c0d7">

<img width="789" alt="Screenshot 2024-01-18 at 18 16 44" src="https://github.com/flutter/flutter/assets/48603081/f55f6a26-2128-48a1-b24d-3c14e4f6ecdc">

### After 
<img width="789" alt="Screenshot 2024-01-18 at 18 20 27" src="https://github.com/flutter/flutter/assets/48603081/7ec8b888-7319-460d-8488-9cd44c9246a6">

<img width="789" alt="Screenshot 2024-01-18 at 18 20 53" src="https://github.com/flutter/flutter/assets/48603081/80d66d5b-7eb2-4f47-ab4d-d7f469a731fa">
parent 634b326e
......@@ -475,8 +475,11 @@ class ExpansionTile extends StatefulWidget {
/// {@macro flutter.material.Material.clipBehavior}
///
/// If this is not null and a custom collapsed or expanded shape is provided,
/// the value of [clipBehavior] will be used to clip the expansion tile.
///
/// If this property is null, the [ExpansionTileThemeData.clipBehavior] is used. If that
/// is also null, a [Clip.none] is used
/// is also null, defaults to [Clip.antiAlias].
///
/// See also:
///
......@@ -656,11 +659,12 @@ class _ExpansionTileState extends State<ExpansionTile> with SingleTickerProvider
Widget _buildChildren(BuildContext context, Widget? child) {
final ThemeData theme = Theme.of(context);
final ExpansionTileThemeData expansionTileTheme = ExpansionTileTheme.of(context);
final Color backgroundColor = _backgroundColor.value ?? expansionTileTheme.backgroundColor ?? Colors.transparent;
final ShapeBorder expansionTileBorder = _border.value ?? const Border(
top: BorderSide(color: Colors.transparent),
bottom: BorderSide(color: Colors.transparent),
);
final Clip clipBehavior = widget.clipBehavior ?? expansionTileTheme.clipBehavior ?? Clip.none;
final Clip clipBehavior = widget.clipBehavior ?? expansionTileTheme.clipBehavior ?? Clip.antiAlias;
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
final String onTapHint = _isExpanded
? localizations.expansionTileExpandedTapHint
......@@ -679,12 +683,13 @@ class _ExpansionTileState extends State<ExpansionTile> with SingleTickerProvider
break;
}
return Container(
clipBehavior: clipBehavior,
decoration: ShapeDecoration(
color: _backgroundColor.value ?? expansionTileTheme.backgroundColor ?? Colors.transparent,
final Decoration decoration = ShapeDecoration(
color: backgroundColor,
shape: expansionTileBorder,
),
);
final Widget tile = Padding(
padding: decoration.padding,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
......@@ -720,6 +725,23 @@ class _ExpansionTileState extends State<ExpansionTile> with SingleTickerProvider
],
),
);
final bool isShapeProvided = widget.shape != null || expansionTileTheme.shape != null
|| widget.collapsedShape != null || expansionTileTheme.collapsedShape != null;
if (isShapeProvided) {
return Material(
clipBehavior: clipBehavior,
color: backgroundColor,
shape: expansionTileBorder,
child: tile,
);
}
return DecoratedBox(
decoration: decoration,
child: tile,
);
}
@override
......
......@@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file is run as part of a reduced test set in CI on Mac and Windows
// machines.
@Tags(<String>['reduced-test-set'])
library;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
......@@ -48,19 +53,22 @@ void main() {
const Color unselectedWidgetColor = Colors.black54;
const Color headerColor = Colors.black45;
Material getMaterial(WidgetTester tester) {
return tester.widget<Material>(find.descendant(
of: find.byType(ExpansionTile),
matching: find.byType(Material),
));
}
testWidgets('ExpansionTile initial state', (WidgetTester tester) async {
final Key topKey = UniqueKey();
final Key tileKey = UniqueKey();
const Key expandedKey = PageStorageKey<String>('expanded');
const Key collapsedKey = PageStorageKey<String>('collapsed');
const Key defaultKey = PageStorageKey<String>('default');
final Key tileKey = UniqueKey();
const Clip clipBehavior = Clip.antiAlias;
await tester.pumpWidget(MaterialApp(
theme: ThemeData(
dividerColor: dividerColor,
),
theme: ThemeData(dividerColor: dividerColor),
home: Material(
child: SingleChildScrollView(
child: Column(
......@@ -71,7 +79,6 @@ void main() {
initiallyExpanded: true,
title: const Text('Expanded'),
backgroundColor: Colors.red,
clipBehavior: clipBehavior,
children: <Widget>[
ListTile(
key: tileKey,
......@@ -103,24 +110,21 @@ void main() {
));
double getHeight(Key key) => tester.getSize(find.byKey(key)).height;
Container getContainer(Key key) => tester.firstWidget(find.descendant(
DecoratedBox getDecoratedBox(Key key) => tester.firstWidget(find.descendant(
of: find.byKey(key),
matching: find.byType(Container),
matching: find.byType(DecoratedBox),
));
expect(getHeight(topKey), getHeight(expandedKey) - getHeight(tileKey) - 2.0);
expect(getHeight(topKey), getHeight(collapsedKey) - 2.0);
expect(getHeight(topKey), getHeight(defaultKey) - 2.0);
// expansionTile should have Clip.antiAlias as clipBehavior
expect(getContainer(expandedKey).clipBehavior, clipBehavior);
ShapeDecoration expandedContainerDecoration = getContainer(expandedKey).decoration! as ShapeDecoration;
ShapeDecoration expandedContainerDecoration = getDecoratedBox(expandedKey).decoration as ShapeDecoration;
expect(expandedContainerDecoration.color, Colors.red);
expect((expandedContainerDecoration.shape as Border).top.color, dividerColor);
expect((expandedContainerDecoration.shape as Border).bottom.color, dividerColor);
ShapeDecoration collapsedContainerDecoration = getContainer(collapsedKey).decoration! as ShapeDecoration;
ShapeDecoration collapsedContainerDecoration = getDecoratedBox(collapsedKey).decoration as ShapeDecoration;
expect(collapsedContainerDecoration.color, Colors.transparent);
expect((collapsedContainerDecoration.shape as Border).top.color, Colors.transparent);
expect((collapsedContainerDecoration.shape as Border).bottom.color, Colors.transparent);
......@@ -133,7 +137,7 @@ void main() {
// Pump to the middle of the animation for expansion.
await tester.pump(const Duration(milliseconds: 100));
final ShapeDecoration collapsingContainerDecoration = getContainer(collapsedKey).decoration! as ShapeDecoration;
final ShapeDecoration collapsingContainerDecoration = getDecoratedBox(collapsedKey).decoration as ShapeDecoration;
expect(collapsingContainerDecoration.color, Colors.transparent);
expect((collapsingContainerDecoration.shape as Border).top.color, const Color(0x15222222));
expect((collapsingContainerDecoration.shape as Border).bottom.color, const Color(0x15222222));
......@@ -146,13 +150,13 @@ void main() {
expect(getHeight(topKey), getHeight(defaultKey) - getHeight(tileKey) - 2.0);
// Expanded should be collapsed now.
expandedContainerDecoration = getContainer(expandedKey).decoration! as ShapeDecoration;
expandedContainerDecoration = getDecoratedBox(expandedKey).decoration as ShapeDecoration;
expect(expandedContainerDecoration.color, Colors.transparent);
expect((expandedContainerDecoration.shape as Border).top.color, Colors.transparent);
expect((expandedContainerDecoration.shape as Border).bottom.color, Colors.transparent);
// Collapsed should be expanded now.
collapsedContainerDecoration = getContainer(collapsedKey).decoration! as ShapeDecoration;
collapsedContainerDecoration = getDecoratedBox(collapsedKey).decoration as ShapeDecoration;
expect(collapsedContainerDecoration.color, Colors.transparent);
expect((collapsedContainerDecoration.shape as Border).top.color, dividerColor);
expect((collapsedContainerDecoration.shape as Border).bottom.color, dividerColor);
......@@ -506,20 +510,20 @@ void main() {
),
));
ShapeDecoration shapeDecoration = tester.firstWidget<Container>(find.descendant(
ShapeDecoration shapeDecoration = tester.firstWidget<DecoratedBox>(find.descendant(
of: find.byKey(expansionTileKey),
matching: find.byType(Container),
)).decoration! as ShapeDecoration;
matching: find.byType(DecoratedBox),
)).decoration as ShapeDecoration;
expect(shapeDecoration.color, collapsedBackgroundColor);
await tester.tap(find.text('Title'));
await tester.pumpAndSettle();
shapeDecoration = tester.firstWidget<Container>(find.descendant(
shapeDecoration = tester.firstWidget<DecoratedBox>(find.descendant(
of: find.byKey(expansionTileKey),
matching: find.byType(Container),
)).decoration! as ShapeDecoration;
matching: find.byType(DecoratedBox),
)).decoration as ShapeDecoration;
expect(shapeDecoration.color, backgroundColor);
});
......@@ -601,10 +605,7 @@ void main() {
await tester.pumpWidget(MaterialApp(
home: Material(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
ExpansionTile(
child: ExpansionTile(
key: expansionTileKey,
title: const Text('ExpansionTile'),
collapsedShape: collapsedShape,
......@@ -615,27 +616,24 @@ void main() {
),
],
),
],
),
),
),
));
Container getContainer(Key key) => tester.firstWidget(find.descendant(
of: find.byKey(key),
matching: find.byType(Container),
));
// expansionTile should be Collapsed now.
ShapeDecoration expandedContainerDecoration = getContainer(expansionTileKey).decoration! as ShapeDecoration;
expect(expandedContainerDecoration.shape, collapsedShape);
// When a custom shape is provided, ExpansionTile will use the
// Material widget to draw the shape and background color
// instead of a Container.
Material material = getMaterial(tester);
// ExpansionTile should be collapsed initially.
expect(material.shape, collapsedShape);
expect(material.clipBehavior, Clip.antiAlias);
await tester.tap(find.text('ExpansionTile'));
await tester.pumpAndSettle();
// expansionTile should be Expanded now.
expandedContainerDecoration = getContainer(expansionTileKey).decoration! as ShapeDecoration;
expect(expandedContainerDecoration.shape, shape);
// ExpansionTile should be Expanded now.
material = getMaterial(tester);
expect(material.shape, shape);
expect(material.clipBehavior, Clip.antiAlias);
});
testWidgets('ExpansionTile platform controlAffinity test', (WidgetTester tester) async {
......@@ -940,14 +938,15 @@ void main() {
),
));
ShapeDecoration shapeDecoration = tester.firstWidget<Container>(find.descendant(
of: find.byKey(expansionTileKey),
matching: find.byType(Container),
)).decoration! as ShapeDecoration;
// When a custom shape is provided, ExpansionTile will use the
// Material widget to draw the shape and background color
// instead of a Container.
Material material = getMaterial(tester);
// Test initial ExpansionTile properties.
expect(shapeDecoration.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
expect(shapeDecoration.color, const Color(0xffff0000));
expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
expect(material.color, const Color(0xffff0000));
expect(material.clipBehavior, Clip.antiAlias);
expect(tester.state<TestIconState>(find.byType(TestIcon)).iconTheme.color, const Color(0xffffffff));
expect(tester.state<TestTextState>(find.byType(TestText)).textStyle.color, const Color(0xffffffff));
......@@ -955,14 +954,12 @@ void main() {
await tester.tap(find.text('Update collapsed properties'));
await tester.pumpAndSettle();
shapeDecoration = tester.firstWidget<Container>(find.descendant(
of: find.byKey(expansionTileKey),
matching: find.byType(Container),
)).decoration! as ShapeDecoration;
material = getMaterial(tester);
// Test updated ExpansionTile properties.
expect(shapeDecoration.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16))));
expect(shapeDecoration.color, const Color(0xffffff00));
expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16))));
expect(material.color, const Color(0xffffff00));
expect(material.clipBehavior, Clip.antiAlias);
expect(tester.state<TestIconState>(find.byType(TestIcon)).iconTheme.color, const Color(0xff000000));
expect(tester.state<TestTextState>(find.byType(TestText)).textStyle.color, const Color(0xff000000));
});
......@@ -1019,14 +1016,15 @@ void main() {
await tester.tap(find.text('title'));
await tester.pumpAndSettle();
ShapeDecoration shapeDecoration = tester.firstWidget<Container>(find.descendant(
of: find.byKey(expansionTileKey),
matching: find.byType(Container),
)).decoration! as ShapeDecoration;
// When a custom shape is provided, ExpansionTile will use the
// Material widget to draw the shape and background color
// instead of a Container.
Material material = getMaterial(tester);
// Test initial ExpansionTile properties.
expect(shapeDecoration.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(12))));
expect(shapeDecoration.color, const Color(0xff0000ff));
expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(12))));
expect(material.color, const Color(0xff0000ff));
expect(material.clipBehavior, Clip.antiAlias);
expect(tester.state<TestIconState>(find.byType(TestIcon)).iconTheme.color, const Color(0xff00ffff));
expect(tester.state<TestTextState>(find.byType(TestText)).textStyle.color, const Color(0xff00ffff));
......@@ -1034,16 +1032,14 @@ void main() {
await tester.tap(find.text('Update collapsed properties'));
await tester.pumpAndSettle();
shapeDecoration = tester.firstWidget<Container>(find.descendant(
of: find.byKey(expansionTileKey),
matching: find.byType(Container),
)).decoration! as ShapeDecoration;
material = getMaterial(tester);
iconColor = tester.state<TestIconState>(find.byType(TestIcon)).iconTheme.color!;
textColor = tester.state<TestTextState>(find.byType(TestText)).textStyle.color!;
// Test updated ExpansionTile properties.
expect(shapeDecoration.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(6))));
expect(shapeDecoration.color, const Color(0xff123456));
expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(6))));
expect(material.color, const Color(0xff123456));
expect(material.clipBehavior, Clip.antiAlias);
expect(tester.state<TestIconState>(find.byType(TestIcon)).iconTheme.color, const Color(0xffffffff));
expect(tester.state<TestTextState>(find.byType(TestText)).textStyle.color, const Color(0xffffffff));
});
......@@ -1149,6 +1145,93 @@ void main() {
expect(getHeight(expansionTileKey), 158.0);
});
testWidgets('Material3 - ExpansionTile draws Inkwell splash on top of background color', (WidgetTester tester) async {
const Key expansionTileKey = Key('expansionTileKey');
const ShapeBorder shape = RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(16)),
);
const ShapeBorder collapsedShape = RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(16)),
);
const Color collapsedBackgroundColor = Color(0xff00ff00);
const Color backgroundColor = Color(0xffff0000);
await tester.pumpWidget(const MaterialApp(
home: Material(
child: Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 24.0),
child: ExpansionTile(
key: expansionTileKey,
shape: shape,
collapsedBackgroundColor: collapsedBackgroundColor,
backgroundColor: backgroundColor,
collapsedShape: collapsedShape,
title: TestText('title'),
trailing: TestIcon(),
children: <Widget>[
SizedBox(height: 100, width: 100),
],
),
),
),
),
));
// Tap and hold the ExpansionTile to trigger ink splash.
final Offset center = tester.getCenter(find.byKey(expansionTileKey));
final TestGesture gesture = await tester.startGesture(center);
await tester.pump(); // Start the splash animation.
await tester.pump(const Duration(milliseconds: 100)); // Splash is underway.
// Material 3 uses the InkSparkle which uses a shader, so we can't capture
// the effect with paint methods. Use a golden test instead.
// Check if the ink sparkle is drawn on top of the background color.
await expectLater(
find.byKey(expansionTileKey),
matchesGoldenFile('expansion_tile.ink_splash.drawn_on_top_of_background_color.png'),
);
// Finish gesture to release resources.
await gesture.up();
await tester.pumpAndSettle();
});
testWidgets('Default clipBehavior when a shape is provided', (WidgetTester tester) async {
await tester.pumpWidget(
const MaterialApp(
home: Scaffold(
body: ExpansionTile(
title: Text('Title'),
subtitle: Text('Subtitle'),
shape: StadiumBorder(),
children: <Widget>[ListTile(title: Text('0'))],
),
),
),
);
expect(getMaterial(tester).clipBehavior, Clip.antiAlias);
});
testWidgets('Can override clipBehavior when a shape is provided', (WidgetTester tester) async {
await tester.pumpWidget(
const MaterialApp(
home: Scaffold(
body: ExpansionTile(
title: Text('Title'),
subtitle: Text('Subtitle'),
shape: StadiumBorder(),
clipBehavior: Clip.none,
children: <Widget>[ListTile(title: Text('0'))],
),
),
),
);
expect(getMaterial(tester).clipBehavior, Clip.none);
});
group('Material 2', () {
// These tests are only relevant for Material 2. Once Material 2
// support is deprecated and the APIs are removed, these tests
......@@ -1182,6 +1265,56 @@ void main() {
expect(getIconColor(), theme.colorScheme.primary);
expect(getTextColor(), theme.colorScheme.primary);
});
testWidgets('Material2 - ExpansionTile draws inkwell splash on top of background color', (WidgetTester tester) async {
const Key expansionTileKey = Key('expansionTileKey');
final ThemeData theme = ThemeData(useMaterial3: false);
const ShapeBorder shape = RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(16)),
);
const ShapeBorder collapsedShape = RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(16)),
);
const Color collapsedBackgroundColor = Color(0xff00ff00);
const Color backgroundColor = Color(0xffff0000);
await tester.pumpWidget(MaterialApp(
theme: theme,
home: const Material(
child: Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 24.0),
child: ExpansionTile(
key: expansionTileKey,
shape: shape,
collapsedBackgroundColor: collapsedBackgroundColor,
backgroundColor: backgroundColor,
collapsedShape: collapsedShape,
title: TestText('title'),
trailing: TestIcon(),
children: <Widget>[
SizedBox(height: 100, width: 100),
],
),
),
),
),
));
// Tap and hold the ExpansionTile to trigger ink splash.
final Offset center = tester.getCenter(find.byKey(expansionTileKey));
final TestGesture gesture = await tester.startGesture(center);
await tester.pump(); // Start the splash animation.
await tester.pump(const Duration(milliseconds: 100)); // Splash is underway.
final RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
// Check if the ink splash is drawn on top of the background color.
expect(inkFeatures, paints..path(color: collapsedBackgroundColor)..circle(color: theme.splashColor));
// Finish gesture to release resources.
await gesture.up();
await tester.pumpAndSettle();
});
});
testWidgets('ExpansionTileController isExpanded, expand() and collapse()', (WidgetTester tester) async {
......
......@@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file is run as part of a reduced test set in CI on Mac and Windows
// machines.
@Tags(<String>['reduced-test-set'])
library;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
......@@ -42,6 +47,13 @@ class TestTextState extends State<TestText> {
}
void main() {
Material getMaterial(WidgetTester tester) {
return tester.widget<Material>(find.descendant(
of: find.byType(ExpansionTile),
matching: find.byType(Material),
));
}
test('ExpansionTileThemeData copyWith, ==, hashCode basics', () {
expect(const ExpansionTileThemeData(), const ExpansionTileThemeData().copyWith());
expect(const ExpansionTileThemeData().hashCode, const ExpansionTileThemeData().copyWith().hashCode);
......@@ -173,21 +185,16 @@ void main() {
),
);
final ShapeDecoration shapeDecoration = tester.firstWidget<Container>(find.descendant(
of: find.byKey(tileKey),
matching: find.byType(Container),
)).decoration! as ShapeDecoration;
// When a custom shape is provided, ExpansionTile will use the
// Material widget to draw the shape and background color
// instead of a Container.
final Material material = getMaterial(tester);
final Clip tileClipBehavior = tester.firstWidget<Container>(find.descendant(
of: find.byKey(tileKey),
matching: find.byType(Container),
)).clipBehavior;
// expansionTile should have Clip.antiAlias as clipBehavior
expect(tileClipBehavior, clipBehavior);
// ExpansionTile should have Clip.antiAlias as clipBehavior.
expect(material.clipBehavior, clipBehavior);
// Check the tile's collapsed background color when collapsedBackgroundColor is applied.
expect(shapeDecoration.color, collapsedBackgroundColor);
expect(material.color, collapsedBackgroundColor);
final Rect titleRect = tester.getRect(find.text('Collapsed Tile'));
final Rect trailingRect = tester.getRect(find.byIcon(Icons.expand_more));
......@@ -211,7 +218,7 @@ void main() {
// Check the collapsed text color when textColor is applied.
expect(getTextColor(), collapsedTextColor);
// Check the collapsed ShapeBorder when shape is applied.
expect(shapeDecoration.shape, collapsedShape);
expect(material.shape, collapsedShape);
});
testWidgets('ExpansionTileTheme - expanded', (WidgetTester tester) async {
......@@ -232,6 +239,7 @@ void main() {
top: BorderSide(color: Colors.green),
bottom: BorderSide(color: Colors.green),
);
const Clip clipBehavior = Clip.none;
await tester.pumpWidget(
MaterialApp(
......@@ -248,6 +256,7 @@ void main() {
collapsedTextColor: collapsedTextColor,
shape: shape,
collapsedShape: collapsedShape,
clipBehavior: clipBehavior,
),
),
home: Material(
......@@ -264,12 +273,12 @@ void main() {
),
);
final ShapeDecoration shapeDecoration = tester.firstWidget<Container>(find.descendant(
of: find.byKey(tileKey),
matching: find.byType(Container),
)).decoration! as ShapeDecoration;
// When a custom shape is provided, ExpansionTile will use the
// Material widget to draw the shape and background color
// instead of a Container.
final Material material = getMaterial(tester);
// Check the tile's background color when backgroundColor is applied.
expect(shapeDecoration.color, backgroundColor);
expect(material.color, backgroundColor);
final Rect titleRect = tester.getRect(find.text('Expanded Tile'));
final Rect trailingRect = tester.getRect(find.byIcon(Icons.expand_more));
......@@ -293,7 +302,9 @@ void main() {
// Check the expanded text color when textColor is applied.
expect(getTextColor(), textColor);
// Check the expanded ShapeBorder when shape is applied.
expect(shapeDecoration.shape, shape);
expect(material.shape, shape);
// Check the clipBehavior when shape is applied.
expect(material.clipBehavior, clipBehavior);
// Check the child position when expandedAlignment is applied.
final Rect childRect = tester.getRect(find.text('Tile 1'));
......
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