首页 > 解决方案 > 与孩子大小相同的可拖动反馈

问题描述

我正在尝试使用Draggable小部件实现可刷卡(类似于 Tinder 应用程序)。滑动工作正常,除了我正在努力弄清楚如何将Draggable'sfeedback的大小设置为与child. 问题是Stack保存Draggable项目的小部件具有取决于屏幕大小的动态大小,因此将大小设置为固定值不是一种选择。

我试图使用 LayoutBuilder 并希望能够使用RenderBox box = context.findRenderObject() as RenderBox;以下异常来获得大小RenderBox was not laid out。阅读文档后,发现无法在build函数中调用获取 RenderBox。

另一种选择是使用MediaQuery.of(context).size,但这并不方便,因为它只返回应用程序呈现的窗口大小(全屏)。

如果有人能告诉我如何做到这一点,我将不胜感激。

代码

class CardStack extends StatefulWidget {
  @override
  _CardStackState createState() => new _CardStackState();
}

class _CardStackState extends State<StatefulWidget> {
  @override
  Widget build(BuildContext context) {
    return new Container(
      padding: EdgeInsets.all(32),
      child: SizedBox.expand(
        child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
          RenderBox box = context.findRenderObject() as RenderBox;
          return new Stack(
            children: <Widget>[
              new Draggable(
                key: ObjectKey('card1'),
                child: new Card(
                  color: Colors.red,
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(10)),
                  child: Container(
                  ),
                ),
                feedback: new Card(
                  color: Colors.red,
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(10)),
                  child: Container(
                    width: box.size.width, // TODO: how to get same size as child??
                    height: box.size.height, // TODO: how to get same size as child??
                  ),
                ),
                childWhenDragging: Container(),
              ),
              new Draggable(
                key: ObjectKey('card2'),
                child: new Card(
                  color: Colors.green,
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(10)),
                  child: Container(
                  ),
                ),
                feedback: new Card(
                  color: Colors.green,
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(10)),
                  child: Container(
                    width: box.size.width,
                    height: box.size.height,
                  ),
                ),
                childWhenDragging: Container(),
              ),
              new Listener(
                onPointerDown: (PointerDownEvent event) {
                  print(event.position);
                },
                child: new Draggable(
                  key: ObjectKey('card3'),
                  child: new Card(
                    color: Colors.blue,
                    shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(10)),
                    child: Container(
                    ),
                  ),
                  feedback: new Card(
                    color: Colors.blue,
                    shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(10)),
                    child: Container(
                      width: box.size.width,
                      height: box.size.height,
                    ),
                  ),
                  childWhenDragging: Container(),
                ),
              ),
            ],
          );
        }),
      ),
    );
  }
}

标签: flutter

解决方案


更新

请使用LayoutBuilder来构建Draggable. 它的 builder 函数接收一个约束参数,您可以使用它来调整反馈的大小。这要好得多,因为GlobalKey如果你有一个包含动态数据的列表,你就不能总是拥有一个。

例子:

LayoutBuilder(
  builder: (context, constraints) => Draggable(
    child: Container(...),
    feedback: Container (
      width: constraints.maxWidth,
    )
  ),
);

初始职位

您可以通过使用其 GlobalKey 来确定 Widget 的大小。我在GitHub 上针对 ListView发布了此评论,但我认为您可以将相同的示例用于 Stack。

ListView.builder(
  itemCount: 25,
  itemBuilder: (BuildContext context, int index) {
    GlobalKey myKey = GlobalKey();
    return Draggable(
      child: ListTile(
        key: myKey,
          title: Text("Tile #$index"),
        ),
        childWhenDragging: Opacity(
          opacity: 0.2,
          child: ListTile(
            title: Text("Tile #$index"),
          ),
        ),
        feedback: FeedbackWidget(
          dragChildKey: myKey,
          child: ListTile(
            title: Text("Tile #$index"),
          ),
       ),
     );
  }
)


class FeedbackWidget extends StatelessWidget{
  final GlobalKey dragChildKey;
  final Widget child;
  const FeedbackWidget({Key key, this.dragChildKey, this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    //Determine the size of the original widget
    final RenderBox renderBoxRed = dragChildKey.currentContext.findRenderObject();
    final size = renderBoxRed.size;
    return Container(
      width: size.width,
      height: size.height,
      child: Material(
        child: child,
      ),
    );
  }
}

你也可以看看这篇 Medium 文章


推荐阅读