Unverified Commit 0300cfa6 authored by Qun Cheng's avatar Qun Cheng Committed by GitHub

Create `SearchAnchor` and `SearchViewTheme` Widget (#123256)

parent 9a7387c7
......@@ -46,6 +46,7 @@ import 'package:gen_defaults/popup_menu_template.dart';
import 'package:gen_defaults/progress_indicator_template.dart';
import 'package:gen_defaults/radio_template.dart';
import 'package:gen_defaults/search_bar_template.dart';
import 'package:gen_defaults/search_view_template.dart';
import 'package:gen_defaults/segmented_button_template.dart';
import 'package:gen_defaults/slider_template.dart';
import 'package:gen_defaults/snackbar_template.dart';
......@@ -177,6 +178,7 @@ Future<void> main(List<String> args) async {
ProgressIndicatorTemplate('ProgressIndicator', '$materialLib/progress_indicator.dart', tokens).updateFile();
RadioTemplate('Radio<T>', '$materialLib/radio.dart', tokens).updateFile();
SearchBarTemplate('SearchBar', '$materialLib/search_anchor.dart', tokens).updateFile();
SearchViewTemplate('SearchView', '$materialLib/search_anchor.dart', tokens).updateFile();
SegmentedButtonTemplate('md.comp.outlined-segmented-button', 'SegmentedButton', '$materialLib/segmented_button.dart', tokens).updateFile();
SnackbarTemplate('md.comp.snackbar', 'Snackbar', '$materialLib/snack_bar.dart', tokens).updateFile();
SliderTemplate('md.comp.slider', 'Slider', '$materialLib/slider.dart', tokens).updateFile();
......
// 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 'template.dart';
class SearchViewTemplate extends TokenTemplate {
const SearchViewTemplate(super.blockName, super.fileName, super.tokens, {
super.colorSchemePrefix = '_colors.',
super.textThemePrefix = '_textTheme.'
});
@override
String generate() => '''
class _${blockName}DefaultsM3 extends ${blockName}ThemeData {
_${blockName}DefaultsM3(this.context, {required this.isFullScreen});
final BuildContext context;
final bool isFullScreen;
late final ColorScheme _colors = Theme.of(context).colorScheme;
late final TextTheme _textTheme = Theme.of(context).textTheme;
static double fullScreenBarHeight = ${tokens['md.comp.search-view.full-screen.header.container.height']};
@override
Color? get backgroundColor => ${componentColor('md.comp.search-view.container')};
@override
double? get elevation => ${elevation('md.comp.search-view.container')};
@override
Color? get surfaceTintColor => ${colorOrTransparent('md.comp.search-view.container.surface-tint-layer.color')};
// No default side
@override
OutlinedBorder? get shape => isFullScreen
? ${shape('md.comp.search-view.full-screen.container')}
: ${shape('md.comp.search-view.docked.container')};
@override
TextStyle? get headerTextStyle => ${textStyleWithColor('md.comp.search-view.header.input-text')};
@override
TextStyle? get headerHintStyle => ${textStyleWithColor('md.comp.search-view.header.supporting-text')};
@override
BoxConstraints get constraints => const BoxConstraints(minWidth: 360.0, minHeight: 240.0);
@override
Color? get dividerColor => ${componentColor('md.comp.search-view.divider')};
}
''';
}
// 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.
// Flutter code sample for [SearchAnchor.bar].
import 'package:flutter/material.dart';
void main() => runApp(const SearchBarApp());
class SearchBarApp extends StatefulWidget {
const SearchBarApp({super.key});
@override
State<SearchBarApp> createState() => _SearchBarAppState();
}
class _SearchBarAppState extends State<SearchBarApp> {
Color? selectedColorSeed;
List<ColorLabel> searchHistory = <ColorLabel>[];
Iterable<Widget> getHistoryList(SearchController controller) {
return searchHistory.map((ColorLabel color) => ListTile(
leading: const Icon(Icons.history),
title: Text(color.label),
trailing: IconButton(icon: const Icon(Icons.call_missed), onPressed: () {
controller.text = color.label;
controller.selection = TextSelection.collapsed(offset: controller.text.length);
}),
));
}
Iterable<Widget> getSuggestions(SearchController controller) {
final String input = controller.value.text;
return ColorLabel.values.where((ColorLabel color) => color.label.contains(input))
.map((ColorLabel filteredColor) =>
ListTile(
leading: CircleAvatar(backgroundColor: filteredColor.color),
title: Text(filteredColor.label),
trailing: IconButton(icon: const Icon(Icons.call_missed), onPressed: () {
controller.text = filteredColor.label;
controller.selection = TextSelection.collapsed(offset: controller.text.length);
}),
onTap: () {
controller.closeView(filteredColor.label);
handleSelection(filteredColor);
},
));
}
void handleSelection(ColorLabel selectedColor) {
setState(() {
selectedColorSeed = selectedColor.color;
if (searchHistory.length >= 5) {
searchHistory.removeLast();
}
searchHistory.insert(0, selectedColor);
});
}
@override
Widget build(BuildContext context) {
final ThemeData themeData = ThemeData(useMaterial3: true, colorSchemeSeed: selectedColorSeed);
final ColorScheme colors = themeData.colorScheme;
return MaterialApp(
theme: themeData,
home: Scaffold(
appBar: AppBar(title: const Text('Search Bar Sample')),
body: Align(
alignment: Alignment.topCenter,
child: Column(
children: <Widget>[
SearchAnchor.bar(
barHintText: 'Search colors',
suggestionsBuilder: (BuildContext context, SearchController controller) {
if (controller.text.isEmpty) {
if (searchHistory.isNotEmpty) {
return getHistoryList(controller);
}
return <Widget>[ Center(child: Text('No search history.', style: TextStyle(color: colors.outline))) ];
}
return getSuggestions(controller);
},
),
cardSize,
Card(color: colors.primary, child: cardSize),
Card(color: colors.onPrimary, child: cardSize),
Card(color: colors.primaryContainer, child: cardSize),
Card(color: colors.onPrimaryContainer, child: cardSize),
Card(color: colors.secondary, child: cardSize),
Card(color: colors.onSecondary, child: cardSize),
],
),
),
),
);
}
}
SizedBox cardSize = const SizedBox(width: 80, height: 30,);
enum ColorLabel {
red('red', Colors.red),
orange('orange', Colors.orange),
yellow('yellow', Colors.yellow),
green('green', Colors.green),
blue('blue', Colors.blue),
indigo('indigo', Colors.indigo),
violet('violet', Color(0xFF8F00FF)),
purple('purple', Colors.purple),
pink('pink', Colors.pink),
silver('silver', Color(0xFF808080)),
gold('gold', Color(0xFFFFD700)),
beige('beige', Color(0xFFF5F5DC)),
brown('brown', Colors.brown),
grey('grey', Colors.grey),
black('black', Colors.black),
white('white', Colors.white);
const ColorLabel(this.label, this.color);
final String label;
final Color color;
}
// 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.
// Flutter code sample for pinned [SearchAnchor] while scrolling.
import 'package:flutter/material.dart';
void main() {
runApp(const PinnedSearchBarApp());
}
class PinnedSearchBarApp extends StatefulWidget {
const PinnedSearchBarApp({super.key});
@override
State<PinnedSearchBarApp> createState() => _PinnedSearchBarAppState();
}
class _PinnedSearchBarAppState extends State<PinnedSearchBarApp> {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
useMaterial3: true,
colorSchemeSeed: const Color(0xff6750a4)
),
home: Scaffold(
body: SafeArea(
child: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
clipBehavior: Clip.none,
shape: const StadiumBorder(),
scrolledUnderElevation: 0.0,
titleSpacing: 0.0,
backgroundColor: Colors.transparent,
floating: true, // We can also uncomment this line and set `pinned` to true to see a pinned search bar.
title: SearchAnchor.bar(
suggestionsBuilder: (BuildContext context, SearchController controller) {
return List<Widget>.generate(5, (int index) {
return ListTile(
titleAlignment: ListTileTitleAlignment.center,
title: Text('Initial list item $index'),
);
});
}
),
),
// The listed items below are just for filling the screen
// so we can see the scrolling effect.
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.all(20),
child: SizedBox(
height: 100.0,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 10,
itemBuilder: (BuildContext context, int index) {
return SizedBox(
width: 100.0,
child: Card(
child: Center(child: Text('Card $index')),
),
);
},
),
),
),
),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Container(
height: 1000,
color: Colors.deepPurple.withOpacity(0.5),
),
),
),
],
),
),
),
);
}
}
// 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.
// Flutter code sample for [SearchAnchor].
import 'package:flutter/material.dart';
void main() => runApp(const SearchBarApp());
class SearchBarApp extends StatefulWidget {
const SearchBarApp({super.key});
@override
State<SearchBarApp> createState() => _SearchBarAppState();
}
class _SearchBarAppState extends State<SearchBarApp> {
final SearchController controller = SearchController();
@override
Widget build(BuildContext context) {
final ThemeData themeData = ThemeData(useMaterial3: true);
return MaterialApp(
theme: themeData,
home: Scaffold(
appBar: AppBar(title: const Text('Search Anchor Sample')),
body: Column(
children: <Widget>[
SearchAnchor(
searchController: controller,
builder: (BuildContext context, SearchController controller) {
return IconButton(
icon: const Icon(Icons.search),
onPressed: () {
controller.openView();
},
);
},
suggestionsBuilder: (BuildContext context, SearchController controller) {
return List<ListTile>.generate(5, (int index) {
final String item = 'item $index';
return ListTile(
title: Text(item),
onTap: () {
setState(() {
controller.closeView(item);
});
},
);
});
}
),
Center(
child: controller.text.isEmpty
? const Text('No item selected')
: Text('Selected item: ${controller.value.text}'),
),
],
),
),
);
}
}
......@@ -154,6 +154,7 @@ export 'src/material/scrollbar_theme.dart';
export 'src/material/search.dart';
export 'src/material/search_anchor.dart';
export 'src/material/search_bar_theme.dart';
export 'src/material/search_view_theme.dart';
export 'src/material/segmented_button.dart';
export 'src/material/segmented_button_theme.dart';
export 'src/material/selectable_text.dart';
......
......@@ -204,6 +204,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
this.titleTextStyle,
this.systemOverlayStyle,
this.forceMaterialTransparency = false,
this.clipBehavior,
}) : assert(elevation == null || elevation >= 0.0),
preferredSize = _PreferredAppBarSize(toolbarHeight, bottom?.preferredSize.height);
......@@ -714,6 +715,9 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
/// {@endtemplate}
final bool forceMaterialTransparency;
/// {@macro flutter.material.Material.clipBehavior}
final Clip? clipBehavior;
bool _getEffectiveCenterTitle(ThemeData theme) {
bool platformCenter() {
switch (theme.platform) {
......@@ -1044,6 +1048,7 @@ class _AppBarState extends State<AppBar> {
// If the toolbar is allocated less than toolbarHeight make it
// appear to scroll upwards within its shrinking container.
Widget appBar = ClipRect(
clipBehavior: widget.clipBehavior ?? Clip.hardEdge,
child: CustomSingleChildLayout(
delegate: _ToolbarContainerLayout(toolbarHeight),
child: IconTheme.merge(
......@@ -1186,6 +1191,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
required this.titleTextStyle,
required this.systemOverlayStyle,
required this.forceMaterialTransparency,
required this.clipBehavior
}) : assert(primary || topPadding == 0.0),
_bottomHeight = bottom?.preferredSize.height ?? 0.0;
......@@ -1221,6 +1227,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
final SystemUiOverlayStyle? systemOverlayStyle;
final double _bottomHeight;
final bool forceMaterialTransparency;
final Clip? clipBehavior;
@override
double get minExtent => collapsedHeight;
......@@ -1259,6 +1266,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
toolbarOpacity: toolbarOpacity,
isScrolledUnder: isScrolledUnder,
child: AppBar(
clipBehavior: clipBehavior,
leading: leading,
automaticallyImplyLeading: automaticallyImplyLeading,
title: title,
......@@ -1463,6 +1471,7 @@ class SliverAppBar extends StatefulWidget {
this.titleTextStyle,
this.systemOverlayStyle,
this.forceMaterialTransparency = false,
this.clipBehavior,
}) : assert(floating || !snap, 'The "snap" argument only makes sense for floating app bars.'),
assert(stretchTriggerOffset > 0.0),
assert(collapsedHeight == null || collapsedHeight >= toolbarHeight, 'The "collapsedHeight" argument has to be larger than or equal to [toolbarHeight].');
......@@ -1929,6 +1938,9 @@ class SliverAppBar extends StatefulWidget {
/// This property is used to configure an [AppBar].
final bool forceMaterialTransparency;
/// {@macro flutter.material.Material.clipBehavior}
final Clip? clipBehavior;
@override
State<SliverAppBar> createState() => _SliverAppBarState();
}
......@@ -2035,6 +2047,7 @@ class _SliverAppBarState extends State<SliverAppBar> with TickerProviderStateMix
titleTextStyle: widget.titleTextStyle,
systemOverlayStyle: widget.systemOverlayStyle,
forceMaterialTransparency: widget.forceMaterialTransparency,
clipBehavior: widget.clipBehavior,
),
),
);
......
......@@ -1322,19 +1322,19 @@ class _BottomSheetDefaultsM3 extends BottomSheetThemeData {
late final ColorScheme _colors = Theme.of(context).colorScheme;
@override
Color get backgroundColor => _colors.surface;
Color? get backgroundColor => _colors.surface;
@override
Color get surfaceTintColor => _colors.surfaceTint;
Color? get surfaceTintColor => _colors.surfaceTint;
@override
Color get shadowColor => Colors.transparent;
Color? get shadowColor => Colors.transparent;
@override
Color get dragHandleColor => Theme.of(context).colorScheme.onSurfaceVariant.withOpacity(0.4);
Color? get dragHandleColor => _colors.onSurfaceVariant.withOpacity(0.4);
@override
Size get dragHandleSize => const Size(32, 4);
Size? get dragHandleSize => const Size(32, 4);
}
// END GENERATED TOKEN PROPERTIES - BottomSheet
// 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/rendering.dart';
import 'package:flutter/widgets.dart';
import 'theme.dart';
// Examples can assume:
// late BuildContext context;
/// Defines the configuration of the search views created by the [SearchAnchor]
/// widget.
///
/// Descendant widgets obtain the current [SearchViewThemeData] object using
/// `SearchViewTheme.of(context)`.
///
/// Typically, a [SearchViewThemeData] is specified as part of the overall [Theme]
/// with [ThemeData.searchViewTheme]. Otherwise, [SearchViewTheme] can be used
/// to configure its own widget subtree.
///
/// All [SearchViewThemeData] properties are `null` by default. If any of these
/// properties are null, the search view will provide its own defaults.
///
/// See also:
///
/// * [ThemeData], which describes the overall theme for the application.
/// * [SearchBarThemeData], which describes the theme for the search bar itself in a
/// [SearchBar] widget.
/// * [SearchAnchor], which is used to open a search view route.
@immutable
class SearchViewThemeData with Diagnosticable {
/// Creates a theme that can be used for [ThemeData.searchViewTheme].
const SearchViewThemeData({
this.backgroundColor,
this.elevation,
this.surfaceTintColor,
this.constraints,
this.side,
this.shape,
this.headerTextStyle,
this.headerHintStyle,
this.dividerColor,
});
/// Overrides the default value of the [SearchAnchor.viewBackgroundColor].
final Color? backgroundColor;
/// Overrides the default value of the [SearchAnchor.viewElevation].
final double? elevation;
/// Overrides the default value of the [SearchAnchor.viewSurfaceTintColor].
final Color? surfaceTintColor;
/// Overrides the default value of the [SearchAnchor.viewSide].
final BorderSide? side;
/// Overrides the default value of the [SearchAnchor.viewShape].
final OutlinedBorder? shape;
/// Overrides the default value for [SearchAnchor.headerTextStyle].
final TextStyle? headerTextStyle;
/// Overrides the default value for [SearchAnchor.headerHintStyle].
final TextStyle? headerHintStyle;
/// Overrides the value of size constraints for [SearchAnchor.viewConstraints].
final BoxConstraints? constraints;
/// Overrides the value of the divider color for [SearchAnchor.dividerColor].
final Color? dividerColor;
/// Creates a copy of this object but with the given fields replaced with the
/// new values.
SearchViewThemeData copyWith({
Color? backgroundColor,
double? elevation,
Color? surfaceTintColor,
BorderSide? side,
OutlinedBorder? shape,
TextStyle? headerTextStyle,
TextStyle? headerHintStyle,
BoxConstraints? constraints,
Color? dividerColor,
}) {
return SearchViewThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor,
elevation: elevation ?? this.elevation,
surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor,
side: side ?? this.side,
shape: shape ?? this.shape,
headerTextStyle: headerTextStyle ?? this.headerTextStyle,
headerHintStyle: headerHintStyle ?? this.headerHintStyle,
constraints: constraints ?? this.constraints,
dividerColor: dividerColor ?? this.dividerColor,
);
}
/// Linearly interpolate between two [SearchViewThemeData]s.
static SearchViewThemeData? lerp(SearchViewThemeData? a, SearchViewThemeData? b, double t) {
if (identical(a, b)) {
return a;
}
return SearchViewThemeData(
backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t),
elevation: lerpDouble(a?.elevation, b?.elevation, t),
surfaceTintColor: Color.lerp(a?.surfaceTintColor, b?.surfaceTintColor, t),
side: _lerpSides(a?.side, b?.side, t),
shape: OutlinedBorder.lerp(a?.shape, b?.shape, t),
headerTextStyle: TextStyle.lerp(a?.headerTextStyle, b?.headerTextStyle, t),
headerHintStyle: TextStyle.lerp(a?.headerTextStyle, b?.headerTextStyle, t),
constraints: BoxConstraints.lerp(a?.constraints, b?.constraints, t),
dividerColor: Color.lerp(a?.dividerColor, b?.dividerColor, t),
);
}
@override
int get hashCode => Object.hash(
backgroundColor,
elevation,
surfaceTintColor,
side,
shape,
headerTextStyle,
headerHintStyle,
constraints,
dividerColor,
);
@override
bool operator ==(Object other) {
if (identical(this, other)) {
return true;
}
if (other.runtimeType != runtimeType) {
return false;
}
return other is SearchViewThemeData
&& other.backgroundColor == backgroundColor
&& other.elevation == elevation
&& other.surfaceTintColor == surfaceTintColor
&& other.side == side
&& other.shape == shape
&& other.headerTextStyle == headerTextStyle
&& other.headerHintStyle == headerHintStyle
&& other.constraints == constraints
&& other.dividerColor == dividerColor;
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<Color?>('backgroundColor', backgroundColor, defaultValue: null));
properties.add(DiagnosticsProperty<double?>('elevation', elevation, defaultValue: null));
properties.add(DiagnosticsProperty<Color?>('surfaceTintColor', surfaceTintColor, defaultValue: null));
properties.add(DiagnosticsProperty<BorderSide?>('side', side, defaultValue: null));
properties.add(DiagnosticsProperty<OutlinedBorder?>('shape', shape, defaultValue: null));
properties.add(DiagnosticsProperty<TextStyle?>('headerTextStyle', headerTextStyle, defaultValue: null));
properties.add(DiagnosticsProperty<TextStyle?>('headerHintStyle', headerHintStyle, defaultValue: null));
properties.add(DiagnosticsProperty<BoxConstraints>('constraints', constraints, defaultValue: null));
properties.add(DiagnosticsProperty<Color?>('dividerColor', dividerColor, defaultValue: null));
}
// Special case because BorderSide.lerp() doesn't support null arguments
static BorderSide? _lerpSides(BorderSide? a, BorderSide? b, double t) {
if (a == null || b == null) {
return null;
}
if (identical(a, b)) {
return a;
}
return BorderSide.lerp(a, b, t);
}
}
/// An inherited widget that defines the configuration in this widget's
/// descendants for search view created by the [SearchAnchor] widget.
///
/// A search view theme can be specified as part of the overall Material theme using
/// [ThemeData.searchViewTheme].
///
/// See also:
///
/// * [SearchViewThemeData], which describes the actual configuration of a search view
/// theme.
class SearchViewTheme extends InheritedWidget {
/// Creates a const theme that controls the configurations for the search view
/// created by the [SearchAnchor] widget.
const SearchViewTheme({
super.key,
required this.data,
required super.child,
});
/// The properties used for all descendant [SearchAnchor] widgets.
final SearchViewThemeData data;
/// Returns the configuration [data] from the closest [SearchViewTheme] ancestor.
/// If there is no ancestor, it returns [ThemeData.searchViewTheme].
///
/// Typical usage is as follows:
///
/// ```dart
/// SearchViewThemeData theme = SearchViewTheme.of(context);
/// ```
static SearchViewThemeData of(BuildContext context) {
final SearchViewTheme? searchViewTheme = context.dependOnInheritedWidgetOfExactType<SearchViewTheme>();
return searchViewTheme?.data ?? Theme.of(context).searchViewTheme;
}
@override
bool updateShouldNotify(SearchViewTheme oldWidget) => data != oldWidget.data;
}
......@@ -54,6 +54,7 @@ import 'progress_indicator_theme.dart';
import 'radio_theme.dart';
import 'scrollbar_theme.dart';
import 'search_bar_theme.dart';
import 'search_view_theme.dart';
import 'segmented_button_theme.dart';
import 'slider_theme.dart';
import 'snack_bar_theme.dart';
......@@ -375,6 +376,7 @@ class ThemeData with Diagnosticable {
ProgressIndicatorThemeData? progressIndicatorTheme,
RadioThemeData? radioTheme,
SearchBarThemeData? searchBarTheme,
SearchViewThemeData? searchViewTheme,
SegmentedButtonThemeData? segmentedButtonTheme,
SliderThemeData? sliderTheme,
SnackBarThemeData? snackBarTheme,
......@@ -590,6 +592,7 @@ class ThemeData with Diagnosticable {
progressIndicatorTheme ??= const ProgressIndicatorThemeData();
radioTheme ??= const RadioThemeData();
searchBarTheme ??= const SearchBarThemeData();
searchViewTheme ??= const SearchViewThemeData();
segmentedButtonTheme ??= const SegmentedButtonThemeData();
sliderTheme ??= const SliderThemeData();
snackBarTheme ??= const SnackBarThemeData();
......@@ -688,6 +691,7 @@ class ThemeData with Diagnosticable {
progressIndicatorTheme: progressIndicatorTheme,
radioTheme: radioTheme,
searchBarTheme: searchBarTheme,
searchViewTheme: searchViewTheme,
segmentedButtonTheme: segmentedButtonTheme,
sliderTheme: sliderTheme,
snackBarTheme: snackBarTheme,
......@@ -800,6 +804,7 @@ class ThemeData with Diagnosticable {
required this.progressIndicatorTheme,
required this.radioTheme,
required this.searchBarTheme,
required this.searchViewTheme,
required this.segmentedButtonTheme,
required this.sliderTheme,
required this.snackBarTheme,
......@@ -1492,6 +1497,9 @@ class ThemeData with Diagnosticable {
/// A theme for customizing the appearance and layout of [SearchBar] widgets.
final SearchBarThemeData searchBarTheme;
/// A theme for customizing the appearance and layout of search views created by [SearchAnchor] widgets.
final SearchViewThemeData searchViewTheme;
/// A theme for customizing the appearance and layout of [SegmentedButton] widgets.
final SegmentedButtonThemeData segmentedButtonTheme;
......@@ -1704,6 +1712,7 @@ class ThemeData with Diagnosticable {
ProgressIndicatorThemeData? progressIndicatorTheme,
RadioThemeData? radioTheme,
SearchBarThemeData? searchBarTheme,
SearchViewThemeData? searchViewTheme,
SegmentedButtonThemeData? segmentedButtonTheme,
SliderThemeData? sliderTheme,
SnackBarThemeData? snackBarTheme,
......@@ -1839,6 +1848,7 @@ class ThemeData with Diagnosticable {
progressIndicatorTheme: progressIndicatorTheme ?? this.progressIndicatorTheme,
radioTheme: radioTheme ?? this.radioTheme,
searchBarTheme: searchBarTheme ?? this.searchBarTheme,
searchViewTheme: searchViewTheme ?? this.searchViewTheme,
segmentedButtonTheme: segmentedButtonTheme ?? this.segmentedButtonTheme,
sliderTheme: sliderTheme ?? this.sliderTheme,
snackBarTheme: snackBarTheme ?? this.snackBarTheme,
......@@ -2034,6 +2044,7 @@ class ThemeData with Diagnosticable {
progressIndicatorTheme: ProgressIndicatorThemeData.lerp(a.progressIndicatorTheme, b.progressIndicatorTheme, t)!,
radioTheme: RadioThemeData.lerp(a.radioTheme, b.radioTheme, t),
searchBarTheme: SearchBarThemeData.lerp(a.searchBarTheme, b.searchBarTheme, t)!,
searchViewTheme: SearchViewThemeData.lerp(a.searchViewTheme, b.searchViewTheme, t)!,
segmentedButtonTheme: SegmentedButtonThemeData.lerp(a.segmentedButtonTheme, b.segmentedButtonTheme, t),
sliderTheme: SliderThemeData.lerp(a.sliderTheme, b.sliderTheme, t),
snackBarTheme: SnackBarThemeData.lerp(a.snackBarTheme, b.snackBarTheme, t),
......@@ -2141,6 +2152,7 @@ class ThemeData with Diagnosticable {
other.progressIndicatorTheme == progressIndicatorTheme &&
other.radioTheme == radioTheme &&
other.searchBarTheme == searchBarTheme &&
other.searchViewTheme == searchViewTheme &&
other.segmentedButtonTheme == segmentedButtonTheme &&
other.sliderTheme == sliderTheme &&
other.snackBarTheme == snackBarTheme &&
......@@ -2245,6 +2257,7 @@ class ThemeData with Diagnosticable {
progressIndicatorTheme,
radioTheme,
searchBarTheme,
searchViewTheme,
segmentedButtonTheme,
sliderTheme,
snackBarTheme,
......@@ -2351,6 +2364,7 @@ class ThemeData with Diagnosticable {
properties.add(DiagnosticsProperty<ProgressIndicatorThemeData>('progressIndicatorTheme', progressIndicatorTheme, defaultValue: defaultData.progressIndicatorTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<RadioThemeData>('radioTheme', radioTheme, defaultValue: defaultData.radioTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<SearchBarThemeData>('searchBarTheme', searchBarTheme, defaultValue: defaultData.searchBarTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<SearchViewThemeData>('searchViewTheme', searchViewTheme, defaultValue: defaultData.searchViewTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<SegmentedButtonThemeData>('segmentedButtonTheme', segmentedButtonTheme, defaultValue: defaultData.segmentedButtonTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<SliderThemeData>('sliderTheme', sliderTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<SnackBarThemeData>('snackBarTheme', snackBarTheme, defaultValue: defaultData.snackBarTheme, level: DiagnosticLevel.debug));
......
This diff is collapsed.
......@@ -787,6 +787,7 @@ void main() {
progressIndicatorTheme: const ProgressIndicatorThemeData(),
radioTheme: const RadioThemeData(),
searchBarTheme: const SearchBarThemeData(),
searchViewTheme: const SearchViewThemeData(),
segmentedButtonTheme: const SegmentedButtonThemeData(),
sliderTheme: sliderTheme,
snackBarTheme: const SnackBarThemeData(backgroundColor: Colors.black),
......@@ -906,6 +907,7 @@ void main() {
progressIndicatorTheme: const ProgressIndicatorThemeData(),
radioTheme: const RadioThemeData(),
searchBarTheme: const SearchBarThemeData(),
searchViewTheme: const SearchViewThemeData(),
segmentedButtonTheme: const SegmentedButtonThemeData(),
sliderTheme: otherSliderTheme,
snackBarTheme: const SnackBarThemeData(backgroundColor: Colors.white),
......@@ -1010,6 +1012,7 @@ void main() {
progressIndicatorTheme: otherTheme.progressIndicatorTheme,
radioTheme: otherTheme.radioTheme,
searchBarTheme: otherTheme.searchBarTheme,
searchViewTheme: otherTheme.searchViewTheme,
sliderTheme: otherTheme.sliderTheme,
snackBarTheme: otherTheme.snackBarTheme,
switchTheme: otherTheme.switchTheme,
......@@ -1111,6 +1114,7 @@ void main() {
expect(themeDataCopy.progressIndicatorTheme, equals(otherTheme.progressIndicatorTheme));
expect(themeDataCopy.radioTheme, equals(otherTheme.radioTheme));
expect(themeDataCopy.searchBarTheme, equals(otherTheme.searchBarTheme));
expect(themeDataCopy.searchViewTheme, equals(otherTheme.searchViewTheme));
expect(themeDataCopy.sliderTheme, equals(otherTheme.sliderTheme));
expect(themeDataCopy.snackBarTheme, equals(otherTheme.snackBarTheme));
expect(themeDataCopy.switchTheme, equals(otherTheme.switchTheme));
......@@ -1249,6 +1253,7 @@ void main() {
'progressIndicatorTheme',
'radioTheme',
'searchBarTheme',
'searchViewTheme',
'segmentedButtonTheme',
'sliderTheme',
'snackBarTheme',
......
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