modal_barrier.dart 5.25 KB
Newer Older
Adam Barth's avatar
Adam Barth committed
1 2 3 4
// 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.

5 6
import 'package:flutter/foundation.dart';

Adam Barth's avatar
Adam Barth committed
7
import 'basic.dart';
8
import 'container.dart';
9
import 'debug.dart';
Adam Barth's avatar
Adam Barth committed
10
import 'framework.dart';
Hixie's avatar
Hixie committed
11
import 'gesture_detector.dart';
Adam Barth's avatar
Adam Barth committed
12
import 'navigator.dart';
13 14
import 'transitions.dart';

15
/// A widget that prevents the user from interacting with widgets behind itself.
16 17 18 19 20 21 22 23 24 25 26 27 28
///
/// 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.
29
class ModalBarrier extends StatelessWidget {
30
  /// Creates a widget that blocks user interaction.
31
  const ModalBarrier({
32
    Key key,
Hixie's avatar
Hixie committed
33
    this.color,
34
    this.dismissible = true,
35
    this.semanticsLabel,
36 37
  }) : super(key: key);

38
  /// If non-null, fill the barrier with this color.
39 40 41 42 43
  ///
  /// See also:
  ///
  ///  * [ModalRoute.barrierColor], which controls this property for the
  ///    [ModalBarrier] built by [ModalRoute] pages.
44
  final Color color;
45 46

  /// Whether touching the barrier will pop the current route off the [Navigator].
47 48 49 50 51
  ///
  /// See also:
  ///
  ///  * [ModalRoute.barrierDismissible], which controls this property for the
  ///    [ModalBarrier] built by [ModalRoute] pages.
52
  final bool dismissible;
Adam Barth's avatar
Adam Barth committed
53

54 55 56 57 58 59 60 61 62 63 64
  /// 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;

65
  @override
Adam Barth's avatar
Adam Barth committed
66
  Widget build(BuildContext context) {
67
    assert(!dismissible || semanticsLabel == null || debugCheckHasDirectionality(context));
68
    final bool semanticsDismissible = dismissible && defaultTargetPlatform != TargetPlatform.android;
69 70
    return new BlockSemantics(
      child: new ExcludeSemantics(
71
        // On Android, the back button is used to dismiss a modal.
72
        excluding: !semanticsDismissible,
73 74 75 76 77 78 79
        child: new GestureDetector(
          onTapDown: (TapDownDetails details) {
            if (dismissible)
              Navigator.pop(context);
          },
          behavior: HitTestBehavior.opaque,
          child: new Semantics(
80 81
            label: semanticsDismissible ? semanticsLabel : null,
            textDirection: semanticsDismissible && semanticsLabel != null ? Directionality.of(context) : null,
82 83 84 85
            child: new ConstrainedBox(
              constraints: const BoxConstraints.expand(),
              child: color == null ? null : new DecoratedBox(
                decoration: new BoxDecoration(
86
                  color: color,
87
                )
88
              )
Hixie's avatar
Hixie committed
89
            )
Adam Barth's avatar
Adam Barth committed
90 91
          )
        )
92 93 94 95 96
      )
    );
  }
}

97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
/// 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.
113
class AnimatedModalBarrier extends AnimatedWidget {
114
  /// Creates a widget that blocks user interaction.
115
  const AnimatedModalBarrier({
116
    Key key,
117
    Animation<Color> color,
118
    this.dismissible = true,
119
    this.semanticsLabel,
120
  }) : super(key: key, listenable: color);
121

122
  /// If non-null, fill the barrier with this color.
123 124 125 126 127
  ///
  /// See also:
  ///
  ///  * [ModalRoute.barrierColor], which controls this property for the
  ///    [AnimatedModalBarrier] built by [ModalRoute] pages.
128
  Animation<Color> get color => listenable;
129 130

  /// Whether touching the barrier will pop the current route off the [Navigator].
131 132 133 134 135
  ///
  /// See also:
  ///
  ///  * [ModalRoute.barrierDismissible], which controls this property for the
  ///    [AnimatedModalBarrier] built by [ModalRoute] pages.
136
  final bool dismissible;
137

138 139 140 141 142 143 144 145 146 147
  /// 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;

148
  @override
149
  Widget build(BuildContext context) {
150
    return new ModalBarrier(
151
      color: color?.value,
152
      dismissible: dismissible,
153
      semanticsLabel: semanticsLabel,
154 155 156
    );
  }
}