小部件的状态问题——从父级更新并从内部更新

问题描述

这会太长,但我不知道问题出在哪里/该怎么做。

更新:如果我使用 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")],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,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;
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)