Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
55270099
Unverified
Commit
55270099
authored
Jul 26, 2023
by
Ian Hickson
Committed by
GitHub
Jul 26, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Document the Flow/Opacity/hit-test issues (#131239)
Closes
https://github.com/flutter/flutter/issues/6100
.
parent
8046e133
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
124 additions
and
11 deletions
+124
-11
basic.dart
packages/flutter/lib/src/widgets/basic.dart
+46
-11
implicit_animations.dart
packages/flutter/lib/src/widgets/implicit_animations.dart
+37
-0
transitions.dart
packages/flutter/lib/src/widgets/transitions.dart
+41
-0
No files found.
packages/flutter/lib/src/widgets/basic.dart
View file @
55270099
...
...
@@ -290,6 +290,22 @@ class Directionality extends _UbiquitousInheritedWidget {
/// Drawing content into the offscreen buffer may also trigger render target
/// switches and such switching is particularly slow in older GPUs.
///
/// ## Hit testing
///
/// Setting the [opacity] to zero does not prevent hit testing from being applied
/// to the descendants of the [Opacity] widget. This can be confusing for the
/// user, who may not see anything, and may believe the area of the interface
/// where the [Opacity] is hiding a widget to be non-interactive.
///
/// With certain widgets, such as [Flow], that compute their positions only when
/// they are painted, this can actually lead to bugs (from unexpected geometry
/// to exceptions), because those widgets are not painted by the [Opacity]
/// widget at all when the [opacity] is zero.
///
/// To avoid such problems, it is generally a good idea to use an
/// [IgnorePointer] widget when setting the [opacity] to zero. This prevents
/// interactions with any children in the subtree.
///
/// See also:
///
/// * [Visibility], which can hide a child more efficiently (albeit less
...
...
@@ -5574,27 +5590,46 @@ class Wrap extends MultiChildRenderObjectWidget {
/// this animation and repaint whenever the animation ticks, avoiding both the
/// build and layout phases of the pipeline.
///
/// {@tool dartpad}
/// This example uses the [Flow] widget to create a menu that opens and closes
/// as it is interacted with, shown above. The color of the button in the menu
/// changes to indicate which one has been selected.
///
/// ** See code in examples/api/lib/widgets/basic/flow.0.dart **
/// {@end-tool}
///
/// ## Hit testing and hidden [Flow] widgets
///
/// The [Flow] widget recomputers its children's positions (as used by hit
/// testing) during the _paint_ phase rather than during the _layout_ phase.
///
/// Widgets like [Opacity] avoid painting their children when those children
/// would be invisible due to their opacity being zero.
///
/// Unfortunately, this means that hiding a [Flow] widget using an [Opacity]
/// widget will cause bugs when the user attempts to interact with the hidden
/// region, for example, by tapping it or clicking it.
///
/// Such bugs will manifest either as out-of-date geometry (taps going to
/// different widgets than might be expected by the currently-specified
/// [FlowDelegate]s), or exceptions (e.g. if the last time the [Flow] was
/// painted, a different set of children was specified).
///
/// To avoid this, when hiding a [Flow] widget with an [Opacity] widget (or
/// [AnimatedOpacity] or similar), it is wise to also disable hit testing on the
/// widget by using [IgnorePointer]. This is generally good advice anyway as
/// hit-testing invisible widgets is often confusing for the user.
///
/// See also:
///
/// * [Wrap], which provides the layout model that some other frameworks call
/// "flow", and is otherwise unrelated to [Flow].
/// * [FlowDelegate], which controls the visual presentation of the children.
/// * [Stack], which arranges children relative to the edges of the container.
/// * [CustomSingleChildLayout], which uses a delegate to control the layout of
/// a single child.
/// * [CustomMultiChildLayout], which uses a delegate to position multiple
/// children.
/// * The [catalog of layout widgets](https://flutter.dev/widgets/layout/).
///
///
/// {@tool dartpad}
/// This example uses the [Flow] widget to create a menu that opens and closes
/// as it is interacted with, shown above. The color of the button in the menu
/// changes to indicate which one has been selected.
///
/// ** See code in examples/api/lib/widgets/basic/flow.0.dart **
/// {@end-tool}
///
class
Flow
extends
MultiChildRenderObjectWidget
{
/// Creates a flow layout.
///
...
...
packages/flutter/lib/src/widgets/implicit_animations.dart
View file @
55270099
...
...
@@ -1674,6 +1674,24 @@ class _AnimatedSlideState extends ImplicitlyAnimatedWidgetState<AnimatedSlide> {
/// ```
/// {@end-tool}
///
/// ## Hit testing
///
/// Setting the [opacity] to zero does not prevent hit testing from being
/// applied to the descendants of the [AnimatedOpacity] widget. This can be
/// confusing for the user, who may not see anything, and may believe the area
/// of the interface where the [AnimatedOpacity] is hiding a widget to be
/// non-interactive.
///
/// With certain widgets, such as [Flow], that compute their positions only when
/// they are painted, this can actually lead to bugs (from unexpected geometry
/// to exceptions), because those widgets are not painted by the [AnimatedOpacity]
/// widget at all when the [opacity] animation reaches zero.
///
/// To avoid such problems, it is generally a good idea to use an
/// [IgnorePointer] widget when setting the [opacity] to zero. This prevents
/// interactions with any children in the subtree when the [child] is animating
/// away.
///
/// See also:
///
/// * [AnimatedCrossFade], for fading between two children.
...
...
@@ -1771,6 +1789,25 @@ class _AnimatedOpacityState extends ImplicitlyAnimatedWidgetState<AnimatedOpacit
/// ** See code in examples/api/lib/widgets/implicit_animations/sliver_animated_opacity.0.dart **
/// {@end-tool}
///
/// ## Hit testing
///
/// Setting the [opacity] to zero does not prevent hit testing from being
/// applied to the descendants of the [SliverAnimatedOpacity] widget. This can
/// be confusing for the user, who may not see anything, and may believe the
/// area of the interface where the [SliverAnimatedOpacity] is hiding a widget
/// to be non-interactive.
///
/// With certain widgets, such as [Flow], that compute their positions only when
/// they are painted, this can actually lead to bugs (from unexpected geometry
/// to exceptions), because those widgets are not painted by the
/// [SliverAnimatedOpacity] widget at all when the [opacity] animation reaches
/// zero.
///
/// To avoid such problems, it is generally a good idea to use a
/// [SliverIgnorePointer] widget when setting the [opacity] to zero. This
/// prevents interactions with any children in the subtree when the [sliver] is
/// animating away.
///
/// See also:
///
/// * [SliverFadeTransition], an explicitly animated version of this widget, where
...
...
packages/flutter/lib/src/widgets/transitions.dart
View file @
55270099
...
...
@@ -507,6 +507,26 @@ class SizeTransition extends AnimatedWidget {
/// ** See code in examples/api/lib/widgets/transitions/fade_transition.0.dart **
/// {@end-tool}
///
/// ## Hit testing
///
/// Setting the [opacity] to zero does not prevent hit testing from being
/// applied to the descendants of the [FadeTransition] widget. This can be
/// confusing for the user, who may not see anything, and may believe the area
/// of the interface where the [FadeTransition] is hiding a widget to be
/// non-interactive.
///
/// With certain widgets, such as [Flow], that compute their positions only when
/// they are painted, this can actually lead to bugs (from unexpected geometry
/// to exceptions), because those widgets are not painted by the [FadeTransition]
/// widget at all when the [opacity] animation reaches zero.
///
/// To avoid such problems, it is generally a good idea to combine this widget
/// with an [IgnorePointer] that one enables when the [opacity] animation
/// reaches zero. This prevents interactions with any children in the subtree
/// when the [child] is not visible. For performance reasons, when implementing
/// this, care should be taken not to rebuild the relevant widget (e.g. by
/// calling [State.setState]) except at the transition point.
///
/// See also:
///
/// * [Opacity], which does not animate changes in opacity.
...
...
@@ -580,6 +600,27 @@ class FadeTransition extends SingleChildRenderObjectWidget {
///
/// {@animation 300 378 https://flutter.github.io/assets-for-api-docs/assets/widgets/fade_transition.mp4}
///
/// ## Hit testing
///
/// Setting the [opacity] to zero does not prevent hit testing from being
/// applied to the descendants of the [SliverFadeTransition] widget. This can be
/// confusing for the user, who may not see anything, and may believe the area
/// of the interface where the [SliverFadeTransition] is hiding a widget to be
/// non-interactive.
///
/// With certain widgets, such as [Flow], that compute their positions only when
/// they are painted, this can actually lead to bugs (from unexpected geometry
/// to exceptions), because those widgets are not painted by the
/// [SliverFadeTransition] widget at all when the [opacity] animation reaches
/// zero.
///
/// To avoid such problems, it is generally a good idea to combine this widget
/// with a [SliverIgnorePointer] that one enables when the [opacity] animation
/// reaches zero. This prevents interactions with any children in the subtree
/// when the [sliver] is not visible. For performance reasons, when implementing
/// this, care should be taken not to rebuild the relevant widget (e.g. by
/// calling [State.setState]) except at the transition point.
///
/// See also:
///
/// * [SliverOpacity], which does not animate changes in opacity.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment