gpt4 book ai didi

popup - 如何在flutter中动态创建和显示弹出菜单?

转载 作者:行者123 更新时间:2023-12-03 15:26:50 35 4
gpt4 key购买 nike

是否可以通过按下操作按钮来动态创建弹出菜单(PopupMenuButton)并在屏幕中间显示此菜单?比如如何修改标准的flutter应用来实现这个场景:

  void _showPopupMenu()
{
// Create and show popup menu
...
}

我设法在解决问题方面取得了一些进展,但仍然存在问题。这是 main.dart 的文本。通过单击 Canvas ,从 _handleTapDown (...) 调用 _showPopupMenu3(上下文)函数。菜单确实出现了,我可以捕捉选项,但是选择菜单后没有关闭。要关闭菜单需要按 BACK 按钮或单击 Canvas 。这可能对应于 CANCEL 情况。所以问题是:
1)选择项目后如何关闭菜单(可能只是菜单属性的一些参数)?
2)应该传递给位置参数的坐标的目的和意义不是很清楚。如何提高点击坐标旁边的菜单?

资料来源:
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or press Run > Flutter Hot Reload in IntelliJ). Notice that the
// counter didn't reset back to zero; the application is not restarted.
primarySwatch: Colors.blue,
),
home: new TouchTestPage(title: 'Flutter Demo Home Page'),
);
}
}

class TouchTestPage extends StatefulWidget {
TouchTestPage({Key key, this.title}) : super(key: key);

// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.

// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".

final String title;

@override
_TouchTestPageState createState() => new _TouchTestPageState();
}

class _TouchTestPageState extends State<TouchTestPage> {

@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return new Scaffold(
appBar: new AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: new Text(widget.title),
),
body: new Container(
decoration: new BoxDecoration(
color: Colors.white70,
gradient: new LinearGradient(
colors: <Color>[Colors.lightBlue, Colors.white30]),
border: new Border.all(
color: Colors.blueGrey,
width: 1.0,
),
),
child: new Center(child: new TouchControl()),
),
);
}
}

class TouchControl extends StatefulWidget {
final double xPos;
final double yPos;
final ValueChanged<Offset> onChanged;

const TouchControl({
Key key,
this.onChanged,
this.xPos: 0.0,
this.yPos: 0.0,
})
: super(key: key);

@override
TouchControlState createState() => new TouchControlState();
}

class TouchControlState extends State<TouchControl> {
double xPos = 0.0;
double yPos = 0.0;

double xStart = 0.0;
double yStart = 0.0;

double _scale = 1.0;
double _prevScale = null;

void reset()
{
xPos = 0.0;
yPos = 0.0;
}

final List<String> popupRoutes = <String>[
"Properties", "Delete", "Leave"
];
String selectedPopupRoute = "Properties";

void _showPopupMenu3(BuildContext context)
{
showMenu<String>(
context: context,
initialValue: selectedPopupRoute,
position: new RelativeRect.fromLTRB(40.0, 60.0, 100.0, 100.0),
items: popupRoutes.map((String popupRoute) {
return new PopupMenuItem<String>(
child: new
ListTile(
leading: const Icon(Icons.visibility),
title: new Text(popupRoute),
onTap: ()
{
setState(()
{
print("onTap [${popupRoute}] ");
selectedPopupRoute = popupRoute;
});
}
),
value: popupRoute,
);
}).toList(),
);
}

void onChanged(Offset offset)
{
final RenderBox referenceBox = context.findRenderObject();
Offset position = referenceBox.globalToLocal(offset);
if (widget.onChanged != null)
{
// print('---- onChanged.CHANGE ----');
widget.onChanged(position);
}
else
{
// print('---- onChanged.NO CHANGE ----');
}

xPos = position.dx;
yPos = position.dy;

}

@override
bool hitTestSelf(Offset position) => true;

void _handlePanStart(DragStartDetails details) {
print('start');
// _scene.clear();


final RenderBox referenceBox = context.findRenderObject();
Offset position = referenceBox.globalToLocal(details.globalPosition);

onChanged(details.globalPosition);
xStart = xPos;
yStart = yPos;
}

void _handlePanEnd(DragEndDetails details) {

print("_handlePanEnd");
print('end');

}

void _handleTapDown(TapDownDetails details) {

print('--- _handleTapDown ---');
final RenderBox referenceBox = context.findRenderObject();
Offset position = referenceBox.globalToLocal(details.globalPosition);
onChanged(new Offset(0.0, 0.0));

_showPopupMenu3(context); //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

print('+++ _handleTapDown [${position.dx},${position.dy}] +++');
}

void _handleTapUp(TapUpDetails details) {
// _scene.clear();

print('--- _handleTapUp ---');
final RenderBox referenceBox = context.findRenderObject();
Offset position = referenceBox.globalToLocal(details.globalPosition);
onChanged(new Offset(0.0, 0.0));

//_showPopupMenu(context);
print('+++ _handleTapUp [${position.dx},${position.dy}] +++');
}

void _handleDoubleTap() {
print('_handleDoubleTap');
}

void _handleLongPress() {
print('_handleLongPress');
}

void _handlePanUpdate(DragUpdateDetails details) {

// logger.clear("_handlePanUpdate");
final RenderBox referenceBox = context.findRenderObject();
Offset position = referenceBox.globalToLocal(details.globalPosition);
onChanged(details.globalPosition);
}

@override
Widget build(BuildContext context) {
return new ConstrainedBox(
constraints: new BoxConstraints.expand(),
child: new GestureDetector(
behavior: HitTestBehavior.opaque,
onPanStart: _handlePanStart,
onPanEnd: _handlePanEnd,
onPanUpdate: _handlePanUpdate,
onTapDown: _handleTapDown,
onTapUp: _handleTapUp,
onDoubleTap: _handleDoubleTap,
onLongPress: _handleLongPress,
// onScaleStart: _handleScaleStart,
// onScaleUpdate: _handleScaleUpdate,
// onScaleEnd: _handleScaleEnd,
// child: new CustomPaint(
// size: new Size(xPos, yPos),
// painter: new ScenePainter(editor.getScene()),
// foregroundPainter: new TouchControlPainter(/*_scene*//*editor.getScene(),*/ xPos, yPos),
// ),
),
);
}
}

最佳答案

对的,这是可能的

    void _showPopupMenu() async {
await showMenu(
context: context,
position: RelativeRect.fromLTRB(100, 100, 100, 100),
items: [
PopupMenuItem(
value: 1
child: Text("View"),
),
PopupMenuItem(
value: 2
child: Text("Edit"),
),
PopupMenuItem(
value: 3
child: Text("Delete"),
),
],
elevation: 8.0,
).then((value){

// NOTE: even you didnt select item this method will be called with null of value so you should call your call back with checking if value is not null


if(value!=null)
print(value);

});
}

有时您会想要显示 _showPopupMenu 您按下按钮的位置
为此使用 GestureDetector
GestureDetector(
onTapDown: (TapDownDetails details) {
_showPopupMenu(details.globalPosition);
},
child: Container(child: Text("Press Me")),
);
然后 _showPopupMenu 会像
_showPopupMenu(Offset offset) async {
double left = offset.dx;
double top = offset.dy;
await showMenu(
context: context,
position: RelativeRect.fromLTRB(left, top, 0, 0),
items: [
...,
elevation: 8.0,
);
}

关于popup - 如何在flutter中动态创建和显示弹出菜单?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50758121/

35 4 0
文章推荐: sql - CosmosDb 计算不同元素的数量
文章推荐: vuejs2 - Vue.js : what's the difference between and
?
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com