fix: InteractiveViewer failing to render when alignment is set - #6887
Merged
Merged
Conversation
InteractiveViewer handed the raw property value, a {x, y} map, to
Flutter's InteractiveViewer(alignment:). On native and wasm clients the
implicit cast in Control.get threw a TypeError while building, so the
viewer was replaced by Flutter's error box. JS web builds skip that
check, so the map reached Transform and the viewer painted nothing,
raising a NoSuchMethodError on every frame or pointer event over it.
Read it with getAlignment, as before the 1.0 rewrite.
The docstring described alignment as the position of the content. In
Flutter it is the origin of the zoom transform: it never moves the
content, and gestures and the pan() limits assume a top-left origin.
Document that, and point to Container.alignment for positioning.
Deploying flet-website-v2 with
|
| Latest commit: |
0ff1ca0
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://530e609e.flet-website-v2.pages.dev |
| Branch Preview URL: | https://fix-interactive-viewer-align.flet-website-v2.pages.dev |
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The regression test described in the PR is absent from the changes.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
What changed in this PR
Fixes InteractiveViewer rendering failures by parsing alignment into Flutter’s expected type and clarifying its transformation semantics.
Changes:
- Parse wire-format alignment values with
getAlignment. - Clarify alignment behavior and limitations.
- Add a 1.0.2 changelog entry.
| File | Description |
|---|---|
CHANGELOG.md |
Records the bug fix. |
packages/flet/lib/src/controls/interactive_viewer.dart |
Parses alignment values correctly. |
sdk/python/packages/flet/src/flet/controls/core/interactive_viewer.py |
Documents alignment semantics. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The docs page shows only main.py, so code copied from it fails without the example's assets/viper.mp3. The example intro now points at that file and at using a URL for src instead. The project description no longer calls the track remote.
A client found in build/<platform> is launched ahead of the standard one. On Windows and Linux this was never logged, and on macOS only with -v, so a client built before an extension was added went unnoticed: calls to that extension just timed out. All three platforms now log a warning with the client's path, which is shown without -v.
FeodorFitsner
approved these changes
Sep 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Problem
InteractiveViewerpassed itsalignmentproperty to Flutter'sInteractiveViewer(alignment:)unparsed.Control.get<T>infersTfrom the parameter and returns the wire value, an{x, y}map, as is, so anyalignmentfailed the cast inbuild():Flutter then replaced the viewer with its error widget, a grey box in release builds, and the message only reached Python as
page.on_error. JS web builds omit that implicit cast (dart2js-O4), so there the map reachedTransformand the viewer painted nothing, raising aNoSuchMethodErrorfor every frame or pointer event that touched it. 0.28.x parsed the value withparseAlignment; the parser was lost in the 1.0 rewrite, so this has been broken since 0.80.0.Fixes #6744
Changes
alignmentwithgetAlignment.alignmentwas described as the position of the content. Flutter passes it toTransform.alignment, so it is the origin the content is scaled around and never moves the content. The docstring now says so and points toContainer.alignmentfor positioning, and notes that gestures and thepan()limits assume a top-left origin.Not in this PR: making
alignmentposition the content instead (by wrapping it inAlign), and hardeningControl.get<T>so a mistyped value fails with the control and property name. #6684 was the same cast bug inGestureDetector.Testing
Controltree reproduced the cast error onmainand passed with the fix. It also checked that the parsed value reaches Flutter'sInteractiveViewerand that nothing is passed whenalignmentis unset. The existingpackages/flettests pass.mainan empty viewer. A web client built from this branch renders the content with nopage.on_errorreports.alignment=Alignment.CENTER: one wheel tick moves the point under the pointer by about (-47, -34) px, and at 2.5× the pan limits are off by (-675, -487) px; with no alignment both are exact.zoom(2)scales around the center, butpan()then stops short of one edge.flutter analyze,dart formatand ruff.Test code
Summary by Sourcery
Fix
InteractiveVieweralignment handling and improve diagnostics and documentation for reused desktop clients and the audio example.Bug Fixes:
InteractiveViewerrendering failures when itsalignmentproperty is set by correctly converting the alignment value before passing it to Flutter.Enhancements:
InteractiveViewer.alignmentcontrols the transformation origin rather than content placement, including the implications for gestures and panning.Documentation:
Chores: