mirror of https://github.com/flutter/samples.git
Updates detail screen to new, modal design. (#40)
parent
bfb8b8aea9
commit
6ce0d22e9b
@ -0,0 +1,131 @@
|
||||
// Copyright 2018 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:veggieseasons/styles.dart';
|
||||
|
||||
/// Partially overlays and then blurs its child.
|
||||
class FrostedBox extends StatelessWidget {
|
||||
const FrostedBox({
|
||||
this.child,
|
||||
Key key,
|
||||
}) : super(key: key);
|
||||
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: Styles.frostedBackground,
|
||||
),
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// An Icon that implicitly animates changes to its color.
|
||||
class ColorChangingIcon extends ImplicitlyAnimatedWidget {
|
||||
const ColorChangingIcon(
|
||||
this.icon, {
|
||||
this.color = CupertinoColors.black,
|
||||
this.size,
|
||||
@required Duration duration,
|
||||
Key key,
|
||||
}) : assert(icon != null),
|
||||
assert(color != null),
|
||||
assert(duration != null),
|
||||
super(key: key, duration: duration);
|
||||
|
||||
final Color color;
|
||||
|
||||
final IconData icon;
|
||||
|
||||
final double size;
|
||||
|
||||
@override
|
||||
_ColorChangingIconState createState() => _ColorChangingIconState();
|
||||
}
|
||||
|
||||
class _ColorChangingIconState
|
||||
extends AnimatedWidgetBaseState<ColorChangingIcon> {
|
||||
ColorTween _colorTween;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Icon(
|
||||
widget.icon,
|
||||
size: widget.size,
|
||||
color: _colorTween?.evaluate(animation),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void forEachTween(visitor) {
|
||||
_colorTween = visitor(
|
||||
_colorTween,
|
||||
widget.color,
|
||||
(dynamic value) => ColorTween(begin: value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// A simple "close this modal" button that invokes a callback when pressed.
|
||||
class CloseButton extends StatefulWidget {
|
||||
const CloseButton(this.onPressed);
|
||||
|
||||
final VoidCallback onPressed;
|
||||
|
||||
@override
|
||||
CloseButtonState createState() {
|
||||
return new CloseButtonState();
|
||||
}
|
||||
}
|
||||
|
||||
class CloseButtonState extends State<CloseButton> {
|
||||
bool tapInProgress = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTapDown: (details) {
|
||||
setState(() => tapInProgress = true);
|
||||
},
|
||||
onTapUp: (details) {
|
||||
setState(() => tapInProgress = false);
|
||||
widget.onPressed();
|
||||
},
|
||||
onTapCancel: () {
|
||||
setState(() => tapInProgress = false);
|
||||
},
|
||||
child: ClipOval(
|
||||
child: FrostedBox(
|
||||
child: Container(
|
||||
width: 30,
|
||||
height: 30,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
),
|
||||
child: Center(
|
||||
child: ColorChangingIcon(
|
||||
CupertinoIcons.clear_thick,
|
||||
duration: Duration(milliseconds: 300),
|
||||
color: tapInProgress
|
||||
? Styles.closeButtonPressed
|
||||
: Styles.closeButtonUnpressed,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in new issue