展开时,Flutter Interactive Viewer 子项不在堆栈顶部
Flutter Interactive Viewer child not on top of stack when expanded
对于一列包含一行两个容器的屏幕,每个容器显示一个图像,行下方有一个撤消 FlatButton,当我将 InteractiveViewer 用于行中的第二个时,它工作得很好,但对于第一个,当它已展开,图像顶部有撤消按钮。
希望当其中一个容器与交互式查看器一起使用时,它们位于视图的顶部。
还希望 Interactive Viewer 容器在长按时进入全屏并在松开长按时退出全屏。
final TransformationController _transformationController =
TransformationController();
Animation<Matrix4> _animationReset;
AnimationController _controllerReset;
void _onAnimateReset() {
_transformationController.value = _animationReset.value;
if (!_controllerReset.isAnimating) {
_animationReset?.removeListener(_onAnimateReset);
_animationReset = null;
_controllerReset.reset();
}
}
void _animateResetInitialize() {
_controllerReset.reset();
_animationReset = Matrix4Tween(
begin: _transformationController.value,
end: Matrix4.identity(),
).animate(_controllerReset);
_animationReset.addListener(_onAnimateReset);
_controllerReset.forward();
}
void _animateResetStop() {
_controllerReset.stop();
_animationReset?.removeListener(_onAnimateReset);
_animationReset = null;
_controllerReset.reset();
}
void _onInteractionStart(ScaleStartDetails details) {
// If the user tries to cause a transformation while the reset animation is
// running, cancel the reset animation.
if (_controllerReset.status == AnimationStatus.forward) {
_animateResetStop();
}
}
void _onInteractionEnd(ScaleEndDetails details) {
_animateResetInitialize();
}
final TransformationController _transformationController2 =
TransformationController();
Animation<Matrix4> _animationReset2;
AnimationController _controllerReset2;
void _onAnimateReset2() {
_transformationController2.value = _animationReset2.value;
if (!_controllerReset2.isAnimating) {
_animationReset2?.removeListener(_onAnimateReset2);
_animationReset2 = null;
_controllerReset2.reset();
}
}
void _animateResetInitialize2() {
_controllerReset2.reset();
_animationReset2 = Matrix4Tween(
begin: _transformationController2.value,
end: Matrix4.identity(),
).animate(_controllerReset2);
_animationReset2.addListener(_onAnimateReset2);
_controllerReset2.forward();
}
void _animateResetStop2() {
_controllerReset2.stop();
_animationReset2?.removeListener(_onAnimateReset2);
_animationReset2 = null;
_controllerReset2.reset();
}
void _onInteractionStart2(ScaleStartDetails details) {
// If the user tries to cause a transformation while the reset animation is
// running, cancel the reset animation.
if (_controllerReset2.status == AnimationStatus.forward) {
_animateResetStop2();
}
}
void _onInteractionEnd2(ScaleEndDetails details) {
_animateResetInitialize2();
}
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: BGColor,
appBar: AppBar(
backgroundColor: PrimaryColor,
title: Text('App\'name',
style: TextStyle(
color: Colors.white
),
),
leading: GestureDetector(
onTap: () {
Navigator.of(context).pop();},
child: Padding(
padding: EdgeInsets.only(top: 19.0, left: 12.0),
child: Text('Quit',
style: TextStyle(
color: Colors.white54,
fontSize: 18.0,
),
),
),
),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Flexible(
flex: 1,
child: tapInstruct(),
),
SizedBox(height: 5.0),
Flexible(
flex: 9,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 1,
child: InteractiveViewer(
boundaryMargin: EdgeInsets.all(double.infinity),
transformationController: _transformationController,
minScale: 1.0,
maxScale: 5,
onInteractionStart: _onInteractionStart,
onInteractionEnd: _onInteractionEnd,
panEnabled: false,
child: Container(
//margin: EdgeInsets.all(10.0),
child: GestureDetector(
onTap: () => _leftCardTapped(),
child: Padding(
padding: const EdgeInsets.all(2.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(15.0),
child: Image.file(
favpicz[lcn]
// fit: BoxFit.fitHeight,
),
),
),
// ),
),
),
),
),
Divider(
thickness: 2.0,
),
Expanded(
flex: 1,
child: InteractiveViewer(
boundaryMargin: EdgeInsets.all(double.infinity),
transformationController: _transformationController2,
minScale: 1.0,
maxScale: 5,
onInteractionStart: _onInteractionStart2,
onInteractionEnd: _onInteractionEnd2,
panEnabled: false,
child: Container(
//margin: EdgeInsets.all(10.0),
child: GestureDetector(
onTap: () => _rightCardTapped(),
//onLongPress: //TODO full screen image,
// onLongPressEnd: ,//TODO exit full screen
//child: Card(
child: Padding(
padding: const EdgeInsets.all(2.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(15.0),
child: Image.file(
favpicz[rcn],
),
),
),
//),
),
),
),
),
],
),
),
SizedBox(height: 5.0),
Flexible(
flex: 1,
child:
GestureDetector(
child: FlatButton(
onPressed: () => undo(),
child: Text('Undo',
style: TextStyle(
color: BGColor
),),
color: undoButtonColor,
),
),
)
],
),
),
);
}
通过在 Visibility 小部件中包装两个 Container 和 FlatButton 并创建函数以在 InteractiveViewer 动画开始时将另一个容器和平面按钮的可见性设置为 false,我能够使它看起来像我想要的那样结束时为真。
使用“可见性”小部件也可以在长按时获得所需的全屏效果。
对于一列包含一行两个容器的屏幕,每个容器显示一个图像,行下方有一个撤消 FlatButton,当我将 InteractiveViewer 用于行中的第二个时,它工作得很好,但对于第一个,当它已展开,图像顶部有撤消按钮。
希望当其中一个容器与交互式查看器一起使用时,它们位于视图的顶部。
还希望 Interactive Viewer 容器在长按时进入全屏并在松开长按时退出全屏。
final TransformationController _transformationController =
TransformationController();
Animation<Matrix4> _animationReset;
AnimationController _controllerReset;
void _onAnimateReset() {
_transformationController.value = _animationReset.value;
if (!_controllerReset.isAnimating) {
_animationReset?.removeListener(_onAnimateReset);
_animationReset = null;
_controllerReset.reset();
}
}
void _animateResetInitialize() {
_controllerReset.reset();
_animationReset = Matrix4Tween(
begin: _transformationController.value,
end: Matrix4.identity(),
).animate(_controllerReset);
_animationReset.addListener(_onAnimateReset);
_controllerReset.forward();
}
void _animateResetStop() {
_controllerReset.stop();
_animationReset?.removeListener(_onAnimateReset);
_animationReset = null;
_controllerReset.reset();
}
void _onInteractionStart(ScaleStartDetails details) {
// If the user tries to cause a transformation while the reset animation is
// running, cancel the reset animation.
if (_controllerReset.status == AnimationStatus.forward) {
_animateResetStop();
}
}
void _onInteractionEnd(ScaleEndDetails details) {
_animateResetInitialize();
}
final TransformationController _transformationController2 =
TransformationController();
Animation<Matrix4> _animationReset2;
AnimationController _controllerReset2;
void _onAnimateReset2() {
_transformationController2.value = _animationReset2.value;
if (!_controllerReset2.isAnimating) {
_animationReset2?.removeListener(_onAnimateReset2);
_animationReset2 = null;
_controllerReset2.reset();
}
}
void _animateResetInitialize2() {
_controllerReset2.reset();
_animationReset2 = Matrix4Tween(
begin: _transformationController2.value,
end: Matrix4.identity(),
).animate(_controllerReset2);
_animationReset2.addListener(_onAnimateReset2);
_controllerReset2.forward();
}
void _animateResetStop2() {
_controllerReset2.stop();
_animationReset2?.removeListener(_onAnimateReset2);
_animationReset2 = null;
_controllerReset2.reset();
}
void _onInteractionStart2(ScaleStartDetails details) {
// If the user tries to cause a transformation while the reset animation is
// running, cancel the reset animation.
if (_controllerReset2.status == AnimationStatus.forward) {
_animateResetStop2();
}
}
void _onInteractionEnd2(ScaleEndDetails details) {
_animateResetInitialize2();
}
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: BGColor,
appBar: AppBar(
backgroundColor: PrimaryColor,
title: Text('App\'name',
style: TextStyle(
color: Colors.white
),
),
leading: GestureDetector(
onTap: () {
Navigator.of(context).pop();},
child: Padding(
padding: EdgeInsets.only(top: 19.0, left: 12.0),
child: Text('Quit',
style: TextStyle(
color: Colors.white54,
fontSize: 18.0,
),
),
),
),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Flexible(
flex: 1,
child: tapInstruct(),
),
SizedBox(height: 5.0),
Flexible(
flex: 9,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 1,
child: InteractiveViewer(
boundaryMargin: EdgeInsets.all(double.infinity),
transformationController: _transformationController,
minScale: 1.0,
maxScale: 5,
onInteractionStart: _onInteractionStart,
onInteractionEnd: _onInteractionEnd,
panEnabled: false,
child: Container(
//margin: EdgeInsets.all(10.0),
child: GestureDetector(
onTap: () => _leftCardTapped(),
child: Padding(
padding: const EdgeInsets.all(2.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(15.0),
child: Image.file(
favpicz[lcn]
// fit: BoxFit.fitHeight,
),
),
),
// ),
),
),
),
),
Divider(
thickness: 2.0,
),
Expanded(
flex: 1,
child: InteractiveViewer(
boundaryMargin: EdgeInsets.all(double.infinity),
transformationController: _transformationController2,
minScale: 1.0,
maxScale: 5,
onInteractionStart: _onInteractionStart2,
onInteractionEnd: _onInteractionEnd2,
panEnabled: false,
child: Container(
//margin: EdgeInsets.all(10.0),
child: GestureDetector(
onTap: () => _rightCardTapped(),
//onLongPress: //TODO full screen image,
// onLongPressEnd: ,//TODO exit full screen
//child: Card(
child: Padding(
padding: const EdgeInsets.all(2.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(15.0),
child: Image.file(
favpicz[rcn],
),
),
),
//),
),
),
),
),
],
),
),
SizedBox(height: 5.0),
Flexible(
flex: 1,
child:
GestureDetector(
child: FlatButton(
onPressed: () => undo(),
child: Text('Undo',
style: TextStyle(
color: BGColor
),),
color: undoButtonColor,
),
),
)
],
),
),
);
}
通过在 Visibility 小部件中包装两个 Container 和 FlatButton 并创建函数以在 InteractiveViewer 动画开始时将另一个容器和平面按钮的可见性设置为 false,我能够使它看起来像我想要的那样结束时为真。
使用“可见性”小部件也可以在长按时获得所需的全屏效果。