Skip to content

RenderAnimatedOpacityMixin causes child pixel snapping when fully opaque #71008

@jonahwilliams

Description

@jonahwilliams

RenderAnimatedOpacityMixin has the following paint method, which avoids painting both the child widget and the opacity later when fully transparent. When fully opaque, the opacity layer is elided while the child is painted. Unfortunately this last optimization causes obvious pixel snapping on low DPR screens.

RenderAnimatedOpacityMixin.paint

 @override
  void paint(PaintingContext context, Offset offset) {
    if (child != null) {
      if (_alpha == 0) {
        // No need to keep the layer. We'll create a new one if necessary.
        layer = null;
        return;
      }
      if (_alpha == 255) {
        // No need to keep the layer. We'll create a new one if necessary.
        layer = null;
        context.paintChild(child!, offset);
        return;
      }
      assert(needsCompositing);
      layer = context.pushOpacity(offset, _alpha!, super.paint, oldLayer: layer as OpacityLayer?);
    }
  }

This can be seen fairly easily when a mouse hover first reveals a tooltip, such as in the "example app" section of the flutter gallery. The last frame visible shifts - fairly dramatically compared to the previous animation. Though the video below uses 10x time dilation to make it more obvious, it is still hard to see in the low res/low framerate GIF.

ezgif-6-2fad4fb28e3e (1)

Keeping the opacity layer even when at fully opaque removes this jump.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Issues that are less important to the Flutter projecta: qualityA truly polished experienceframeworkflutter/packages/flutter repository. See also f: labels.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions