约束可拖动区域

Val*_*mar 5 dart flutter

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

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
            ),
          ],
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

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

Rém*_*let 10

不。这不是Draggable小部件的目标。相反,使用 aGestureDetector来检测拖动。然后将它与诸如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,
          );
        },
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这仍然是最好的方法吗?为什么我们需要 ValueChanged 和 notificationParent? (2认同)
  • 这非常有帮助 - 谢谢@rémi-rousselet!一个小改动是修改了onHorizo​​ntalDragUpdate()中的计算...在Rémi的解决方案中,它是根据容器的全宽来计算...当它是所有子级时,应该根据子级中心的坐标来计算一直向左,以及当它一直向右时。IE。去掉两边的边距和子元素宽度的一半。例如。而不是使用 context.size.width,它应该使用:context.size.width - (40+25) - (40+25)。如果我们不这样做,子位置就会滞后于触摸 (2认同)