Flutter web - ReordorableListView,在字段之间悬停时带有 + 按钮
Flutter web - ReordorableListView with + button on hover between fields
我正在做一个 Flutter Web 项目,我们想要一个 ReordorableListView
设计。当用户悬停在两个元素之间时(然后在所选位置添加一个元素),我们还希望在列表的卡片之间有一个 "+"+" 按钮。
我试图通过在列表中包含一个小部件(它是透明的,悬停时变成 "+")来实现的。但是通过这样做,这个小部件也可以被我不想要的用户拖动。
这是一个简单的例子:
class Screen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ReorderableListView(
onReorder: (int oldIndex, int newIndex) {},
children: [
const Card(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text('Value 0'),
),
key: Key('key0'),
),
PlusButton(
key: Key('plusButton'),
),
const Card(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text('Value 1'),
),
key: Key('key1'),
),
const Card(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text('Value 2'),
),
key: Key('key2'),
),
],
);
}
}
class PlusButton extends StatefulWidget {
PlusButton({Key key}) : super(key: key);
@override
_PlusButtonState createState() => _PlusButtonState();
}
class _PlusButtonState extends State<PlusButton> {
bool isHovered = false;
@override
Widget build(BuildContext context) {
return MouseRegion(
onEnter: (_) {
print('enter');
setState(() {
isHovered = true;
});
},
onExit: (_) {
print('exit');
setState(() {
isHovered = false;
});
},
child: Container(
height: 20,
width: 50,
color: Colors.red, // Should be transparent, red to see it in the example
child: isHovered
? IconButton(
iconSize: 10,
icon: const Icon(Icons.add),
onPressed: () {},
)
: null,
),
);
}
}
名单:
当按钮悬停时:
如您所见,按钮也是可拖动的:
当用户将鼠标悬停在两个元素之间时,如何显示 "+"+" 按钮?
我没有找到任何合适的方法来做我想做的事。我发现的一个解决方法是在按钮的 Container
上放置一个 GestureDetector
和一个非空(但为空)onLongPress
以阻止小部件的拖动。
这是更新后的代码:
class Screen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ReorderableListView(
onReorder: (int oldIndex, int newIndex) {},
children: [
const Card(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text('Value 0'),
),
key: Key('key0'),
),
PlusButton(
key: Key('plusButton'),
),
const Card(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text('Value 1'),
),
key: Key('key1'),
),
const Card(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text('Value 2'),
),
key: Key('key2'),
),
],
);
}
}
class PlusButton extends StatefulWidget {
PlusButton({Key key}) : super(key: key);
@override
_PlusButtonState createState() => _PlusButtonState();
}
class _PlusButtonState extends State<PlusButton> {
bool isHovered = false;
@override
Widget build(BuildContext context) {
return GestureDetector(
onLongPress: () {}, // To prevent the drag
child: MouseRegion(
onEnter: (_) {
print('enter');
setState(() {
isHovered = true;
});
},
onExit: (_) {
print('exit');
setState(() {
isHovered = false;
});
},
child: Container(
height: 20,
width: 50,
color: Colors.red, // Should be transparent, red to see it in the example
child: isHovered
? IconButton(
iconSize: 10,
icon: const Icon(Icons.add),
onPressed: () {},
)
: null,
),
),
);
}
}
也许你可以看看 ReorderableListView
,里面有一个 buildDefaultDragHandle
参数。通过将其设置为 false,该小部件将不再自动使项目可拖动,但它允许您使用 ReorderableDragStartListener
或 ReorderableDelayedDragStartListener
(需要长按触发拖动)包裹您的项目。
Off-topic:我也有一个类似的feature-request,但它是为了让“加号按钮”悬停在ListView的顶部,而不是在项目之间。
Flutter 不擅长通过其原始能力创建非常规布局,尝试将 SizedBox.shrink 与 OverflowBox 结合使用,它在图形上有效但 HitTest 不起作用,因为溢出部分不计算在内。
我正在做一个 Flutter Web 项目,我们想要一个 ReordorableListView
设计。当用户悬停在两个元素之间时(然后在所选位置添加一个元素),我们还希望在列表的卡片之间有一个 "+"+" 按钮。
我试图通过在列表中包含一个小部件(它是透明的,悬停时变成 "+")来实现的。但是通过这样做,这个小部件也可以被我不想要的用户拖动。
这是一个简单的例子:
class Screen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ReorderableListView(
onReorder: (int oldIndex, int newIndex) {},
children: [
const Card(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text('Value 0'),
),
key: Key('key0'),
),
PlusButton(
key: Key('plusButton'),
),
const Card(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text('Value 1'),
),
key: Key('key1'),
),
const Card(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text('Value 2'),
),
key: Key('key2'),
),
],
);
}
}
class PlusButton extends StatefulWidget {
PlusButton({Key key}) : super(key: key);
@override
_PlusButtonState createState() => _PlusButtonState();
}
class _PlusButtonState extends State<PlusButton> {
bool isHovered = false;
@override
Widget build(BuildContext context) {
return MouseRegion(
onEnter: (_) {
print('enter');
setState(() {
isHovered = true;
});
},
onExit: (_) {
print('exit');
setState(() {
isHovered = false;
});
},
child: Container(
height: 20,
width: 50,
color: Colors.red, // Should be transparent, red to see it in the example
child: isHovered
? IconButton(
iconSize: 10,
icon: const Icon(Icons.add),
onPressed: () {},
)
: null,
),
);
}
}
名单:
当按钮悬停时:
如您所见,按钮也是可拖动的:
当用户将鼠标悬停在两个元素之间时,如何显示 "+"+" 按钮?
我没有找到任何合适的方法来做我想做的事。我发现的一个解决方法是在按钮的 Container
上放置一个 GestureDetector
和一个非空(但为空)onLongPress
以阻止小部件的拖动。
这是更新后的代码:
class Screen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ReorderableListView(
onReorder: (int oldIndex, int newIndex) {},
children: [
const Card(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text('Value 0'),
),
key: Key('key0'),
),
PlusButton(
key: Key('plusButton'),
),
const Card(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text('Value 1'),
),
key: Key('key1'),
),
const Card(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text('Value 2'),
),
key: Key('key2'),
),
],
);
}
}
class PlusButton extends StatefulWidget {
PlusButton({Key key}) : super(key: key);
@override
_PlusButtonState createState() => _PlusButtonState();
}
class _PlusButtonState extends State<PlusButton> {
bool isHovered = false;
@override
Widget build(BuildContext context) {
return GestureDetector(
onLongPress: () {}, // To prevent the drag
child: MouseRegion(
onEnter: (_) {
print('enter');
setState(() {
isHovered = true;
});
},
onExit: (_) {
print('exit');
setState(() {
isHovered = false;
});
},
child: Container(
height: 20,
width: 50,
color: Colors.red, // Should be transparent, red to see it in the example
child: isHovered
? IconButton(
iconSize: 10,
icon: const Icon(Icons.add),
onPressed: () {},
)
: null,
),
),
);
}
}
也许你可以看看 ReorderableListView
,里面有一个 buildDefaultDragHandle
参数。通过将其设置为 false,该小部件将不再自动使项目可拖动,但它允许您使用 ReorderableDragStartListener
或 ReorderableDelayedDragStartListener
(需要长按触发拖动)包裹您的项目。
Off-topic:我也有一个类似的feature-request,但它是为了让“加号按钮”悬停在ListView的顶部,而不是在项目之间。
Flutter 不擅长通过其原始能力创建非常规布局,尝试将 SizedBox.shrink 与 OverflowBox 结合使用,它在图形上有效但 HitTest 不起作用,因为溢出部分不计算在内。