mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Feat: Add carousel view theme (#164769)
Feat: Add carousel view theme fixes: #159679 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing.
This commit is contained in:
parent
909aeccfe4
commit
ddc95409bd
@ -47,6 +47,7 @@ export 'src/material/calendar_date_picker.dart';
|
||||
export 'src/material/card.dart';
|
||||
export 'src/material/card_theme.dart';
|
||||
export 'src/material/carousel.dart';
|
||||
export 'src/material/carousel_theme.dart';
|
||||
export 'src/material/checkbox.dart';
|
||||
export 'src/material/checkbox_list_tile.dart';
|
||||
export 'src/material/checkbox_theme.dart';
|
||||
|
@ -12,6 +12,8 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'carousel_theme.dart';
|
||||
import 'color_scheme.dart';
|
||||
import 'colors.dart';
|
||||
import 'ink_well.dart';
|
||||
import 'material.dart';
|
||||
@ -401,25 +403,30 @@ class _CarouselViewState extends State<CarouselView> {
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildCarouselItem(ThemeData theme, int index) {
|
||||
final EdgeInsets effectivePadding = widget.padding ?? const EdgeInsets.all(4.0);
|
||||
Widget _buildCarouselItem(int index) {
|
||||
final CarouselViewThemeData carouselTheme = CarouselViewTheme.of(context);
|
||||
final ColorScheme colorScheme = ColorScheme.of(context);
|
||||
final EdgeInsets effectivePadding =
|
||||
widget.padding ?? carouselTheme.padding ?? const EdgeInsets.all(4.0);
|
||||
final Color effectiveBackgroundColor =
|
||||
widget.backgroundColor ?? Theme.of(context).colorScheme.surface;
|
||||
final double effectiveElevation = widget.elevation ?? 0.0;
|
||||
widget.backgroundColor ?? carouselTheme.backgroundColor ?? colorScheme.surface;
|
||||
final double effectiveElevation = widget.elevation ?? carouselTheme.elevation ?? 0.0;
|
||||
final ShapeBorder effectiveShape =
|
||||
widget.shape ??
|
||||
carouselTheme.shape ??
|
||||
const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(28.0)));
|
||||
final WidgetStateProperty<Color?> effectiveOverlayColor =
|
||||
widget.overlayColor ??
|
||||
carouselTheme.overlayColor ??
|
||||
WidgetStateProperty.resolveWith((Set<WidgetState> states) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return theme.colorScheme.onSurface.withOpacity(0.1);
|
||||
return colorScheme.onSurface.withOpacity(0.1);
|
||||
}
|
||||
if (states.contains(WidgetState.hovered)) {
|
||||
return theme.colorScheme.onSurface.withOpacity(0.08);
|
||||
return colorScheme.onSurface.withOpacity(0.08);
|
||||
}
|
||||
if (states.contains(WidgetState.focused)) {
|
||||
return theme.colorScheme.onSurface.withOpacity(0.1);
|
||||
return colorScheme.onSurface.withOpacity(0.1);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
@ -461,7 +468,7 @@ class _CarouselViewState extends State<CarouselView> {
|
||||
itemExtent: _itemExtent!,
|
||||
minExtent: widget.shrinkExtent,
|
||||
delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
|
||||
return _buildCarouselItem(theme, index);
|
||||
return _buildCarouselItem(index);
|
||||
}, childCount: widget.children.length),
|
||||
);
|
||||
}
|
||||
@ -475,7 +482,7 @@ class _CarouselViewState extends State<CarouselView> {
|
||||
shrinkExtent: widget.shrinkExtent,
|
||||
weights: _flexWeights!,
|
||||
delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
|
||||
return _buildCarouselItem(theme, index);
|
||||
return _buildCarouselItem(index);
|
||||
}, childCount: widget.children.length),
|
||||
);
|
||||
}
|
||||
|
183
packages/flutter/lib/src/material/carousel_theme.dart
Normal file
183
packages/flutter/lib/src/material/carousel_theme.dart
Normal file
@ -0,0 +1,183 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:ui' show lerpDouble;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'carousel.dart';
|
||||
import 'material.dart';
|
||||
import 'theme.dart';
|
||||
|
||||
/// Defines default property values for descendant [CarouselView] widgets.
|
||||
///
|
||||
/// Descendant widgets obtain the current [CarouselViewThemeData] object using
|
||||
/// `CarouselViewTheme.of(context)`. Instances of [CarouselViewThemeData] can be
|
||||
/// customized with [CarouselViewThemeData.copyWith].
|
||||
///
|
||||
/// Typically a [CarouselViewThemeData] is specified as part of the overall [Theme]
|
||||
/// with [ThemeData.carouselViewTheme].
|
||||
///
|
||||
/// All [CarouselViewThemeData] properties are `null` by default. When null, the [CarouselView]
|
||||
/// will provide its own defaults.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [CarouselViewTheme], an [InheritedWidget] that propagates the theme to its descendants.
|
||||
/// * [ThemeData], which describes the overall theme information for the application.
|
||||
@immutable
|
||||
class CarouselViewThemeData with Diagnosticable {
|
||||
/// Creates a theme that can be used for [ThemeData.carouselViewTheme].
|
||||
const CarouselViewThemeData({
|
||||
this.elevation,
|
||||
this.backgroundColor,
|
||||
this.overlayColor,
|
||||
this.shape,
|
||||
this.padding,
|
||||
});
|
||||
|
||||
/// The amount of space to surround each carousel item with.
|
||||
///
|
||||
/// Overrides the default value for [CarouselView.padding].
|
||||
final EdgeInsets? padding;
|
||||
|
||||
/// The background color for each carousel item.
|
||||
///
|
||||
/// Overrides the default value for [CarouselView.backgroundColor].
|
||||
final Color? backgroundColor;
|
||||
|
||||
/// The z-coordinate of each carousel item.
|
||||
///
|
||||
/// This controls the size of the shadow below the carousel.
|
||||
///
|
||||
/// Overrides the default value for [CarouselView.elevation].
|
||||
final double? elevation;
|
||||
|
||||
/// The shape of the carousel item's [Material].
|
||||
///
|
||||
/// Overrides the default value for [CarouselView.shape].
|
||||
final OutlinedBorder? shape;
|
||||
|
||||
/// The highlight color to indicate the carousel items are in pressed, hovered
|
||||
/// or focused states.
|
||||
///
|
||||
/// Overrides the default value for [CarouselView.overlayColor].
|
||||
final WidgetStateProperty<Color?>? overlayColor;
|
||||
|
||||
/// Creates a copy of this object with the given fields replaced with the
|
||||
/// new values.
|
||||
CarouselViewThemeData copyWith({
|
||||
Color? backgroundColor,
|
||||
double? elevation,
|
||||
OutlinedBorder? shape,
|
||||
WidgetStateProperty<Color?>? overlayColor,
|
||||
EdgeInsets? padding,
|
||||
}) {
|
||||
return CarouselViewThemeData(
|
||||
backgroundColor: backgroundColor ?? this.backgroundColor,
|
||||
elevation: elevation ?? this.elevation,
|
||||
shape: shape ?? this.shape,
|
||||
overlayColor: overlayColor ?? this.overlayColor,
|
||||
padding: padding ?? this.padding,
|
||||
);
|
||||
}
|
||||
|
||||
/// Linearly interpolate between two carousel themes.
|
||||
///
|
||||
/// {@macro dart.ui.shadow.lerp}
|
||||
static CarouselViewThemeData lerp(CarouselViewThemeData? a, CarouselViewThemeData? b, double t) {
|
||||
if (identical(a, b) && a != null) {
|
||||
return a;
|
||||
}
|
||||
return CarouselViewThemeData(
|
||||
backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t),
|
||||
elevation: lerpDouble(a?.elevation, b?.elevation, t),
|
||||
shape: ShapeBorder.lerp(a?.shape, b?.shape, t) as OutlinedBorder?,
|
||||
overlayColor: WidgetStateProperty.lerp<Color?>(
|
||||
a?.overlayColor,
|
||||
b?.overlayColor,
|
||||
t,
|
||||
Color.lerp,
|
||||
),
|
||||
padding: EdgeInsets.lerp(a?.padding, b?.padding, t),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(backgroundColor, elevation, shape, overlayColor, padding);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) {
|
||||
return true;
|
||||
}
|
||||
if (other.runtimeType != runtimeType) {
|
||||
return false;
|
||||
}
|
||||
return other is CarouselViewThemeData &&
|
||||
other.backgroundColor == backgroundColor &&
|
||||
other.elevation == elevation &&
|
||||
other.shape == shape &&
|
||||
other.overlayColor == overlayColor &&
|
||||
other.padding == padding;
|
||||
}
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(ColorProperty('backgroundColor', backgroundColor, defaultValue: null));
|
||||
properties.add(DoubleProperty('elevation', elevation, defaultValue: null));
|
||||
properties.add(DiagnosticsProperty<OutlinedBorder>('shape', shape, defaultValue: null));
|
||||
properties.add(
|
||||
DiagnosticsProperty<WidgetStateProperty<Color?>>(
|
||||
'overlayColor',
|
||||
overlayColor,
|
||||
defaultValue: null,
|
||||
),
|
||||
);
|
||||
properties.add(DiagnosticsProperty<EdgeInsets>('padding', padding, defaultValue: null));
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies a carousel theme to descendant [CarouselView] widgets.
|
||||
///
|
||||
/// Descendant widgets obtain the current theme's [CarouselViewThemeData] using
|
||||
/// [CarouselViewTheme.of]. When a widget uses [CarouselViewTheme.of], it is automatically
|
||||
/// rebuilt if the theme later changes.
|
||||
///
|
||||
/// A carousel theme can be specified as part of the overall Material theme using
|
||||
/// [ThemeData.carouselViewTheme].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [CarouselViewThemeData], which describes the actual configuration of a carousel
|
||||
/// theme.
|
||||
/// * [Theme], which controls the overall theme inheritance.
|
||||
class CarouselViewTheme extends InheritedTheme {
|
||||
/// Creates a carousel theme that configures all descendant [CarouselView] widgets.
|
||||
const CarouselViewTheme({super.key, required this.data, required super.child});
|
||||
|
||||
/// The properties for descendant carousel widgets.
|
||||
final CarouselViewThemeData data;
|
||||
|
||||
/// Returns the configuration [data] from the closest [CarouselViewTheme] ancestor.
|
||||
///
|
||||
/// If there is no ancestor, it returns [ThemeData.carouselViewTheme].
|
||||
static CarouselViewThemeData of(BuildContext context) {
|
||||
final CarouselViewTheme? inheritedTheme =
|
||||
context.dependOnInheritedWidgetOfExactType<CarouselViewTheme>();
|
||||
return inheritedTheme?.data ?? Theme.of(context).carouselViewTheme;
|
||||
}
|
||||
|
||||
/// Wraps the given [child] with a [CarouselViewTheme] containing the [data].
|
||||
@override
|
||||
Widget wrap(BuildContext context, Widget child) {
|
||||
return CarouselViewTheme(data: data, child: child);
|
||||
}
|
||||
|
||||
/// Returns true if the [data] fields of the two themes are different.
|
||||
@override
|
||||
bool updateShouldNotify(CarouselViewTheme oldWidget) => data != oldWidget.data;
|
||||
}
|
@ -21,6 +21,7 @@ import 'bottom_sheet_theme.dart';
|
||||
import 'button_bar_theme.dart';
|
||||
import 'button_theme.dart';
|
||||
import 'card_theme.dart';
|
||||
import 'carousel_theme.dart';
|
||||
import 'checkbox_theme.dart';
|
||||
import 'chip_theme.dart';
|
||||
import 'color_scheme.dart';
|
||||
@ -324,6 +325,7 @@ class ThemeData with Diagnosticable {
|
||||
BottomSheetThemeData? bottomSheetTheme,
|
||||
ButtonThemeData? buttonTheme,
|
||||
CardThemeData? cardTheme,
|
||||
CarouselViewThemeData? carouselViewTheme,
|
||||
CheckboxThemeData? checkboxTheme,
|
||||
ChipThemeData? chipTheme,
|
||||
DataTableThemeData? dataTableTheme,
|
||||
@ -528,6 +530,7 @@ class ThemeData with Diagnosticable {
|
||||
bottomNavigationBarTheme ??= const BottomNavigationBarThemeData();
|
||||
bottomSheetTheme ??= const BottomSheetThemeData();
|
||||
cardTheme ??= const CardThemeData();
|
||||
carouselViewTheme ??= const CarouselViewThemeData();
|
||||
checkboxTheme ??= const CheckboxThemeData();
|
||||
chipTheme ??= const ChipThemeData();
|
||||
dataTableTheme ??= const DataTableThemeData();
|
||||
@ -622,6 +625,7 @@ class ThemeData with Diagnosticable {
|
||||
bottomSheetTheme: bottomSheetTheme,
|
||||
buttonTheme: buttonTheme,
|
||||
cardTheme: cardTheme,
|
||||
carouselViewTheme: carouselViewTheme,
|
||||
checkboxTheme: checkboxTheme,
|
||||
chipTheme: chipTheme,
|
||||
dataTableTheme: dataTableTheme,
|
||||
@ -733,6 +737,7 @@ class ThemeData with Diagnosticable {
|
||||
required this.bottomSheetTheme,
|
||||
required this.buttonTheme,
|
||||
required this.cardTheme,
|
||||
required this.carouselViewTheme,
|
||||
required this.checkboxTheme,
|
||||
required this.chipTheme,
|
||||
required this.dataTableTheme,
|
||||
@ -1305,6 +1310,9 @@ class ThemeData with Diagnosticable {
|
||||
/// This is the value returned from [CardTheme.of].
|
||||
final CardThemeData cardTheme;
|
||||
|
||||
/// A theme for customizing the appearance and layout of [CarouselView] widgets.
|
||||
final CarouselViewThemeData carouselViewTheme;
|
||||
|
||||
/// A theme for customizing the appearance and layout of [Checkbox] widgets.
|
||||
final CheckboxThemeData checkboxTheme;
|
||||
|
||||
@ -1516,6 +1524,7 @@ class ThemeData with Diagnosticable {
|
||||
BottomSheetThemeData? bottomSheetTheme,
|
||||
ButtonThemeData? buttonTheme,
|
||||
CardThemeData? cardTheme,
|
||||
CarouselViewThemeData? carouselViewTheme,
|
||||
CheckboxThemeData? checkboxTheme,
|
||||
ChipThemeData? chipTheme,
|
||||
DataTableThemeData? dataTableTheme,
|
||||
@ -1634,6 +1643,7 @@ class ThemeData with Diagnosticable {
|
||||
bottomSheetTheme: bottomSheetTheme ?? this.bottomSheetTheme,
|
||||
buttonTheme: buttonTheme ?? this.buttonTheme,
|
||||
cardTheme: cardTheme ?? this.cardTheme,
|
||||
carouselViewTheme: carouselViewTheme ?? this.carouselViewTheme,
|
||||
checkboxTheme: checkboxTheme ?? this.checkboxTheme,
|
||||
chipTheme: chipTheme ?? this.chipTheme,
|
||||
dataTableTheme: dataTableTheme ?? this.dataTableTheme,
|
||||
@ -1954,6 +1964,7 @@ class ThemeData with Diagnosticable {
|
||||
bottomSheetTheme: BottomSheetThemeData.lerp(a.bottomSheetTheme, b.bottomSheetTheme, t)!,
|
||||
buttonTheme: t < 0.5 ? a.buttonTheme : b.buttonTheme,
|
||||
cardTheme: CardThemeData.lerp(a.cardTheme, b.cardTheme, t),
|
||||
carouselViewTheme: CarouselViewThemeData.lerp(a.carouselViewTheme, b.carouselViewTheme, t),
|
||||
checkboxTheme: CheckboxThemeData.lerp(a.checkboxTheme, b.checkboxTheme, t),
|
||||
chipTheme: ChipThemeData.lerp(a.chipTheme, b.chipTheme, t)!,
|
||||
dataTableTheme: DataTableThemeData.lerp(a.dataTableTheme, b.dataTableTheme, t),
|
||||
@ -2072,6 +2083,7 @@ class ThemeData with Diagnosticable {
|
||||
other.bottomSheetTheme == bottomSheetTheme &&
|
||||
other.buttonTheme == buttonTheme &&
|
||||
other.cardTheme == cardTheme &&
|
||||
other.carouselViewTheme == carouselViewTheme &&
|
||||
other.checkboxTheme == checkboxTheme &&
|
||||
other.chipTheme == chipTheme &&
|
||||
other.dataTableTheme == dataTableTheme &&
|
||||
@ -2171,6 +2183,7 @@ class ThemeData with Diagnosticable {
|
||||
bottomSheetTheme,
|
||||
buttonTheme,
|
||||
cardTheme,
|
||||
carouselViewTheme,
|
||||
checkboxTheme,
|
||||
chipTheme,
|
||||
dataTableTheme,
|
||||
@ -2549,6 +2562,14 @@ class ThemeData with Diagnosticable {
|
||||
properties.add(
|
||||
DiagnosticsProperty<CardThemeData>('cardTheme', cardTheme, level: DiagnosticLevel.debug),
|
||||
);
|
||||
properties.add(
|
||||
DiagnosticsProperty<CarouselViewThemeData>(
|
||||
'carouselViewTheme',
|
||||
carouselViewTheme,
|
||||
defaultValue: defaultData.carouselViewTheme,
|
||||
level: DiagnosticLevel.debug,
|
||||
),
|
||||
);
|
||||
properties.add(
|
||||
DiagnosticsProperty<CheckboxThemeData>(
|
||||
'checkboxTheme',
|
||||
|
242
packages/flutter/test/material/carousel_theme_test.dart
Normal file
242
packages/flutter/test/material/carousel_theme_test.dart
Normal file
@ -0,0 +1,242 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
test('CarouselViewThemeData copyWith, ==, hashCode basics', () {
|
||||
expect(const CarouselViewThemeData(), const CarouselViewThemeData().copyWith());
|
||||
expect(
|
||||
const CarouselViewThemeData().hashCode,
|
||||
const CarouselViewThemeData().copyWith().hashCode,
|
||||
);
|
||||
});
|
||||
|
||||
test('CarouselViewThemeData null fields by default', () {
|
||||
const CarouselViewThemeData carouselViewTheme = CarouselViewThemeData();
|
||||
expect(carouselViewTheme.backgroundColor, null);
|
||||
expect(carouselViewTheme.elevation, null);
|
||||
expect(carouselViewTheme.overlayColor, null);
|
||||
expect(carouselViewTheme.padding, null);
|
||||
expect(carouselViewTheme.shape, null);
|
||||
});
|
||||
|
||||
testWidgets('Default CarouselViewThemeData debugFillProperties', (WidgetTester tester) async {
|
||||
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
||||
const CarouselViewThemeData().debugFillProperties(builder);
|
||||
|
||||
final List<String> description =
|
||||
builder.properties
|
||||
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
|
||||
.map((DiagnosticsNode node) => node.toString())
|
||||
.toList();
|
||||
|
||||
expect(description, <String>[]);
|
||||
});
|
||||
|
||||
testWidgets('CarouselViewThemeData implements debugFillProperties', (WidgetTester tester) async {
|
||||
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
||||
const CarouselViewThemeData(
|
||||
backgroundColor: Color(0xFFFFFFFF),
|
||||
elevation: 5.0,
|
||||
padding: EdgeInsets.zero,
|
||||
shape: RoundedRectangleBorder(),
|
||||
overlayColor: MaterialStatePropertyAll<Color>(Colors.red),
|
||||
).debugFillProperties(builder);
|
||||
|
||||
final List<String> description =
|
||||
builder.properties
|
||||
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
|
||||
.map((DiagnosticsNode node) => node.toString())
|
||||
.toList();
|
||||
|
||||
expect(description, <String>[
|
||||
'backgroundColor: ${const Color(0xffffffff)}',
|
||||
'elevation: 5.0',
|
||||
'shape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.zero)',
|
||||
'overlayColor: WidgetStatePropertyAll(${Colors.red})',
|
||||
'padding: EdgeInsets.zero',
|
||||
]);
|
||||
});
|
||||
|
||||
testWidgets('Uses value from CarouselViewThemeData', (WidgetTester tester) async {
|
||||
final CarouselViewThemeData carouselViewTheme = _carouselViewThemeData();
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(carouselViewTheme: carouselViewTheme),
|
||||
home: const Scaffold(
|
||||
body: Center(
|
||||
child: CarouselView(
|
||||
itemExtent: 100,
|
||||
children: <Widget>[SizedBox(width: 100, height: 100)],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(find.byType(CarouselView), findsOneWidget);
|
||||
|
||||
final Finder padding = find.descendant(
|
||||
of: find.byType(CarouselView),
|
||||
matching: find.byWidgetPredicate(
|
||||
(Widget widget) => widget is Padding && widget.child is Material,
|
||||
),
|
||||
);
|
||||
|
||||
expect(padding, findsOneWidget);
|
||||
final Padding paddingWidget = tester.widget<Padding>(padding);
|
||||
final Material material = paddingWidget.child! as Material;
|
||||
|
||||
final InkWell inkWell = tester.widget<InkWell>(
|
||||
find.descendant(of: find.byType(CarouselView), matching: find.byType(InkWell)),
|
||||
);
|
||||
|
||||
expect(paddingWidget.padding, carouselViewTheme.padding);
|
||||
expect(material.color, carouselViewTheme.backgroundColor);
|
||||
expect(material.elevation, carouselViewTheme.elevation);
|
||||
expect(material.shape, carouselViewTheme.shape);
|
||||
expect(material.borderRadius, null);
|
||||
expect(material.clipBehavior, Clip.antiAlias);
|
||||
expect(inkWell.overlayColor, carouselViewTheme.overlayColor);
|
||||
});
|
||||
|
||||
testWidgets('Widgets properties override theme', (WidgetTester tester) async {
|
||||
final CarouselViewThemeData carouselViewTheme = _carouselViewThemeData();
|
||||
const Color backgroundColor = Color(0xFFFF0000);
|
||||
const double elevation = 10.0;
|
||||
const EdgeInsets padding = EdgeInsets.all(15.0);
|
||||
const OutlinedBorder shape = RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||
);
|
||||
const WidgetStateProperty<Color?> overlayColor = MaterialStatePropertyAll<Color>(Colors.green);
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(carouselViewTheme: carouselViewTheme),
|
||||
home: const Scaffold(
|
||||
body: Center(
|
||||
child: CarouselView(
|
||||
backgroundColor: backgroundColor,
|
||||
elevation: elevation,
|
||||
padding: padding,
|
||||
shape: shape,
|
||||
overlayColor: overlayColor,
|
||||
itemExtent: 100,
|
||||
children: <Widget>[SizedBox(width: 100, height: 100)],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(find.byType(CarouselView), findsOneWidget);
|
||||
|
||||
final Finder paddingFinder = find.descendant(
|
||||
of: find.byType(CarouselView),
|
||||
matching: find.byWidgetPredicate(
|
||||
(Widget widget) => widget is Padding && widget.child is Material,
|
||||
),
|
||||
);
|
||||
|
||||
expect(paddingFinder, findsOneWidget);
|
||||
final Padding paddingWidget = tester.widget<Padding>(paddingFinder);
|
||||
final Material material = paddingWidget.child! as Material;
|
||||
|
||||
final InkWell inkWell = tester.widget<InkWell>(
|
||||
find.descendant(of: find.byType(CarouselView), matching: find.byType(InkWell)),
|
||||
);
|
||||
|
||||
expect(paddingWidget.padding, padding);
|
||||
expect(material.color, backgroundColor);
|
||||
expect(material.elevation, elevation);
|
||||
expect(material.shape, shape);
|
||||
expect(inkWell.overlayColor, overlayColor);
|
||||
});
|
||||
|
||||
testWidgets('CarouselViewTheme can override Theme.carouselViewTheme', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
const Color globalBackgroundColor = Color(0xfffffff1);
|
||||
const Color globalOverlayColor = Color(0xff000000);
|
||||
const double globalElevation = 5.0;
|
||||
const EdgeInsets globalPadding = EdgeInsets.all(10.0);
|
||||
const OutlinedBorder globalShape = RoundedRectangleBorder();
|
||||
|
||||
const Color localBackgroundColor = Color(0xffff0000);
|
||||
const Color localOverlayColor = Color(0xffffffff);
|
||||
const double localElevation = 10.0;
|
||||
const EdgeInsets localPadding = EdgeInsets.all(15.0);
|
||||
const OutlinedBorder localShape = RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData(
|
||||
carouselViewTheme: const CarouselViewThemeData(
|
||||
backgroundColor: globalBackgroundColor,
|
||||
overlayColor: MaterialStatePropertyAll<Color>(globalOverlayColor),
|
||||
elevation: globalElevation,
|
||||
padding: globalPadding,
|
||||
shape: globalShape,
|
||||
),
|
||||
),
|
||||
home: const Scaffold(
|
||||
body: Center(
|
||||
child: CarouselViewTheme(
|
||||
data: CarouselViewThemeData(
|
||||
backgroundColor: localBackgroundColor,
|
||||
overlayColor: MaterialStatePropertyAll<Color>(localOverlayColor),
|
||||
elevation: localElevation,
|
||||
padding: localPadding,
|
||||
shape: localShape,
|
||||
),
|
||||
child: CarouselView(
|
||||
itemExtent: 100,
|
||||
children: <Widget>[SizedBox(width: 100, height: 100)],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final Finder padding = find.descendant(
|
||||
of: find.byType(CarouselView),
|
||||
matching: find.byWidgetPredicate(
|
||||
(Widget widget) => widget is Padding && widget.child is Material,
|
||||
),
|
||||
);
|
||||
|
||||
expect(padding, findsOneWidget);
|
||||
final Padding paddingWidget = tester.widget<Padding>(padding);
|
||||
final Material material = paddingWidget.child! as Material;
|
||||
|
||||
final InkWell inkWell = tester.widget<InkWell>(
|
||||
find.descendant(of: find.byType(CarouselView), matching: find.byType(InkWell)),
|
||||
);
|
||||
|
||||
expect(paddingWidget.padding, localPadding);
|
||||
expect(material.color, localBackgroundColor);
|
||||
expect(material.elevation, localElevation);
|
||||
expect(material.shape, localShape);
|
||||
expect(inkWell.overlayColor?.resolve(<MaterialState>{}), localOverlayColor);
|
||||
});
|
||||
}
|
||||
|
||||
CarouselViewThemeData _carouselViewThemeData() {
|
||||
const Color backgroundColor = Color(0xFF0000FF);
|
||||
const double elevation = 5.0;
|
||||
const EdgeInsets padding = EdgeInsets.all(10.0);
|
||||
const OutlinedBorder shape = RoundedRectangleBorder();
|
||||
const WidgetStateProperty<Color?> overlayColor = MaterialStatePropertyAll<Color>(Colors.red);
|
||||
|
||||
return const CarouselViewThemeData(
|
||||
backgroundColor: backgroundColor,
|
||||
elevation: elevation,
|
||||
padding: padding,
|
||||
shape: shape,
|
||||
overlayColor: overlayColor,
|
||||
);
|
||||
}
|
@ -1339,6 +1339,7 @@ void main() {
|
||||
bottomSheetTheme: const BottomSheetThemeData(backgroundColor: Colors.black),
|
||||
buttonTheme: const ButtonThemeData(colorScheme: ColorScheme.dark()),
|
||||
cardTheme: const CardThemeData(color: Colors.black),
|
||||
carouselViewTheme: const CarouselViewThemeData(),
|
||||
checkboxTheme: const CheckboxThemeData(),
|
||||
chipTheme: chipTheme,
|
||||
dataTableTheme: const DataTableThemeData(),
|
||||
@ -1467,6 +1468,7 @@ void main() {
|
||||
bottomSheetTheme: const BottomSheetThemeData(backgroundColor: Colors.white),
|
||||
buttonTheme: const ButtonThemeData(colorScheme: ColorScheme.light()),
|
||||
cardTheme: const CardThemeData(color: Colors.white),
|
||||
carouselViewTheme: const CarouselViewThemeData(),
|
||||
checkboxTheme: const CheckboxThemeData(),
|
||||
chipTheme: otherChipTheme,
|
||||
dataTableTheme: const DataTableThemeData(),
|
||||
@ -1807,6 +1809,7 @@ void main() {
|
||||
'bottomSheetTheme',
|
||||
'buttonTheme',
|
||||
'cardTheme',
|
||||
'carouselViewTheme',
|
||||
'checkboxTheme',
|
||||
'chipTheme',
|
||||
'dataTableTheme',
|
||||
|
Loading…
Reference in New Issue
Block a user