滑动列表项以获取更多选项(颤动) [英] Swipe List Item for more options (Flutter)

查看:340
本文介绍了滑动列表项以获取更多选项(颤动)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

前一天我决定从Pinterest为应用程序选择一个Ui来练习使用Flutter构建应用程序但我仍然坚持使用Slider,它在水平拖动时显示更多和删除按钮。

解决方案

已经有了这种姿势的小部件。它叫做可以接受



你可以在这里找到它。

  class Test extends StatefulWidget {
@override
_TestState createState()=> new _TestState();
}

class _TestState extends State< Test> {
双倍评级= 3.5;

@override
Widget build(BuildContext context){
返回新的Scaffold(
body:new ListView(
children:ListTile
。 divideTiles(
context:context,
tiles:new List.generate(42,(index){
return new SlideMenu(
child:new ListTile(
title: new Container(child:new Text(Drag me)),
),
menuItems:< Widget> [
new Container(
child:new IconButton($ b) $ b图标:新图标(Icons.delete),
),
),
新容器(
子:新IconButton(
图标:新图标(图标) .info),
),
),
],
);
}),

.toList(),
),
);
}
}

类SlideMenu扩展了StatefulWidget {
final Widget child;
final List< Widget>的菜单项;

SlideMenu({this.child,this.menuItems});

@override
_SlideMenuState createState()=> new _SlideMenuState();
}

class _SlideMenuState extends State< SlideMenu>使用SingleTickerProviderStateMixin {
AnimationController _controller;

@override
initState(){
super.initState();
_controller = new AnimationController(vsync:this,duration:const Duration(milliseconds:200));
}

@override
dispose(){
_controller.dispose();
super.dispose();
}

@override
Widget构建(BuildContext context){
final animation = new Tween(
begin:const Offset(0.0,0.0),
end:const Offset(-0.2,0.0)
).animate(new CurveTween(curve:Curves.decelerate).animate(_controller));

返回新的GestureDetector(
onHorizo​​ntalDragUpdate :( data){
//我们可以在这里访问context.size
setState((){
_controller。 value - = data.primaryDelta / context.size.width;
});
},
onHorizo​​ntalDragEnd :( data){
if(data.primaryVelocity> 2500)
_controller.animateTo(.0); //关闭菜单快速向右滑动
else if(_controller.value> = .5 || data.primaryVelocity< -2500)//完全打开如果向左拖动或快速向左滑动
_controller.animateTo(1.0);
else //如果上面没有
_controller.animateTo(.0); $ b则关闭$ b},
child:new Stack(
children:< Widget> [
new SlideTransition(position:animation,child:widget.child),
new Positioned.fill (
child:new LayoutBuilder(
builder :( con文本,约束){
返回新的AnimatedBuilder(
animation:_controller,
builder :( context,child){
返回新的堆栈(
children:< Widget> ; [
new Positioned(
right:.0,
top:.0,
bottom:.0,
width:constraint.maxWidth * animation.value。 dx * -1,
child:new Container(
color:Colors.black26,
child:new Row(
children:widget.menuItems.map((child){
返回新的Expanded(
child:child,
);
})。toList(),
),
),
),
],
);
},
);
},
),

],
),
);
}
}

编辑



Flutter不再允许类型动画< FractionalOffset> in SlideTransition 动画属性。根据这篇文章 https://groups.google.com/forum /#!topic / flutter-dev / fmr-C9xK5t4 应该用 AlignmentTween 替换它,但这也不起作用。相反,根据这个问题: https://github.com/flutter/flutter/issues/13812 用原始 Tween 替换它,并直接创建 Offset 对象。不幸的是,代码不太清楚。


Somedays ago I decided to choose an Ui for an app from Pinterest to practice building apps with Flutter but I'm stuck with the Slider which shows an "more" and "delete" button on horizontal drag. Picture on the right.

I don't have enough knowledge to use Gestures combined with Animations to create something like this in flutter. Thats why I hope that someone of you can make an example for everyone like me that we can understand how to implement something like this in a ListView.builder.

(Source)

An gif example from the macOS mail App:

解决方案

There's already a widget for this kind of gesture. It's called Dismissible.

You can find it here. https://docs.flutter.io/flutter/widgets/Dismissible-class.html

EDIT

If you need the exact same transtion, you'd probably have to implement if yourself. I made a basic example. You'd probably want to tweak the animation a bit, but it's working at least.

class Test extends StatefulWidget {
  @override
  _TestState createState() => new _TestState();
}

class _TestState extends State<Test> {
  double rating = 3.5;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: new ListView(
        children: ListTile
            .divideTiles(
              context: context,
              tiles: new List.generate(42, (index) {
                return new SlideMenu(
                  child: new ListTile(
                    title: new Container(child: new Text("Drag me")),
                  ),
                  menuItems: <Widget>[
                    new Container(
                      child: new IconButton(
                        icon: new Icon(Icons.delete),
                      ),
                    ),
                    new Container(
                      child: new IconButton(
                        icon: new Icon(Icons.info),
                      ),
                    ),
                  ],
                );
              }),
            )
            .toList(),
      ),
    );
  }
}

class SlideMenu extends StatefulWidget {
  final Widget child;
  final List<Widget> menuItems;

  SlideMenu({this.child, this.menuItems});

  @override
  _SlideMenuState createState() => new _SlideMenuState();
}

class _SlideMenuState extends State<SlideMenu> with SingleTickerProviderStateMixin {
  AnimationController _controller;

  @override
  initState() {
    super.initState();
    _controller = new AnimationController(vsync: this, duration: const Duration(milliseconds: 200));
  }

  @override
  dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final animation = new Tween(
      begin: const Offset(0.0, 0.0),
      end: const Offset(-0.2, 0.0)
    ).animate(new CurveTween(curve: Curves.decelerate).animate(_controller));

    return new GestureDetector(
      onHorizontalDragUpdate: (data) {
        // we can access context.size here
        setState(() {
          _controller.value -= data.primaryDelta / context.size.width;
        });
      },
      onHorizontalDragEnd: (data) {
        if (data.primaryVelocity > 2500)
          _controller.animateTo(.0); //close menu on fast swipe in the right direction
        else if (_controller.value >= .5 || data.primaryVelocity < -2500) // fully open if dragged a lot to left or on fast swipe to left
          _controller.animateTo(1.0);
        else // close if none of above
          _controller.animateTo(.0);
      },
      child: new Stack(
        children: <Widget>[
          new SlideTransition(position: animation, child: widget.child),
          new Positioned.fill(
            child: new LayoutBuilder(
              builder: (context, constraint) {
                return new AnimatedBuilder(
                  animation: _controller,
                  builder: (context, child) {
                    return new Stack(
                      children: <Widget>[
                        new Positioned(
                          right: .0,
                          top: .0,
                          bottom: .0,
                          width: constraint.maxWidth * animation.value.dx * -1,
                          child: new Container(
                            color: Colors.black26,
                            child: new Row(
                              children: widget.menuItems.map((child) {
                                return new Expanded(
                                  child: child,
                                );
                              }).toList(),
                            ),
                          ),
                        ),
                      ],
                    );
                  },
                );
              },
            ),
          )
        ],
      ),
    );
  }
}

EDIT

Flutter no longer allows type Animation<FractionalOffset> in SlideTransition animation property. According to this post https://groups.google.com/forum/#!topic/flutter-dev/fmr-C9xK5t4 it should be replaced with AlignmentTween but this also doesn't work. Instead, according to this issue: https://github.com/flutter/flutter/issues/13812 replacing it instead with a raw Tween and directly creating Offset object works instead. Unfortunately, the code is much less clear.

这篇关于滑动列表项以获取更多选项(颤动)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆