我正在Flutter中编写抽认卡应用程序(对开源AnkiDroid应用程序的扩展)。基本的工作流程是:该应用程序向我显示一个问题,我可以显示答案。我想要显示答案的手势类似于从底部图标行向上滑动以显示应用程序抽屉的Android 8。快速滑动(或用Android术语猛击?)可以显示应用程序列表,但是抽出缓慢的滑动可以控制应用程序抽屉的运动。
我的问题如下:
谢谢您的任何建议。
这是我到目前为止的屏幕:
问题屏幕
答案屏幕(向上滑动后)
这是代码:
import 'package:flutter/material.dart';
import 'dart:math';
// Uncomment lines 7 and 10 to view the visual layout at runtime.
//import 'package:flutter/rendering.dart' show debugPaintSizeEnabled;
void main() {
//debugPaintSizeEnabled = true;
runApp(MyApp());
}
/*
* travel around the world
* 環遊世界
* wàan jàu sâi gâai
*/
class Card extends StatefulWidget {
@override
createState() => CardState();
}
class CardState extends State<Card> with SingleTickerProviderStateMixin {
var _dragStartOffset;
Animation<double> questionAnimation;
Animation<double> answerAnimation;
Animation<double> opacityAnimation;
AnimationController controller;
initState() {
super.initState();
controller = AnimationController(duration: const Duration(milliseconds: 250), vsync: this);
questionAnimation = Tween(begin: 250.0, end: 150.0).animate(controller)
..addListener(() {
setState(() {
// the state that has changed here is the animation object’s value
});
});
answerAnimation = Tween(begin: 200.0, end: 32.0).animate(controller)
..addListener(() {
setState(() {
// the state that has changed here is the animation object’s value
});
});
opacityAnimation = Tween(begin: 0.0, end: 1.0).animate(controller)
..addListener(() {
setState(() {
// the state that has changed here is the animation object’s value
});
});
}
@override
Widget build(BuildContext context) {
Widget question = Container(
padding: EdgeInsets.only(top: questionAnimation.value),
child: Center (
child: Text(
"travel around the world",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 48.0,
),
textAlign: TextAlign.center,
)
),
);
Widget answer = Container(
padding: EdgeInsets.only(top: answerAnimation.value),
child: Opacity(
opacity: opacityAnimation.value,
child: Text(
"wàan jàu sâi gâai 環遊世界",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 48.0,
),
textAlign: TextAlign.center,
)
)
);
var children = [question, answer];
var child = GestureDetector(
onTap: () {
controller.reset();
},
onVerticalDragUpdate: (data) {
// print(data);
var currentOffset = data.globalPosition;
var travel = _dragStartOffset - currentOffset;
// print(travel);
if(travel.dy <0 )
{
return;
}
// cannot be lower than zero
var travelY = max<double>(0.0, travel.dy);
// cannot be higher than 100
travelY = min<double>(200.0, travelY);
var animationPosition = travelY / 200.0;
controller.value = animationPosition;
},
onVerticalDragEnd: (data) {
if(controller.value > 0.50) {
// make the animation continue on its own
controller.forward();
} else {
// go back the other way
controller.reverse();
}
},
onVerticalDragStart: (data) {
//print(data);
_dragStartOffset = data.globalPosition;
},
child: Scaffold(
appBar: AppBar(
title: Text('AnkiReview'),
),
body: Container(
child:Column(
children: children,
)
),
)
);
return child;
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Card(),
);
}
}
答案 0 :(得分:0)
我想出了一个解决方案。它涉及一个列,顶部只是一个带有问题的容器,而底部是一个具有空白首页的 PageView 。用户可以向上滑动以显示答案。
它解决了裁剪问题,也解决了物理问题,因为PageView具有内置的物理和捕捉功能,否则将很难构建(我可能必须使用CustomScrollView)。
代码:
// Copyright 2017 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/material.dart';
import 'dart:math';
// Uncomment lines 7 and 10 to view the visual layout at runtime.
//import 'package:flutter/rendering.dart' show debugPaintSizeEnabled;
void main() {
//debugPaintSizeEnabled = true;
runApp(MyApp());
}
/*
* travel around the world
* 環遊世界
* wàan jàu sâi gâai
*/
class Card extends StatefulWidget {
@override
createState() => CardState();
}
class CardState extends State<Card> with SingleTickerProviderStateMixin {
var _dragStartOffset;
var _fontSize = 48.0;
static const _padding = 28.0;
initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
var questionText = Text(
"travel around the world",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: _fontSize,
),
textAlign: TextAlign.center,
);
var answerText = Text(
"wàan jàu sâi gâai 環遊世界",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: _fontSize,
),
textAlign: TextAlign.center
);
Widget question = Container(
padding: EdgeInsets.only(bottom: _padding),
alignment: Alignment.bottomCenter,
child: questionText
);
Widget answer = Container(
padding: EdgeInsets.only(top: _padding),
alignment: Alignment.topCenter,
child: answerText
);
var card = Column(
children: [
Expanded(
child: question,
),
Expanded(
child: PageView(
scrollDirection: Axis.vertical,
children: [
Container(),
answer
]
)
)
]
);
return card;
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
appBar: AppBar(
title: Text('AnkiReview'),
),
body: Container(
child:Card()
),
),
);
}
}