【问题标题】:Constraining Draggable area约束可拖动区域
【发布时间】:2018-07-06 19:42:39
【问题描述】:

我正在尝试创建一个可拖动的类似滑块的小部件(如确认滑块)。我的问题是是否有办法限制可拖动区域?

import 'package:flutter/material.dart';

import 'confirmation_slider.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        body: new ListView(
          children: <Widget>[
            new Container(
              margin: EdgeInsets.only(
                top: 50.0
              ),
            ),

            new Container(
              margin: EdgeInsets.only(
                left: 50.0,
                right: 50.0
              ),
              child: new Draggable(
                axis: Axis.horizontal,
                child: new FlutterLogo(size: 50.0),
                feedback: new FlutterLogo(size: 50.0),
              ),

              height: 50.0,
              color: Colors.green
            ),
          ],
        ),
      ),
    );
  }
}

我以为容器类会限制可拖动区域,但它似乎没有这样做。

【问题讨论】:

    标签: dart flutter


    【解决方案1】:

    没有。这不是Draggable 小部件的目标。相反,使用GestureDetector 来检测阻力。然后将其与 Align 之类的内容结合起来移动您的内容

    这是一个基于您当前代码的完整工作滑块。

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: Center(
              child: Slider(),
            ),
          ),
        );
      }
    }
    
    class Slider extends StatefulWidget {
      final ValueChanged<double> valueChanged;
    
      Slider({this.valueChanged});
    
      @override
      SliderState createState() {
        return new SliderState();
      }
    }
    
    class SliderState extends State<Slider> {
      ValueNotifier<double> valueListener = ValueNotifier(.0);
    
      @override
      void initState() {
        valueListener.addListener(notifyParent);
        super.initState();
      }
    
      void notifyParent() {
        if (widget.valueChanged != null) {
          widget.valueChanged(valueListener.value);
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Container(
          color: Colors.green,
          height: 50.0,
          padding: EdgeInsets.symmetric(horizontal: 40.0),
          child: Builder(
            builder: (context) {
              final handle = GestureDetector(
                onHorizontalDragUpdate: (details) {
                  valueListener.value = (valueListener.value +
                          details.delta.dx / context.size.width)
                      .clamp(.0, 1.0);
                },
                child: FlutterLogo(size: 50.0),
              );
    
              return AnimatedBuilder(
                animation: valueListener,
                builder: (context, child) {
                  return Align(
                    alignment: Alignment(valueListener.value * 2 - 1, .5),
                    child: child,
                  );
                },
                child: handle,
              );
            },
          ),
        );
      }
    }
    

    【讨论】:

    • 这仍然是最好的方法吗?为什么我们需要 ValueChanged 和 notifyParent?
    • 这非常有帮助 - 谢谢@rémi-rousselet!一个小的变化是修改 onHorizo​​ntalDragUpdate() 中的计算...在 Rémi 的解决方案中,它是根据容器的全宽计算...它应该根据子中心的坐标计算,当它是所有的一路向左,当它一直向右时。 IE。去掉两边的边距和孩子宽度的一半。例如。而不是使用 context.size.width,它应该使用:context.size.width - (40+25) - (40+25)。如果我们不这样做,子位置就会滞后于触摸
    • @rémi-rousselet 长按时拖动不起作用。长按可以拖动吗?
    • ``` onLongPressStart: (v) {}, onLongPressEnd: (v) {}, onHorizo​​ntalDragUpdate: (details) { ``
    猜你喜欢
    • 2016-06-13
    • 2011-07-13
    • 1970-01-01
    • 2018-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多