| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:flutter/foundation.dart'; |
| |
| import 'basic.dart'; |
| import 'container.dart'; |
| import 'debug.dart'; |
| import 'framework.dart'; |
| import 'gesture_detector.dart'; |
| import 'navigator.dart'; |
| import 'transitions.dart'; |
| |
| /// A widget that prevents the user from interacting with widgets behind itself. |
| /// |
| /// The modal barrier is the scrim that is rendered behind each route, which |
| /// generally prevents the user from interacting with the route below the |
| /// current route, and normally partially obscures such routes. |
| /// |
| /// For example, when a dialog is on the screen, the page below the dialog is |
| /// usually darkened by the modal barrier. |
| /// |
| /// See also: |
| /// |
| /// * [ModalRoute], which indirectly uses this widget. |
| /// * [AnimatedModalBarrier], which is similar but takes an animated [color] |
| /// instead of a single color value. |
| class ModalBarrier extends StatelessWidget { |
| /// Creates a widget that blocks user interaction. |
| const ModalBarrier({ |
| Key key, |
| this.color, |
| this.dismissible = true, |
| this.semanticsLabel, |
| this.barrierSemanticsDismissible = true, |
| }) : super(key: key); |
| |
| /// If non-null, fill the barrier with this color. |
| /// |
| /// See also: |
| /// |
| /// * [ModalRoute.barrierColor], which controls this property for the |
| /// [ModalBarrier] built by [ModalRoute] pages. |
| final Color color; |
| |
| /// Whether touching the barrier will pop the current route off the [Navigator]. |
| /// |
| /// See also: |
| /// |
| /// * [ModalRoute.barrierDismissible], which controls this property for the |
| /// [ModalBarrier] built by [ModalRoute] pages. |
| final bool dismissible; |
| |
| /// Whether the modal barrier semantics are included in the semantics tree. |
| /// |
| /// See also: |
| /// |
| /// * [ModalRoute.semanticsDismissible], which controls this property for |
| /// the [ModalBarrier] built by [ModalRoute] pages. |
| final bool barrierSemanticsDismissible; |
| |
| /// Semantics label used for the barrier if it is [dismissible]. |
| /// |
| /// The semantics label is read out by accessibility tools (e.g. TalkBack |
| /// on Android and VoiceOver on iOS) when the barrier is focused. |
| /// |
| /// See also: |
| /// |
| /// * [ModalRoute.barrierLabel], which controls this property for the |
| /// [ModalBarrier] built by [ModalRoute] pages. |
| final String semanticsLabel; |
| |
| @override |
| Widget build(BuildContext context) { |
| assert(!dismissible || semanticsLabel == null || debugCheckHasDirectionality(context)); |
| final bool semanticsDismissible = dismissible && defaultTargetPlatform != TargetPlatform.android; |
| final bool modalBarrierSemanticsDismissible = barrierSemanticsDismissible ?? semanticsDismissible; |
| return BlockSemantics( |
| child: ExcludeSemantics( |
| // On Android, the back button is used to dismiss a modal. On iOS, some |
| // modal barriers are not dismissible in accessibility mode. |
| excluding: !semanticsDismissible || !modalBarrierSemanticsDismissible, |
| child: GestureDetector( |
| onTapDown: (TapDownDetails details) { |
| if (dismissible) |
| Navigator.maybePop(context); |
| }, |
| behavior: HitTestBehavior.opaque, |
| child: Semantics( |
| label: semanticsDismissible ? semanticsLabel : null, |
| textDirection: semanticsDismissible && semanticsLabel != null ? Directionality.of(context) : null, |
| child: ConstrainedBox( |
| constraints: const BoxConstraints.expand(), |
| child: color == null ? null : DecoratedBox( |
| decoration: BoxDecoration( |
| color: color, |
| ), |
| ), |
| ), |
| ), |
| ), |
| ), |
| ); |
| } |
| } |
| |
| /// A widget that prevents the user from interacting with widgets behind itself, |
| /// and can be configured with an animated color value. |
| /// |
| /// The modal barrier is the scrim that is rendered behind each route, which |
| /// generally prevents the user from interacting with the route below the |
| /// current route, and normally partially obscures such routes. |
| /// |
| /// For example, when a dialog is on the screen, the page below the dialog is |
| /// usually darkened by the modal barrier. |
| /// |
| /// This widget is similar to [ModalBarrier] except that it takes an animated |
| /// [color] instead of a single color. |
| /// |
| /// See also: |
| /// |
| /// * [ModalRoute], which uses this widget. |
| class AnimatedModalBarrier extends AnimatedWidget { |
| /// Creates a widget that blocks user interaction. |
| const AnimatedModalBarrier({ |
| Key key, |
| Animation<Color> color, |
| this.dismissible = true, |
| this.semanticsLabel, |
| this.barrierSemanticsDismissible, |
| }) : super(key: key, listenable: color); |
| |
| /// If non-null, fill the barrier with this color. |
| /// |
| /// See also: |
| /// |
| /// * [ModalRoute.barrierColor], which controls this property for the |
| /// [AnimatedModalBarrier] built by [ModalRoute] pages. |
| Animation<Color> get color => listenable; |
| |
| /// Whether touching the barrier will pop the current route off the [Navigator]. |
| /// |
| /// See also: |
| /// |
| /// * [ModalRoute.barrierDismissible], which controls this property for the |
| /// [AnimatedModalBarrier] built by [ModalRoute] pages. |
| final bool dismissible; |
| |
| /// Semantics label used for the barrier if it is [dismissible]. |
| /// |
| /// The semantics label is read out by accessibility tools (e.g. TalkBack |
| /// on Android and VoiceOver on iOS) when the barrier is focused. |
| /// See also: |
| /// |
| /// * [ModalRoute.barrierLabel], which controls this property for the |
| /// [ModalBarrier] built by [ModalRoute] pages. |
| final String semanticsLabel; |
| |
| /// Whether the modal barrier semantics are included in the semantics tree. |
| /// |
| /// See also: |
| /// |
| /// * [ModalRoute.semanticsDismissible], which controls this property for |
| /// the [ModalBarrier] built by [ModalRoute] pages. |
| final bool barrierSemanticsDismissible; |
| |
| @override |
| Widget build(BuildContext context) { |
| return ModalBarrier( |
| color: color?.value, |
| dismissible: dismissible, |
| semanticsLabel: semanticsLabel, |
| barrierSemanticsDismissible: barrierSemanticsDismissible, |
| ); |
| } |
| } |