Ink class

A convenience widget for drawing images and other decorations on Material widgets, so that InkWell and InkResponse splashes will render over them.

Ink splashes and highlights, as rendered by InkWell and InkResponse, draw on the actual underlying Material, under whatever widgets are drawn over the material (such as Text and Icons). If an opaque image is drawn over the Material (maybe using a Container or DecoratedBox), these ink effects will not be visible, as they will be entirely obscured by the opaque graphics drawn above the Material.

This widget draws the given Decoration directly on the Material, in the same way that InkWell and InkResponse draw there. This allows the splashes to be drawn above the otherwise opaque graphics.

An alternative solution is to use a MaterialType.transparency material above the opaque graphics, so that the ink responses from InkWells and InkResponses will be drawn on the transparent material on top of the opaque graphics, rather than under the opaque graphics on the underlying Material.

Limitations

This widget is subject to the same limitations as other ink effects, as described in the documentation for Material. Most notably, the position of an Ink widget must not change during the lifetime of the Material object unless a LayoutChangedNotification is dispatched each frame that the position changes. This is done automatically for ListView and other scrolling widgets, but is not done for animated transitions such as SlideTransition.

Additionally, if multiple Ink widgets paint on the same Material in the same location, their relative order is not guaranteed. The decorations will be painted in the order that they were added to the material, which generally speaking will match the order they are given in the widget tree, but this order may appear to be somewhat random in more dynamic situations.

This example shows how a Material widget can have a yellow rectangle drawn on it using Ink, while still having ink effects over the yellow rectangle:
link
Material(
  color: Colors.teal[900],
  child: Center(
    child: Ink(
      color: Colors.yellow,
      width: 200.0,
      height: 100.0,
      child: InkWell(
        onTap: () { /* ... */ },
        child: const Center(
          child: Text('YELLOW'),
        )
      ),
    ),
  ),
)

The following example shows how an image can be printed on a Material widget with an InkWell above it:
link
Material(
  color: Colors.grey[800],
  child: Center(
    child: Ink.image(
      image: const AssetImage('cat.jpeg'),
      fit: BoxFit.cover,
      width: 300.0,
      height: 200.0,
      child: InkWell(
        onTap: () { /* ... */ },
        child: const Align(
          alignment: Alignment.topLeft,
          child: Padding(
            padding: EdgeInsets.all(10.0),
            child: Text(
              'KITTEN',
              style: TextStyle(
                fontWeight: FontWeight.w900,
                color: Colors.white,
              ),
            ),
          ),
        )
      ),
    ),
  ),
)

What to do if you want to clip this Ink.image?

Wrapping the Ink in a clipping widget directly will not work since the Material it will be printed on is responsible for clipping.

In this example the image is not being clipped as expected. This is because it is being rendered onto the Scaffold body Material, which isn't wrapped in the ClipRRect.

link

To create a local project with this code sample, run:
flutter create --sample=material.Ink.3 mysample

One solution would be to deliberately wrap the Ink.image in a Material. This makes sure the Material that the image is painted on is also responsible for clipping said content.
link

To create a local project with this code sample, run:
flutter create --sample=material.Ink.4 mysample

See also:

Inheritance

Constructors

Ink({Key? key, EdgeInsetsGeometry? padding, Color? color, Decoration? decoration, double? width, double? height, Widget? child})
Paints a decoration (which can be a simple color) on a Material.
Ink.image({Key? key, EdgeInsetsGeometry? padding, required ImageProvider<Object> image, ImageErrorListener? onImageError, ColorFilter? colorFilter, BoxFit? fit, AlignmentGeometry alignment = Alignment.center, Rect? centerSlice, ImageRepeat repeat = ImageRepeat.noRepeat, bool matchTextDirection = false, double? width, double? height, Widget? child})
Creates a widget that shows an image (obtained from an ImageProvider) on a Material.

Properties

child Widget?
The child contained by the container.
final
decoration Decoration?
The decoration to paint on the nearest ancestor Material widget.
final
hashCode int
The hash code for this object.
no setterinherited
height double?
A height to apply to the decoration and the child. The height includes any padding.
final
key Key?
Controls how one widget replaces another widget in the tree.
finalinherited
padding EdgeInsetsGeometry?
Empty space to inscribe inside the decoration. The child, if any, is placed inside this padding.
final
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
width double?
A width to apply to the decoration and the child. The width includes any padding.
final

Methods

createElement() StatefulElement
Creates a StatefulElement to manage this widget's location in the tree.
inherited
createState() State<Ink>
Creates the mutable state for this widget at a given location in the tree.
override
debugDescribeChildren() List<DiagnosticsNode>
Returns a list of DiagnosticsNode objects describing this node's children.
inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node.
override
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep.
inherited
toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) String
A string representation of this object.
inherited
toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) String
Returns a string representation of this node and its descendants.
inherited
toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) String
Returns a one-line detailed description of the object.
inherited
toStringShort() String
A short, textual description of this widget.
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited