这将是太长了,但我不知道问题出在哪里/该怎么做。
更新:如果我改用 StateLessWidget,值会正确跟踪;所以...
目的
在它的核心,我设想我的 TouchPoint 是一个按钮,如果点击并拖动它会将拖动传递到可滚动容器。如果 LongPressed,它将进入编辑模式并处理几种不同类型的数据;如果在对话框上按下 OK,它将调用 parent() OnPressed 函数将新值传回。如果按下取消,则不应调用 onpressed 或更新标签。
问题
当对话框打开时,你不能真正与之交互(我在控件上有打印消息,我看到它被点击了,但是对话框中的 UI 控件没有反映“新”状态)。
您无法点击并拖动按钮
代码
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'statusword_t.dart';
enum InputType { boolean, text, numeric, outconfig, sword }
class TouchPoint extends StatelessWidget {
TouchPoint({
Key? key,
required this.title,
required this.icon,
required this.value,
required this.enabled,
required this.type,
this.onlyButtons = false,
this.warning,
this.setter,
}) : super(key: key);
final String title;
final String value;
final Icon icon;
final bool enabled;
final InputType type;
final bool onlyButtons;
final Function(String)? setter;
final String? warning;
/*@override
_TouchPointState createState() => _TouchPointState();
*/
@override
Widget build(BuildContext context) {
return ElevatedButton(
//This is the screen buton
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(
enabled ? Colors.blue : Colors.grey),
foregroundColor: MaterialStateProperty.all(Colors.white)),
child: Row(
mainAxisAlignment: MainAxisAlignment.start, //ToDo: center?
crossAxisAlignment: CrossAxisAlignment.center,
children: [
icon,
Column(
//ToDo: Alignment here doesn't seem to do anything...
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
title,
textAlign:
TextAlign.center, //ToDo: TextAlign doesn't work either...
),
_uiControl(inEdit: false, type: type, value: value),
])
],
),
onPressed: null, //ToDo: Pass click-drag to parent...
onLongPress: !enabled
? null
: () {
//ToDo: Flyout setter widget here.
print(
"Pressed: " + title + " [" + type.toString() + ": $value ]");
_inputDialog(context: context, touchPoint: this).then((retval) {
if (retval != null) {
//OK was pressed
print("Setter:" + retval);
if (setter != null) setter!(retval);
}
});
},
);
}
}
TextEditingController _textFieldController = TextEditingController();
Widget _uiControl(
{required bool inEdit,
required InputType type,
required String value,
Function(String)? onPressed,
bool? printme}) {
if (printme != null)
print("IE $inEdit, val: $value, " +
((onPressed == null) ? "nocall" : "wcall"));
switch (type) {
case InputType.numeric:
case InputType.text:
if (!inEdit)
return Text(value);
else {
Widget textf = TextField(
autofocus: true,
keyboardType: //ToDo: Flutter Bug https://github.com/flutter/flutter/issues/58510
(type == InputType.numeric)
? TextInputType.number
: TextInputType.text,
//ToDo: maxLength: maxlen,
//ToDo: Min/Max value?
controller: _textFieldController,
decoration: InputDecoration(hintText: "zzBogusHint"),
);
//Set Initial Values (since it has to be done via the Controller)
switch (type) {
case InputType.numeric:
case InputType.text:
_textFieldController.text = value;
_textFieldController.selection = TextSelection.fromPosition(
TextPosition(offset: _textFieldController.text.length));
break;
default: //These aren't keyboards
break;
}
return textf;
}
case InputType.boolean:
return SizedBox(
height: 16,
width: 16,
child: Checkbox(
value: value == "1",
onChanged: onPressed == null
? null
: (val) {
onPressed(value);
},
));
case InputType.outconfig:
return !inEdit
? ToggleButtons(
//We're gonna look like toggle buttons, but it's just a statement of what we are.
disabledColor: Colors.white,
color: Colors.white,
disabledBorderColor: Colors.white,
children: [
int.parse(value) % 2 == 0 ? Text("NO") : Text("NC"),
],
constraints: BoxConstraints(minHeight: 16, minWidth: 32),
borderRadius: BorderRadius.circular(8.0),
borderWidth: 1,
isSelected: [true])
: Row(
children: [
ToggleButtons(
children: [Text("NO"), Text("NC")],
constraints: BoxConstraints(minHeight: 16, minWidth: 32),
borderRadius: BorderRadius.circular(8.0),
borderWidth: 1,
isSelected: [
int.parse(value) % 2 == 0,
int.parse(value) % 2 == 1
],
onPressed: onPressed == null
? null
: (index) => onPressed(index.toString())),
],
);
case InputType.sword:
return StatusWordWidget(int.parse(value),
short: !inEdit, direction: !inEdit ? Axis.horizontal : Axis.vertical);
}
}
//A flyout dialog for changing values
Future<String?> _inputDialog(
{required BuildContext context, required TouchPoint touchPoint}) async {
String myval = touchPoint.value;
final dlg = showDialog<String>(
context: context,
builder: (context) {
return AlertDialog(
title: Text(touchPoint.title),
content: Column(mainAxisSize: MainAxisSize.min, //Keep it small
children: [
if (touchPoint.warning != null) Text(touchPoint.warning!),
if (!touchPoint.onlyButtons)
_uiControl(
printme: true,
inEdit: true,
type: touchPoint.type,
value: myval,
onPressed: (str) {
switch (touchPoint.type) {
case InputType.boolean:
myval = myval == "0" ? "1" : "0";
print("BoolUpdate: $myval");
break;
case InputType.outconfig:
int ival = int.parse(myval);
print("NoncB4: $str - $ival");
ival =
((ival & 0xFF00) + ((ival & 0xFF) == 0 ? 1 : 0));
myval = ival.toString();
print("NoncAfter: $ival");
break;
default:
}
},
)
]),
actions: <Widget>[
FlatButton(
color: Colors.red,
textColor: Colors.white,
child: Text('CANCEL'),
onPressed: () {
Navigator.pop(context);
},
),
FlatButton(
color: Colors.green,
textColor: Colors.white,
child: Text('OK'),
onPressed: () {
//You have to get the value of the TextField from the Controller
String retval;
switch (touchPoint.type) {
case InputType.numeric:
case InputType.text:
retval = _textFieldController.text;
break;
default:
retval = myval;
}
Navigator.pop(context, retval);
},
),
],
);
});
return dlg;
}