Flutter中是否有任何内置方法可以隐藏FloatingActionButton
ListView
向下滚动,然后在向上滚动时显示它?
答案 0 :(得分:16)
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
ScrollController _hideButtonController;
void _incrementCounter() {
setState(() {
_counter++;
});
}
var _isVisible;
@override
initState(){
super.initState();
_isVisible = true;
_hideButtonController = new ScrollController();
_hideButtonController.addListener((){
if(_hideButtonController.position.userScrollDirection == ScrollDirection.reverse){
setState((){
_isVisible = true;
print("**** ${_isVisible} up");
});
}
if(_hideButtonController.position.userScrollDirection == ScrollDirection.forward){
setState((){
_isVisible = false;
print("**** ${_isVisible} down");
});
}
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new CustomScrollView(
controller: _hideButtonController,
shrinkWrap: true,
slivers: <Widget>[
new SliverPadding(
padding: const EdgeInsets.all(20.0),
sliver: new SliverList(
delegate: new SliverChildListDelegate(
<Widget>[
const Text('I\'m dedicating every day to you'),
const Text('Domestic life was never quite my style'),
const Text('When you smile, you knock me out, I fall apart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('I realize I am crazy'),
],
),
),
),
],
)
),
floatingActionButton: new Opacity( //Use visibility widget instead
opacity: _isVisible ? 1.0 : 0.0,
child: new FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: new Icon(Icons.add),
),
),
);
}
}
如果我不使用listview,我很抱歉,因为我不知道如何使用listview滚动。我会回答你问题的其他部分。
首先,您需要创建一个scrollcontroller来监听scrollPostion个事件
如果scrollcontroller设法找到scrolldirection正向或反向。您添加一个将状态设置为可见的状态。
绘制按钮时,将按钮包裹在opacity类中。您将0.0设置为不可见,或将1.0设置为可见。
编辑:我似乎无法添加指向ScrollController,ScrollerPosition,ScrollDirection和Opacity的链接。我猜您可以自己搜索,也可以在链接中编辑其他人
Edit2:使用CopsonRoad或使用可见性小部件,除非您想要布局树中未上漆的小部件
答案 1 :(得分:6)
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main () => runApp(MyApp())
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool show = true;
List<String> _list = [];
ScrollController _controller = ScrollController();
@override
void initState() {
super.initState();
_list = List.generate(50, (i) => "Index = $i");
_controller.addListener(listener);
}
void listener() {
if (_controller.position.userScrollDirection == ScrollDirection.forward)
show = true;
else
show = false;
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Hide FAB"),
),
body: ListView(
controller: _controller,
children: _list.map((String item) {
return ListTile(
title: Text(item),
);
}).toList(),
),
floatingActionButton: show ? FloatingActionButton(onPressed: null) : Container(),
);
}
@override
void dispose() {
_controller.removeListener(listener);
super.dispose();
}
}
答案 2 :(得分:5)
您可以使用以下代码保留默认动画
floatingActionButton: _isVisible
? FloatingActionButton(...)
: null,
答案 3 :(得分:4)
一个很好的方法...
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
ScrollController controller;
bool fabIsVisible = true;
@override
void initState() {
super.initState();
controller = ScrollController();
controller.addListener(() {
setState(() {
fabIsVisible =
controller.position.userScrollDirection == ScrollDirection.forward;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
controller: controller,
children: List.generate(
100,
(index) => ListTile(
title: Text("Text $index"),
)),
),
floatingActionButton: AnimatedOpacity(
child: FloatingActionButton(
child: Icon(Icons.add),
tooltip: "Increment",
onPressed: () {
print("Pressed");
},
),
duration: Duration(milliseconds: 100),
opacity: fabIsVisible ? 1 : 0,
),
);
}
}
答案 4 :(得分:1)
其他非常好的方法是 AnimatedOpacity
AnimatedOpacity(
opacity: isEnabled ? 0.0 : 1.0,
duration: Duration(milliseconds: 1000),
child: FloatingActionButton(
onPressed: your_method,
tooltip: 'Increment',
child: new Icon(Icons.add),
),
)
答案 5 :(得分:1)
这是一个古老的问题,但是随着最新的发展,我认为有一个更好(更短)的解决方案。
其他解决方案也可以使用,但是如果您想要一个漂亮的动画(与Android中的默认动画相比),请执行以下操作:
每当用户滚动(向上/向下)时,NotificationListener都会通知您。使用AnimationController,您可以控制FAB的动画。
这是一个完整的例子:
class WidgetState extends State<Widget> with TicketProviderStateMixin<Widget> {
AnimationContoller _hideFabAnimation;
@override
initState() {
super.initState();
_hideFabAnimation = AnimationController(vsync: this, duration: kThemeAnimationDuration);
}
@override
void dispose() {
_hideFabAnimation.dispose();
super.dispose();
}
bool _handleScrollNotification(ScrollNotification notification) {
if (notification.depth == 0) {
if (notification is UserScrollNotification) {
final UserScrollNotification userScroll = notification;
switch (userScroll.direction) {
case ScrollDirection.forward:
_hideFabAnimation.forward();
break;
case ScrollDirection.reverse:
_hideFabAnimation.reverse();
break;
case ScrollDirection.idle:
break;
}
}
}
return false;
}
@override
Widget build(BuildContext context) {
return NotificationListener<ScrollNotification>(
onNotification: _handleScrollNotification,
child: Scaffold(
appBar: AppBar(
title: Text('Fabulous FAB Animation')
),
body: Container(),
floatingActionButton: ScaleTransition(
scale: _hideFabAnimation,
alignment: Alignment.bottomCenter,
child: FloatingActionButton(
elevation: 8,
onPressed: () {},
child: Icon(Icons.code),
),
),
),
);
}
}