| 1 | // Copyright 2014 The Flutter Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | /// @docImport 'package:flutter/material.dart'; |
| 6 | library; |
| 7 | |
| 8 | import 'package:flutter/rendering.dart'; |
| 9 | |
| 10 | import 'basic.dart'; |
| 11 | import 'framework.dart'; |
| 12 | import 'icon.dart'; |
| 13 | import 'icon_theme.dart'; |
| 14 | import 'icon_theme_data.dart'; |
| 15 | import 'image.dart'; |
| 16 | |
| 17 | /// An icon that comes from an [ImageProvider], e.g. an [AssetImage]. |
| 18 | /// |
| 19 | /// See also: |
| 20 | /// |
| 21 | /// * [IconButton], for interactive icons. |
| 22 | /// * [IconTheme], which provides ambient configuration for icons. |
| 23 | /// * [Icon], for icons based on glyphs from fonts instead of images. |
| 24 | /// * [Icons], the library of Material Icons. |
| 25 | class ImageIcon extends StatelessWidget { |
| 26 | /// Creates an image icon. |
| 27 | /// |
| 28 | /// The [size] and [color] default to the value given by the current [IconTheme]. |
| 29 | const ImageIcon(this.image, {super.key, this.size, this.color, this.semanticLabel}); |
| 30 | |
| 31 | /// The image to display as the icon. |
| 32 | /// |
| 33 | /// The icon can be null, in which case the widget will render as an empty |
| 34 | /// space of the specified [size]. |
| 35 | final ImageProvider? image; |
| 36 | |
| 37 | /// The size of the icon in logical pixels. |
| 38 | /// |
| 39 | /// Icons occupy a square with width and height equal to size. |
| 40 | /// |
| 41 | /// Defaults to the current [IconTheme] size, if any. If there is no |
| 42 | /// [IconTheme], or it does not specify an explicit size, then it defaults to |
| 43 | /// 24.0. |
| 44 | final double? size; |
| 45 | |
| 46 | /// The color to use when drawing the icon. |
| 47 | /// |
| 48 | /// Defaults to the current [IconTheme] color, if any. If there is |
| 49 | /// no [IconTheme], then it defaults to not recolorizing the image. |
| 50 | /// |
| 51 | /// The image will be additionally adjusted by the opacity of the current |
| 52 | /// [IconTheme], if any. |
| 53 | final Color? color; |
| 54 | |
| 55 | /// Semantic label for the icon. |
| 56 | /// |
| 57 | /// Announced by assistive technologies (e.g TalkBack/VoiceOver). |
| 58 | /// This label does not show in the UI. |
| 59 | /// |
| 60 | /// * [SemanticsProperties.label], which is set to [semanticLabel] in the |
| 61 | /// underlying [Semantics] widget. |
| 62 | final String? semanticLabel; |
| 63 | |
| 64 | @override |
| 65 | Widget build(BuildContext context) { |
| 66 | final IconThemeData iconTheme = IconTheme.of(context); |
| 67 | final double? iconSize = size ?? iconTheme.size; |
| 68 | |
| 69 | if (image == null) { |
| 70 | return Semantics( |
| 71 | label: semanticLabel, |
| 72 | child: SizedBox(width: iconSize, height: iconSize), |
| 73 | ); |
| 74 | } |
| 75 | |
| 76 | final double? iconOpacity = iconTheme.opacity; |
| 77 | Color iconColor = color ?? iconTheme.color!; |
| 78 | |
| 79 | if (iconOpacity != null && iconOpacity != 1.0) { |
| 80 | iconColor = iconColor.withOpacity(iconColor.opacity * iconOpacity); |
| 81 | } |
| 82 | |
| 83 | return Semantics( |
| 84 | label: semanticLabel, |
| 85 | child: Image( |
| 86 | image: image!, |
| 87 | width: iconSize, |
| 88 | height: iconSize, |
| 89 | color: iconColor, |
| 90 | fit: BoxFit.scaleDown, |
| 91 | excludeFromSemantics: true, |
| 92 | ), |
| 93 | ); |
| 94 | } |
| 95 | |
| 96 | @override |
| 97 | void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
| 98 | super.debugFillProperties(properties); |
| 99 | properties.add( |
| 100 | DiagnosticsProperty<ImageProvider>('image' , image, ifNull: '<empty>' , showName: false), |
| 101 | ); |
| 102 | properties.add(DoubleProperty('size' , size, defaultValue: null)); |
| 103 | properties.add(ColorProperty('color' , color, defaultValue: null)); |
| 104 | } |
| 105 | } |
| 106 | |