使用堆栈中拖动的小部件更新所有附加的小部件

亚历克斯·罗伊

如图所示,考虑一堆小部件。我们可以看到索引0小部件附加了索引1、2、3、4小部件;...; 索引3小部件附有索引4小部件,而索引4小部件未附有任何人。

堆栈的小部件
现在,当我拖动一个窗口小部件时,所有附加的窗口小部件也应随其一起拖动,
即,如果我尝试拖动索引2窗口小部件,则所拖动的窗口小部件应为索引2、3、4窗口小部件的堆栈。
如果我尝试拖动索引4小部件,则被拖动的部件应仅为索引4小部件。

现在,我知道可以使用Draggable类的feedbackchildWhenDragging参数来处理拖动的小部件的更新,但是我不知道如何使用它来更新所有其他附加的小部件。

这是我的代码:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}


class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<BlockWidget> blockWidgets;
  final List<Color> widgetColors = [Colors.red, Colors.brown, Colors.black, Colors.pink, Colors.grey];

  @override
  void initState() {
    super.initState();

    blockWidgets = new List();
    for(int i=0; i < widgetColors.length; i++) {
      blockWidgets.add(BlockWidget(widgetId: i, widgetColor: widgetColors.elementAt(i)));
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        title: Text('AppBar'),
      ),
      body: WidgetStacks(
        blocks: blockWidgets,
      ),
    );
  }
}


const blockHeight = 100.0;
const blockWidth = 100.0;

class BlockWidget {
  int widgetId;
  Color widgetColor;

  BlockWidget({
    @required this.widgetId,
    @required this.widgetColor,
  });
}


class TransformedWidget extends StatefulWidget {
  final BlockWidget block;
  final int stackIndex;
  final List<BlockWidget> attachedBlocks;

  TransformedWidget(
      {@required this.block,
        @required this.stackIndex,
        @ required this.attachedBlocks,
      });

  @override
  _TransformedWidgetState createState() => _TransformedWidgetState();
}

class _TransformedWidgetState extends State<TransformedWidget> {
  @override
  Widget build(BuildContext context) {
    return Transform(
      transform: Matrix4.identity()
        ..translate(
          widget.stackIndex * (blockHeight / 2),
          widget.stackIndex * (blockWidth / 2),
          0.0,
        ),
      child: Draggable<Map>(
        child: _buildBlock(),
        feedback: WidgetStacks(
          blocks: widget.attachedBlocks,
        ),
        childWhenDragging: Container(),
      ),
    );
  }

  Widget _buildBlock() {
    return Container(
      height: blockHeight,
      width: blockWidth,
      color: widget.block.widgetColor,
      alignment: Alignment.centerLeft,
      child: Text(
        widget.block.widgetId.toString(),
        style: TextStyle(
          fontSize: 30.0,
          color: Colors.white,
        ),
      ),
    );
  }
}


class WidgetStacks extends StatefulWidget {
  final List<BlockWidget> blocks;

  WidgetStacks({@required this.blocks});

  @override
  _WidgetStacksState createState() => _WidgetStacksState();
}

class _WidgetStacksState extends State<WidgetStacks> {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 5 * blockHeight,
      width: 5 * blockWidth,
      margin: EdgeInsets.all(2.0),
      child: Stack(
        children: widget.blocks.map((block) {
          int index = widget.blocks.indexOf(block);
          return TransformedWidget(
            block: block,
            stackIndex: index,
            attachedBlocks: widget.blocks.sublist(index),
          );
        }).toList(),
      ),
    );
  }
}
卡佩什·昆达纳尼
  1. 您应该将回调(onDragStart,onDragEnd)传递给TransformedWidget以获得有关拖动事件的通知。
  2. 基于回调,您应该重建您的父窗口小部件(在您的情况下为WidgetStacks)。

以下是工作代码供您参考:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<BlockWidget> blockWidgets;
  final List<Color> widgetColors = [
    Colors.red,
    Colors.brown,
    Colors.black,
    Colors.pink,
    Colors.grey
  ];

  @override
  void initState() {
    super.initState();

    blockWidgets = new List();
    for (int i = 0; i < widgetColors.length; i++) {
      blockWidgets.add(
          BlockWidget(widgetId: i, widgetColor: widgetColors.elementAt(i)));
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        title: Text('AppBar'),
      ),
      body: WidgetStacks(
        key:ValueKey('WidgetStacks_${blockWidgets.length}'),
        blocks: blockWidgets,
      ),
    );
  }
}

const blockHeight = 100.0;
const blockWidth = 100.0;

class BlockWidget {
  int widgetId;
  Color widgetColor;

  BlockWidget({
    @required this.widgetId,
    @required this.widgetColor,
  });
}

class TransformedWidget extends StatefulWidget {
  final BlockWidget block;
  final int stackIndex;
  final List<BlockWidget> attachedBlocks;
  final Function() onDragCanceled;
  final Function() onDragStart;

  TransformedWidget({
    Key key,
    @required this.block,
    @required this.stackIndex,
    @required this.attachedBlocks, this.onDragCanceled, this.onDragStart,
  }):super(key: key);

  @override
  _TransformedWidgetState createState() => _TransformedWidgetState();
}

class _TransformedWidgetState extends State<TransformedWidget> {
  @override
  Widget build(BuildContext context) {
    return Transform(
      transform: Matrix4.identity()
        ..translate(
          widget.stackIndex * (blockHeight / 2),
          widget.stackIndex * (blockWidth / 2),
          0.0,
        ),
      child: Draggable<Map>(
        key: ValueKey(widget.stackIndex),
        onDragStarted: ()=>widget.onDragStart(),
        onDraggableCanceled: (_,__)=>widget.onDragCanceled(),
        child: _buildBlock(),
        feedback: WidgetStacks(
          key: ValueKey('WidgetStacks_${widget.attachedBlocks.length}'),
          blocks: widget.attachedBlocks,
        ),
        childWhenDragging: Container(),
      ),
    );
  }

  Widget _buildBlock() => Material(
          child: Container(
        height: blockHeight,
        width: blockWidth,
        color: widget.block.widgetColor,
        alignment: Alignment.centerLeft,
        child: Text(
          widget.block.widgetId.toString(),
          style: TextStyle(
            fontSize: 30.0,
            color: Colors.white,
          ),
        ),
      ),
    );
}

class WidgetStacks extends StatefulWidget {
  final List<BlockWidget> blocks;

  WidgetStacks({@required this.blocks, Key key}):super(key:key);

  @override
  _WidgetStacksState createState() => _WidgetStacksState();
}

class _WidgetStacksState extends State<WidgetStacks> {
  ValueNotifier<List<BlockWidget>> blocksToBeShownNotifier;

  @override
  void initState() {
    blocksToBeShownNotifier = ValueNotifier<List<BlockWidget>>(widget.blocks);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 5 * blockHeight,
      width: 5 * blockWidth,
      margin: EdgeInsets.all(2.0),
      child: ValueListenableBuilder<List<BlockWidget>>(
        valueListenable: blocksToBeShownNotifier,
        builder: (BuildContext context,List<BlockWidget> value, Widget child) {
        return Stack(
        children: value.map((block) {
          int index = value.indexOf(block);
          return TransformedWidget(
            key: ValueKey(block.widgetId),
            block: block,
            stackIndex: index,
            onDragStart:(){
              blocksToBeShownNotifier.value = widget.blocks.sublist(0, index);
            },
            onDragCanceled:(){
              blocksToBeShownNotifier.value = widget.blocks;
            },
            attachedBlocks: widget.blocks.sublist(index),
          );
        }).toList(),
      );
      },),
    );
  }
}

希望有帮助,如有疑问,请发表评论。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

无法使用NotificationListenerService取消小部件中的所有通知

来自分类Dev

在堆栈中的两个小部件之间传递所有手势

来自分类Dev

从有状态小部件更新无状态小部件

来自分类Dev

如何在Flutter中的StaggeredGridView中使用堆栈小部件?

来自分类Dev

如何使用堆栈小部件在 CircleAvatar 中居中图标按钮

来自分类Dev

我想删除所有小部件并将新的小部件放在tkinter中

来自分类Dev

在IPython窗口小部件中,如何使用新值更新DropDown窗口小部件?

来自分类Python

清除pyqt中布局中的所有小部件

来自分类Dev

Flutter更新小部件

来自分类Dev

如何更新小部件?

来自分类Dev

Kivy更新小部件

来自分类Java

遍历活动中的所有“小部件” /元素

来自分类Dev

Flutter:滚动堆栈小部件

来自分类Dev

Qt反转所有小部件的位置

来自分类Dev

所有小部件上的Flutter Tooltip

来自分类Dev

强制加载所有窗口小部件

来自分类Dev

django对所有字段应用小部件

来自分类Dev

如何从QStackedWidget删除所有小部件?

来自分类Dev

有状态的小部件子项未更新

来自分类Dev

窗口小部件没有更新

来自分类Dev

使用小部件更新Gmaps + Jupyter中的标记

来自分类Dev

更新渲染中的小部件值?

来自分类Dev

如何立即更新Kivy中的小部件?

来自分类Dev

小部件中的ListView不会更新

来自分类Dev

如何更新列表中的小部件

来自分类Dev

小部件中的UITableView

来自分类Dev

Flutter:使用 notifyListeners() 更新小部件状态

来自分类Dev

使用设置状态功能更新小部件

来自分类Dev

使用微调小部件更新特定的列