IconThemeData.size (#4633)
This commit is contained in:
parent
5809a0cb71
commit
cff31a3f6d
@ -26,29 +26,34 @@ import 'theme.dart';
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [IconButton], for interactive icons
|
||||
/// * [Icons], for the list of available icons for use with this class
|
||||
/// * [IconButton], for interactive icons.
|
||||
/// * [Icons], for the list of available icons for use with this class.
|
||||
/// * [IconTheme], which provides ambient configuration for icons.
|
||||
class Icon extends StatelessWidget {
|
||||
/// Creates an icon.
|
||||
///
|
||||
/// The [size] argument most not be null.
|
||||
Icon({
|
||||
/// The [size] and [color] default to the value given by the current [IconTheme].
|
||||
const Icon({
|
||||
Key key,
|
||||
this.icon,
|
||||
this.size: 24.0,
|
||||
this.size,
|
||||
this.color
|
||||
}) : super(key: key) {
|
||||
assert(size != null);
|
||||
}
|
||||
}) : super(key: key);
|
||||
|
||||
/// The icon to display. The available icons are described in [Icons].
|
||||
///
|
||||
/// If null, no icon is shown.
|
||||
final IconData icon;
|
||||
|
||||
/// The size of the icon in logical pixels.
|
||||
///
|
||||
/// Icons occupy a square with width and height equal to size.
|
||||
///
|
||||
/// Defaults to the current [IconTheme] size, if any. If there is no
|
||||
/// [IconTheme], or it does not specify an explicit size, then it defaults to
|
||||
/// 24.0.
|
||||
final double size;
|
||||
|
||||
/// The icon to display. The available icons are described in [Icons].
|
||||
final IconData icon;
|
||||
|
||||
/// The color to use when drawing the icon.
|
||||
///
|
||||
/// Defaults to the current [IconTheme] color, if any. If there is
|
||||
@ -56,6 +61,9 @@ class Icon extends StatelessWidget {
|
||||
/// and black if the theme is light. See [Theme] to set the current
|
||||
/// theme and [ThemeData.brightness] for setting the current theme's
|
||||
/// brightness.
|
||||
///
|
||||
/// The given color will be adjusted by the opacity of the current
|
||||
/// [IconTheme], if any.
|
||||
final Color color;
|
||||
|
||||
Color _getDefaultColorForBrightness(Brightness brightness) {
|
||||
@ -75,8 +83,10 @@ class Icon extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final double iconSize = size ?? IconTheme.of(context)?.size ?? 24.0;
|
||||
|
||||
if (icon == null)
|
||||
return new SizedBox(width: size, height: size);
|
||||
return new SizedBox(width: iconSize, height: iconSize);
|
||||
|
||||
final double iconOpacity = IconTheme.of(context)?.opacity ?? 1.0;
|
||||
Color iconColor = color ?? _getDefaultColor(context);
|
||||
@ -85,15 +95,15 @@ class Icon extends StatelessWidget {
|
||||
|
||||
return new ExcludeSemantics(
|
||||
child: new SizedBox(
|
||||
width: size,
|
||||
height: size,
|
||||
width: iconSize,
|
||||
height: iconSize,
|
||||
child: new Center(
|
||||
child: new Text(
|
||||
new String.fromCharCode(icon.codePoint),
|
||||
style: new TextStyle(
|
||||
inherit: false,
|
||||
color: iconColor,
|
||||
fontSize: size,
|
||||
fontSize: iconSize,
|
||||
fontFamily: 'MaterialIcons'
|
||||
)
|
||||
)
|
||||
@ -105,9 +115,14 @@ class Icon extends StatelessWidget {
|
||||
@override
|
||||
void debugFillDescription(List<String> description) {
|
||||
super.debugFillDescription(description);
|
||||
if (icon != null) {
|
||||
description.add('$icon');
|
||||
} else {
|
||||
description.add('<empty>');
|
||||
}
|
||||
if (size != null)
|
||||
description.add('size: $size');
|
||||
if (this.color != null)
|
||||
if (color != null)
|
||||
description.add('color: $color');
|
||||
}
|
||||
}
|
||||
|
@ -7,9 +7,10 @@ import 'package:meta/meta.dart';
|
||||
|
||||
import 'icon_theme_data.dart';
|
||||
|
||||
/// Controls the color and opacity of icons in a widget subtree.
|
||||
/// Controls the default color, opacity, and size of icons in a widget subtree.
|
||||
class IconTheme extends InheritedWidget {
|
||||
/// Creates an icon theme that controls the color and opacity of descendant widgets.
|
||||
/// Creates an icon theme that controls the color, opacity, and size of
|
||||
/// descendant widgets.
|
||||
///
|
||||
/// Both [data] and [child] arguments must not be null.
|
||||
IconTheme({
|
||||
@ -21,7 +22,7 @@ class IconTheme extends InheritedWidget {
|
||||
assert(child != null);
|
||||
}
|
||||
|
||||
/// The color and opacity to use for icons in this subtree.
|
||||
/// The color, opacity, and size to use for icons in this subtree.
|
||||
final IconThemeData data;
|
||||
|
||||
/// The data from the closest instance of this class that encloses the given context.
|
||||
|
@ -5,16 +5,16 @@
|
||||
import 'dart:ui' as ui show lerpDouble;
|
||||
import 'dart:ui' show Color, hashValues;
|
||||
|
||||
/// Defines the color and opacity of icons.
|
||||
/// Defines the color, opacity, and size of icons.
|
||||
///
|
||||
/// Used by [IconTheme] to control the color and opacity of icons in a widget
|
||||
/// subtree.
|
||||
/// Used by [IconTheme] to control the color, opacity, and size of icons in a
|
||||
/// widget subtree.
|
||||
class IconThemeData {
|
||||
/// Creates an icon theme data.
|
||||
///
|
||||
/// The opacity applies to both explicit and default icon colors. The value
|
||||
/// is clamped between 0.0 and 1.0.
|
||||
const IconThemeData({ this.color, double opacity: 1.0 }) : _opacity = opacity;
|
||||
const IconThemeData({ this.color, double opacity: 1.0, this.size }) : _opacity = opacity;
|
||||
|
||||
/// The default color for icons.
|
||||
final Color color;
|
||||
@ -23,25 +23,42 @@ class IconThemeData {
|
||||
double get opacity => (_opacity ?? 1.0).clamp(0.0, 1.0);
|
||||
final double _opacity;
|
||||
|
||||
/// The default size for icons.
|
||||
final double size;
|
||||
|
||||
/// Linearly interpolate between two icon theme data objects.
|
||||
static IconThemeData lerp(IconThemeData begin, IconThemeData end, double t) {
|
||||
return new IconThemeData(
|
||||
color: Color.lerp(begin.color, end.color, t),
|
||||
opacity: ui.lerpDouble(begin.opacity, end.opacity, t)
|
||||
opacity: ui.lerpDouble(begin.opacity, end.opacity, t),
|
||||
size: ui.lerpDouble(begin.size, end.size, t)
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
if (other is! IconThemeData)
|
||||
if (other.runtimeType != runtimeType)
|
||||
return false;
|
||||
final IconThemeData typedOther = other;
|
||||
return color == typedOther.color && opacity == typedOther.opacity;
|
||||
return color == typedOther.color
|
||||
&& opacity == typedOther.opacity
|
||||
&& size == typedOther.size;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(color, opacity);
|
||||
int get hashCode => hashValues(color, opacity, size);
|
||||
|
||||
@override
|
||||
String toString() => '$color';
|
||||
String toString() {
|
||||
List<String> result = <String>[];
|
||||
if (color != null)
|
||||
result.add('color: $color');
|
||||
if (opacity != 1.0)
|
||||
result.add('opacity: $opacity');
|
||||
if (size != null)
|
||||
result.add('size: $size');
|
||||
if (result.length == 0)
|
||||
return '<no theme>';
|
||||
return result.join(', ');
|
||||
}
|
||||
}
|
||||
|
78
packages/flutter/test/material/icon_test.dart
Normal file
78
packages/flutter/test/material/icon_test.dart
Normal file
@ -0,0 +1,78 @@
|
||||
// Copyright 2015 The Chromium 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/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Icon sizing - no theme, default size', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new Center(
|
||||
child: new Icon()
|
||||
)
|
||||
);
|
||||
|
||||
RenderBox renderObject = tester.renderObject(find.byType(Icon));
|
||||
expect(renderObject.size, equals(const Size.square(24.0)));
|
||||
});
|
||||
|
||||
testWidgets('Icon sizing - no theme, explicit size', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new Center(
|
||||
child: new Icon(
|
||||
size: 96.0
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
RenderBox renderObject = tester.renderObject(find.byType(Icon));
|
||||
expect(renderObject.size, equals(const Size.square(96.0)));
|
||||
});
|
||||
|
||||
testWidgets('Icon sizing - sized theme', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new Center(
|
||||
child: new IconTheme(
|
||||
data: new IconThemeData(size: 36.0),
|
||||
child: new Icon()
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
RenderBox renderObject = tester.renderObject(find.byType(Icon));
|
||||
expect(renderObject.size, equals(const Size.square(36.0)));
|
||||
});
|
||||
|
||||
testWidgets('Icon sizing - sized theme, explicit size', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new Center(
|
||||
child: new IconTheme(
|
||||
data: new IconThemeData(size: 36.0),
|
||||
child: new Icon(
|
||||
size: 48.0
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
RenderBox renderObject = tester.renderObject(find.byType(Icon));
|
||||
expect(renderObject.size, equals(const Size.square(48.0)));
|
||||
});
|
||||
|
||||
testWidgets('Icon sizing - sizeless theme, default size', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new Center(
|
||||
child: new IconTheme(
|
||||
data: new IconThemeData(),
|
||||
child: new Icon()
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
RenderBox renderObject = tester.renderObject(find.byType(Icon));
|
||||
expect(renderObject.size, equals(const Size.square(24.0)));
|
||||
});
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user