|  | // 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 [dismissable]. | 
|  | /// | 
|  | /// 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 [dismissable]. | 
|  | /// | 
|  | /// 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, | 
|  | ); | 
|  | } | 
|  | } |