单击 DropdownButtonFormField 时抛出错误

Throwing an error while clicking on DropdownButtonFormField

我正在尝试在带有选项卡查看器的选项卡控制器中使用 DropdownButtonFormField 在 flutter web 上。它显示但不显示下拉选项点击它显示错误请在我的代码和错误下方找到。

下面是我的示例代码:

import 'package:flutter/material.dart';

class UserManager extends StatefulWidget {
  const UserManager({Key? key}) : super(key: key);

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

class _UserManagerState extends State<UserManager> {
  final _formkey = GlobalKey<FormState>();
  var addName = "";
  var addEmail = "";
  var addPassword = "";
  var addRole = "";


  final nameController = TextEditingController();
  final emailController = TextEditingController();
  final passwordController = TextEditingController();
  final roleController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 2,
        child: Scaffold(
          appBar: AppBar(
            toolbarHeight: 20,
            bottom: const TabBar(
              tabs: [
                Tab(icon: Icon(Icons.person_add)),
                Tab(icon: Icon(Icons.edit)),
              ],
            ),
          ),
          body: TabBarView(
            children: [
              Center(
                child: Form(
                    key: _formkey,
                    child: SingleChildScrollView(
                      reverse: true,
                      child: Container(
                        width: 420,
                        margin: const EdgeInsets.all(10.0),
                        padding: const EdgeInsets.all(16),
                        decoration: BoxDecoration(
                          border: Border.all(color: Colors.grey),
                          borderRadius: const BorderRadius.all(
                            Radius.circular(10),
                          ),
                        ),
                        child: Column(
                          children: [
                            //const SizedBox(
                            //height: 50,
                            //),
                            const Text(
                              "Add name",
                              style: TextStyle(
                                fontSize: 20,
                                fontWeight: FontWeight.bold,
                                color: Colors.indigo,
                              ),
                            ),
                            const SizedBox(
                              height: 10,
                            ),
                            TextFormField(
                                minLines: 1,
                                autofocus: false,
                                keyboardType: TextInputType.text,
                                textInputAction: TextInputAction.next,
                                decoration: const InputDecoration(
                                  labelText: "Name",
                                  border: OutlineInputBorder(),
                                  errorStyle: TextStyle(
                                      color: Colors.redAccent, fontSize: 15),
                                ),
                                controller: nameController,
                                validator: (value) {
                                  if (value == null || value.isEmpty) {
                                    return 'Please Enter Name';
                                  }
                                  return null;
                                }),
                            const SizedBox(
                              height: 10,
                            ),
                            TextFormField(
                                autofocus: false,
                                minLines: 1,
                                keyboardType: TextInputType.emailAddress,
                                textInputAction: TextInputAction.next,
                                decoration: const InputDecoration(
                                  labelText: "Email Address",
                                  //hintText: "Email",
                                  border: OutlineInputBorder(),
                                  errorStyle: TextStyle(
                                      color: Colors.redAccent, fontSize: 15),
                                ),
                                controller: emailController,
                                validator: (value) {
                                  if (value == null || value.isEmpty) {
                                    return 'Please Enter Email ID';
                                  } else if (!value.contains('@')) {
                                    return 'Please Enter Valid Email ID';
                                  }
                                  return null;
                                }),
                            const SizedBox(
                              height: 10,
                            ),
                            TextFormField(
                                minLines: 1,
                                autofocus: false,
                                obscureText: true,
                                keyboardType: TextInputType.text,
                                textInputAction: TextInputAction.next,
                                decoration: const InputDecoration(
                                  labelText: "Password",
                                  border: OutlineInputBorder(),
                                  errorStyle: TextStyle(
                                      color: Colors.redAccent, fontSize: 15),
                                ),
                                controller: passwordController,
                                validator: (value) {
                                  if (value == null || value.isEmpty) {
                                    return 'Please Enter Password';
                                  }
                                  return null;
                                }),
                            const SizedBox(
                              height: 20,
                            ),
                            //
                            DropdownButtonFormField(
                              decoration: const InputDecoration(
                                labelText: "department",
                                border: OutlineInputBorder(),
                                errorStyle: TextStyle(
                                    color: Colors.redAccent, fontSize: 15),
                              ),
                              hint: const Text("select department"),
                              value: addRole,
                              onChanged: (String? newValue) {
                                setState(() {
                                  addRole = newValue!;
                                });
                              },
                              validator: (value) => value == null ? 'field required' : null,
                              items: <String>[
                                '',
                                'hr',
                                'dtp'
                              ].map<DropdownMenuItem<String>>((String value) {
                                return DropdownMenuItem<String>(
                                  value: value,
                                  child: Text(value),
                                );
                              }).toList(),
                            ),
                            const SizedBox(
                              height: 20,
                            ),
                            //
                            ElevatedButton(
                              style: ElevatedButton.styleFrom(
                                primary: Colors.red, // background
                                onPrimary: Colors.white, // foreground
                              ),
                              onPressed: ()  {}
                              child: const Text('User Add'),
                            ),
                            const SizedBox(
                              height: 20,
                            ),
                          ],
                        ),
                      ),
                    )),
              ),
              Center(
                child: Text("Test"),
              )
            ],
          ),
        ),
      ),
    );
  }
}

错误如下:

Exception has occurred. "Error: Cannot hit test a render box that has never been laid out. The hitTest() method was called on this RenderBox: RenderSemanticsAnnotations#119e3 NEEDS-LAYOUT NEEDS-PAINT: needs compositing creator: Semantics ← _EffectiveTickerMode ← TickerMode ← _OverlayEntryWidget-[LabeledGlobalKey<_OverlayEntryWidgetState>#c466c] ← _Theatre ← Overlay-[LabeledGlobalKey#26f68] ← UnmanagedRestorationScope ← _FocusMarker ← Semantics ← FocusScope ← AbsorbPointer ← Listener ← ⋯ parentData: not positioned; offset=Offset(0.0, 0.0) constraints: MISSING size: MISSING Unfortunately, this object's geometry is not known at this time, probably because it has never been laid out. This means it cannot be accurately hit-tested. If you are trying to perform a hit test during the layout phase itself, make sure you only hit test nodes that have completed layout (e.g. the node's children, after their layout() method has been called).

调试控制台:

════════ Exception caught by rendering library ═════════════════════════════════
The following assertion was thrown during performLayout():
LayoutBuilder does not support returning intrinsic dimensions.

Calculating the intrinsic dimensions would require running the layout callback speculatively, which might mutate the live render object tree.
The relevant error-causing widget was
SliverFillRemaining
When the exception was thrown, this was the stack

The following RenderObject was being processed when the exception was fired: RenderSliverFillRemaining#ef0f7 relayoutBoundary=up1 NEEDS-LAYOUT NEEDS-COMPOSITING-BITS-UPDATE
RenderObject: RenderSliverFillRemaining#ef0f7 relayoutBoundary=up1 NEEDS-LAYOUT NEEDS-COMPOSITING-BITS-UPDATE
    needs compositing
    parentData: paintOffset=Offset(0.0, 0.0) (can use size)
    constraints: SliverConstraints(AxisDirection.down, GrowthDirection.forward, ScrollDirection.idle, scrollOffset: 0.0, remainingPaintExtent: 574.0, crossAxisExtent: 1034.0, crossAxisDirection: AxisDirection.right, viewportMainAxisExtent: 574.0, remainingCacheExtent: 824.0, cacheOrigin: 0.0)
    geometry: SliverGeometry(scrollExtent: 574.0, paintExtent: 574.0, maxPaintExtent: 574.0, cacheExtent: 574.0)
        scrollExtent: 574.0
        paintExtent: 574.0
        maxPaintExtent: 574.0
        cacheExtent: 574.0
    child: RenderFlex#0b053 NEEDS-LAYOUT NEEDS-COMPOSITING-BITS-UPDATE
        needs compositing
        parentData: paintOffset=Offset(0.0, -0.0)
        constraints: BoxConstraints(w=1034.0, h=574.0)
        size: Size(1034.0, 574.0)
        direction: horizontal
        mainAxisAlignment: start
        mainAxisSize: max
        crossAxisAlignment: center
        textDirection: ltr
        verticalDirection: down
        child 1: RenderSemanticsAnnotations#79122 relayoutBoundary=up1
            needs compositing
            parentData: offset=Offset(0.0, 0.0); flex=null; fit=null (can use size)
            constraints: BoxConstraints(0.0<=w<=Infinity, 0.0<=h<=574.0)
            size: Size(89.0, 574.0)
            child: RenderPhysicalModel#2413b relayoutBoundary=up2
                needs compositing
                parentData: <none> (can use size)
                constraints: BoxConstraints(0.0<=w<=Infinity, 0.0<=h<=574.0)
                layer: PhysicalModelLayer#dd0a6
                    engine layer: PhysicalShapeEngineLayer#2eafd
                    handles: 2
                    elevation: 0.0
                    color: Color(0xffffffff)
                size: Size(89.0, 574.0)
                elevation: 0.0
                color: Color(0xffffffff)
                shadowColor: Color(0xffffffff)
                shape: BoxShape.rectangle
                borderRadius: BorderRadius.zero
                child: _RenderInkFeatures#f1226 relayoutBoundary=up3
                    parentData: <none> (can use size)
                    constraints: BoxConstraints(0.0<=w<=Infinity, 0.0<=h<=574.0)
                    size: Size(89.0, 574.0)
        child 2: RenderConstrainedBox#5423b relayoutBoundary=up1
            parentData: offset=Offset(89.0, 0.0); flex=null; fit=null (can use size)
            constraints: BoxConstraints(0.0<=w<=Infinity, 0.0<=h<=574.0)
            size: Size(1.0, 574.0)
            additionalConstraints: BoxConstraints(w=1.0, 0.0<=h<=Infinity)
            child: RenderPositionedBox#2ef82 relayoutBoundary=up2
                parentData: <none> (can use size)
                constraints: BoxConstraints(w=1.0, 0.0<=h<=574.0)
                size: Size(1.0, 574.0)
                alignment: Alignment.center
                textDirection: ltr
                widthFactor: expand
                heightFactor: expand
                child: RenderPadding#25c65 relayoutBoundary=up3
                    parentData: offset=Offset(0.0, 0.0) (can use size)
                    constraints: BoxConstraints(0.0<=w<=1.0, 0.0<=h<=574.0)
                    size: Size(1.0, 574.0)
                    padding: EdgeInsets.zero
                    textDirection: ltr
        child 3: RenderSemanticsAnnotations#7f0ab relayoutBoundary=up1 NEEDS-LAYOUT NEEDS-COMPOSITING-BITS-UPDATE
            needs compositing
            parentData: offset=Offset(90.0, 0.0); flex=1; fit=FlexFit.tight (can use size)
            constraints: BoxConstraints(w=944.0, 0.0<=h<=574.0)
            size: Size(944.0, 574.0)
            child: RenderSemanticsAnnotations#466c4 relayoutBoundary=up2 NEEDS-LAYOUT NEEDS-COMPOSITING-BITS-UPDATE
                needs compositing
                parentData: <none> (can use size)
                constraints: BoxConstraints(w=944.0, 0.0<=h<=574.0)
                size: Size(944.0, 574.0)
                child: RenderSemanticsAnnotations#4f301 relayoutBoundary=up3 NEEDS-LAYOUT NEEDS-COMPOSITING-BITS-UPDATE
                    needs compositing
                    parentData: <none> (can use size)
                    constraints: BoxConstraints(w=944.0, 0.0<=h<=574.0)
                    size: Size(944.0, 574.0)
════════════════════════════════════════════════════════════════════════════════

════════ Exception caught by scheduler library ═════════════════════════════════
Cannot hit test a render box that has never been laid out.
════════════════════════════════════════════════════════════════════════════════

════════ Exception caught by scheduler library ═════════════════════════════════
Assertion failed:
!_debugDuringDeviceUpdate
is not true

在州一级,class String? addRole; 并从 Items<String>[] 中删除 ''

User Add

onPressed: () {
  bool isValid =
      _formkey.currentState!.validate();

  ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
          content: Text("form is $isValid")));
},
                              },

全组件


class _UserManagerState extends State<UserManager> {
  final _formkey = GlobalKey<FormState>();
  var addName = "";
  var addEmail = "";
  var addPassword = "";
  String? addRole;

  final nameController = TextEditingController();
  final emailController = TextEditingController();
  final passwordController = TextEditingController();
  final roleController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 2,
        child: Scaffold(
          appBar: AppBar(
            toolbarHeight: 20,
            bottom: const TabBar(
              tabs: [
                Tab(icon: Icon(Icons.person_add)),
                Tab(icon: Icon(Icons.edit)),
              ],
            ),
          ),
          body: TabBarView(
            children: [
              Center(
                child: Form(
                    key: _formkey,
                    child: SingleChildScrollView(
                      reverse: true,
                      child: Container(
                        width: 420,
                        margin: const EdgeInsets.all(10.0),
                        padding: const EdgeInsets.all(16),
                        decoration: BoxDecoration(
                          border: Border.all(color: Colors.grey),
                          borderRadius: const BorderRadius.all(
                            Radius.circular(10),
                          ),
                        ),
                        child: Column(
                          children: [
                            //const SizedBox(
                            //height: 50,
                            //),
                            const Text(
                              "Add name",
                              style: TextStyle(
                                fontSize: 20,
                                fontWeight: FontWeight.bold,
                                color: Colors.indigo,
                              ),
                            ),
                            const SizedBox(
                              height: 10,
                            ),
                            TextFormField(
                                minLines: 1,
                                autofocus: false,
                                keyboardType: TextInputType.text,
                                textInputAction: TextInputAction.next,
                                decoration: const InputDecoration(
                                  labelText: "Name",
                                  border: OutlineInputBorder(),
                                  errorStyle: TextStyle(
                                      color: Colors.redAccent, fontSize: 15),
                                ),
                                controller: nameController,
                                validator: (value) {
                                  if (value == null || value.isEmpty) {
                                    return 'Please Enter Name';
                                  }
                                  return null;
                                }),
                            const SizedBox(
                              height: 10,
                            ),
                            TextFormField(
                                autofocus: false,
                                minLines: 1,
                                keyboardType: TextInputType.emailAddress,
                                textInputAction: TextInputAction.next,
                                decoration: const InputDecoration(
                                  labelText: "Email Address",
                                  //hintText: "Email",
                                  border: OutlineInputBorder(),
                                  errorStyle: TextStyle(
                                      color: Colors.redAccent, fontSize: 15),
                                ),
                                controller: emailController,
                                validator: (value) {
                                  if (value == null || value.isEmpty) {
                                    return 'Please Enter Email ID';
                                  } else if (!value.contains('@')) {
                                    return 'Please Enter Valid Email ID';
                                  }
                                  return null;
                                }),
                            const SizedBox(
                              height: 10,
                            ),
                            TextFormField(
                                minLines: 1,
                                autofocus: false,
                                obscureText: true,
                                keyboardType: TextInputType.text,
                                textInputAction: TextInputAction.next,
                                decoration: const InputDecoration(
                                  labelText: "Password",
                                  border: OutlineInputBorder(),
                                  errorStyle: TextStyle(
                                      color: Colors.redAccent, fontSize: 15),
                                ),
                                controller: passwordController,
                                validator: (value) {
                                  if (value == null || value.isEmpty) {
                                    return 'Please Enter Password';
                                  }
                                  return null;
                                }),
                            const SizedBox(
                              height: 20,
                            ),
                            //
                            DropdownButtonFormField(
                              decoration: const InputDecoration(
                                labelText: "department",
                                border: OutlineInputBorder(),
                                errorStyle: TextStyle(
                                    color: Colors.redAccent, fontSize: 15),
                              ),
                              hint: const Text("select department"),
                              value: addRole,
                              onChanged: (String? newValue) {
                                setState(() {
                                  addRole = newValue!;
                                });
                              },
                              validator: (value) =>
                                  value == null ? 'field required' : null,
                              items: <String>[
                                'hr',
                                'dtp'
                              ].map<DropdownMenuItem<String>>((String value) {
                                return DropdownMenuItem<String>(
                                  value: value,
                                  child: Text(value),
                                );
                              }).toList(),
                            ),
                            const SizedBox(
                              height: 20,
                            ),
                            //
                            ElevatedButton(
                              style: ElevatedButton.styleFrom(
                                primary: Colors.red, // background
                                onPrimary: Colors.white, // foreground
                              ),
onPressed: () {
  bool isValid =
      _formkey.currentState!.validate();

  ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
          content: Text("form is $isValid")));
},
                              child: const Text('User Add'),
                            ),
                            const SizedBox(
                              height: 20,
                            ),
                          ],
                        ),
                      ),
                    )),
              ),
              Center(
                child: Text("Test"),
              )
            ],
          ),
        ),
      ),
    );
  }
}