1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// 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,
}) : 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;
/// 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 semanticsDismissable = dismissible && defaultTargetPlatform != TargetPlatform.android;
return new BlockSemantics(
child: new ExcludeSemantics(
// On Android, the back button is used to dismiss a modal.
excluding: !semanticsDismissable,
child: new GestureDetector(
onTapDown: (TapDownDetails details) {
if (dismissible)
Navigator.pop(context);
},
behavior: HitTestBehavior.opaque,
child: new Semantics(
label: semanticsDismissable ? semanticsLabel : null,
textDirection: semanticsDismissable && semanticsLabel != null ? Directionality.of(context) : null,
child: new ConstrainedBox(
constraints: const BoxConstraints.expand(),
child: color == null ? null : new DecoratedBox(
decoration: new 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,
}) : 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;
@override
Widget build(BuildContext context) {
return new ModalBarrier(
color: color?.value,
dismissible: dismissible,
semanticsLabel: semanticsLabel,
);
}
}