Почему AlertDialog генерирует ошибку maxWidth: Infinity только на определенных устройствах? - PullRequest
0 голосов
/ 31 марта 2020

Я заметил, что мой виджет Dialog прекрасно работает на моем телефоне, но выдает исключение на моем планшете. Как это возможно?
Я попытался установить width на Dialog, обернув его Container, но это не решает проблему.

Вот сообщение об ошибке:

I/flutter (17549): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY 

╞═════════════════════════════════════════════════════════
I/flutter (17549): The following NoSuchMethodError was thrown during performLayout():
I/flutter (17549): The method 'copyWith' was called on null.
I/flutter (17549): Receiver: null
I/flutter (17549): Tried calling: copyWith(maxWidth: Infinity)
I/flutter (17549): 
I/flutter (17549): The relevant error-causing widget was:
I/flutter (17549):   AlertDialog
I/flutter (17549):   file:///...dialogs/EditTagsDialog.dart:42:41

Вот так выглядит мой диалог:

@override
  Widget build(BuildContext context) => AlertDialog(
    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
    title: Container(
      alignment: Alignment.center,
      child: Text("Select Tags"),
    content: ListView.builder(
      itemCount: tags.length +1,
      itemBuilder: (context, index) {
        return GestureDetector(
            onTap: () { ... },
            child: buildRow(index)
        );
      },
    ),
    actions: <Widget>[
          CancelButton(),
          SaveButton()
        ],
  );

Widget _buildRow(int index) {
    if(index > 0) {
      return Row(
        children: <Widget>[
          Flexible(
            flex: 1,
            child: Checkbox( ... ),
          ),
          Flexible(
            flex: 3,
            child: Text(tags[index-1]))
        ],
      );
    } else {
      return Row(
        children: <Widget>[
          SizedBox(
            width: 160,
            child:  TextField(
              decoration: InputDecoration(hintText: "Add a tag", hintStyle: TextStyle(color:  Theme.of(context).textTheme.display2.color)),
              textInputAction: TextInputAction.done,
              controller: _textEditingController,
              style: TextStyle(color: Theme.of(context).textTheme.display1.color),
            ),
          ),
          IconButton(
            icon: Icon(Icons.check),
            onPressed: () { ... };
          )
        ],
      );
    }
  }

Вот полная трассировка стека:

I/flutter (17549): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY 

╞═════════════════════════════════════════════════════════
I/flutter (17549): The following NoSuchMethodError was thrown during performLayout():
I/flutter (17549): The method 'copyWith' was called on null.
I/flutter (17549): Receiver: null
I/flutter (17549): Tried calling: copyWith(maxWidth: Infinity)
I/flutter (17549): 
I/flutter (17549): The relevant error-causing widget was:
I/flutter (17549):   AlertDialog
I/flutter (17549):   file:///.../dialogs/EditTagsDialog.dart:42:41
I/flutter (17549): 
I/flutter (17549): When the exception was thrown, this was the stack:
I/flutter (17549): #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
I/flutter (17549): #1      _RenderButtonBarRow.constraints (package:flutter/src/material/button_bar.dart:292:30)
I/flutter (17549): #2      RenderObject.debugFillProperties (package:flutter/src/rendering/object.dart:2791:68)
I/flutter (17549): #3      RenderBox.debugFillProperties (package:flutter/src/rendering/box.dart:2417:11)
I/flutter (17549): #4      RenderFlex.debugFillProperties (package:flutter/src/rendering/flex.dart:1015:11)
I/flutter (17549): #5      DiagnosticableNode.builder (package:flutter/src/foundation/diagnostics.dart:2900:14)
I/flutter (17549): #6      DiagnosticableNode.style (package:flutter/src/foundation/diagnostics.dart:2907:70)
I/flutter (17549): #7      DiagnosticsNode.toString (package:flutter/src/foundation/diagnostics.dart:1629:12)
I/flutter (17549): #8      _StringBase._interpolate (dart:core-patch/string_patch.dart:845:19)
I/flutter (17549): #9      TextTreeRenderer.render.visitor (package:flutter/src/foundation/diagnostics.dart:1140:69)
I/flutter (17549): #10     TextTreeRenderer.render.visitor (package:flutter/src/foundation/diagnostics.dart:1142:22)
I/flutter (17549): #11     TextTreeRenderer.render.visitor (package:flutter/src/foundation/diagnostics.dart:1142:22)
I/flutter (17549): #12     TextTreeRenderer.render.visitor (package:flutter/src/foundation/diagnostics.dart:1142:22)
I/flutter (17549): #13     TextTreeRenderer.render.visitor (package:flutter/src/foundation/diagnostics.dart:1142:22)
I/flutter (17549): #14     TextTreeRenderer.render (package:flutter/src/foundation/diagnostics.dart:1150:14)
I/flutter (17549): #15     TextTreeRenderer.render (package:flutter/src/foundation/diagnostics.dart:1294:39)
I/flutter (17549): #16     FlutterError.dumpErrorToConsole (package:flutter/src/foundation/assertions.dart:652:11)
I/flutter (17549): #17     FlutterError.reportError (package:flutter/src/foundation/assertions.dart:741:14)
I/flutter (17549): #18     RenderObject._debugReportException (package:flutter/src/rendering/object.dart:1270:18)
I/flutter (17549): #19     RenderObject.layout (package:flutter/src/rendering/object.dart:1731:7)
I/flutter (17549): #20     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17549): #21     _RenderCustomClip.performLayout (package:flutter/src/rendering/proxy_box.dart:1232:11)
I/flutter (17549): #22     RenderObject.layout (package:flutter/src/rendering/object.dart:1724:7)
I/flutter (17549): #23     RenderConstrainedBox.performLayout (package:flutter/src/rendering/proxy_box.dart:259:13)
I/flutter (17549): #24     RenderObject.layout (package:flutter/src/rendering/object.dart:1724:7)
I/flutter (17549): #25     RenderPositionedBox.performLayout (package:flutter/src/rendering/shifted_box.dart:392:13)
I/flutter (17549): #26     RenderObject.layout (package:flutter/src/rendering/object.dart:1724:7)
I/flutter (17549): #27     RenderPadding.performLayout (package:flutter/src/rendering/shifted_box.dart:206:11)
I/flutter (17549): #28     RenderObject.layout (package:flutter/src/rendering/object.dart:1724:7)
I/flutter (17549): #29     RenderPadding.performLayout (package:flutter/src/rendering/shifted_box.dart:206:11)
I/flutter (17549): #30     RenderObject.layout (package:flutter/src/rendering/object.dart:1724:7)
I/flutter (17549): #31     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17549): #32     RenderObject.layout (package:flutter/src/rendering/object.dart:1724:7)
I/flutter (17549): #33     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17549): #34     RenderObject.layout (package:flutter/src/rendering/object.dart:1724:7)
I/flutter (17549): #35     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17549): #36     RenderObject.layout (package:flutter/src/rendering/object.dart:1724:7)
I/flutter (17549): #37     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17549): #38     RenderObject.layout (package:flutter/src/rendering/object.dart:1724:7)
I/flutter (17549): #39     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17549): #40     RenderObject.layout (package:flutter/src/rendering/object.dart:1724:7)
I/flutter (17549): #41     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17549): #42     RenderObject.layout (package:flutter/src/rendering/object.dart:1724:7)
I/flutter (17549): #43     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17549): #44     RenderOffstage.performLayout (package:flutter/src/rendering/proxy_box.dart:3168:13)
I/flutter (17549): #45     RenderObject.layout (package:flutter/src/rendering/object.dart:1724:7)
I/flutter (17549): #46     RenderStack.performLayout (package:flutter/src/rendering/stack.dart:505:15)
I/flutter (17549): #47     RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1584:7)
I/flutter (17549): #48     PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:844:18)
I/flutter (17549): #49     RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:344:19)
I/flutter (17549): #50     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:774:13)
I/flutter (17549): #51     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:283:5)
I/flutter (17549): #52     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1102:15)
I/flutter (17549): #53     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1041:9)
I/flutter (17549): #54     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:957:5)
I/flutter (17549): #58     _invoke (dart:ui/hooks.dart:259:10)
I/flutter (17549): #59     _drawFrame (dart:ui/hooks.dart:217:3)
I/flutter (17549): (elided 3 frames from package dart:async)
I/flutter (17549): 
I/flutter (17549): The following RenderObject was being processed when the exception was fired: RenderPhysicalShape#3b374 relayoutBoundary=up2 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE:
I/flutter (17549):   needs compositing
I/flutter (17549):   creator: PhysicalShape ← _MaterialInterior ← Material ← ConstrainedBox ← Center ← MediaQuery ←
I/flutter (17549):     Padding ← AnimatedPadding ← Dialog ← AlertDialog ← EditTagsDialog ← Builder ← ⋯
I/flutter (17549):   parentData: <none> (can use size)
I/flutter (17549):   constraints: BoxConstraints(280.0<=w<=720.0, 0.0<=h<=1160.0)
I/flutter (17549):   size: MISSING
I/flutter (17549):   elevation: 24.0
I/flutter (17549):   color: Color(0xffffffff)
I/flutter (17549):   shadowColor: Color(0xffffffff)
I/flutter (17549):   clipper: ShapeBorderClipper
I/flutter (17549): This RenderObject had the following descendants (showing up to depth 5):
I/flutter (17549):     child: RenderCustomPaint#a1260 relayoutBoundary=up3 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
I/flutter (17549):       child: _RenderInkFeatures#29c07 relayoutBoundary=up4 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
I/flutter (17549):         child: RenderIntrinsicWidth#dce05 relayoutBoundary=up5 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
I/flutter (17549):           child: RenderFlex#1a3c5 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
I/flutter (17549):             child 1: RenderPadding#f4dc8 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
I/flutter (17549):             child 2: RenderPadding#45b2a NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
I/flutter (17549):             child 3: RenderPadding#8c9cf NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
I/flutter (17549): ════════════════════════════════════════════════════════════════════════════════════════════════════

Вот полный исходный код этого класса:

class EditTagsDialog extends StatefulWidget {
  final List<String> tags;
  final Function cancelCallback;
  final Function(List<String>) saveCallback;

  const EditTagsDialog(
      {Key key, this.tags, this.saveCallback, this.cancelCallback})
      : super(key: key);

  @override
  State<StatefulWidget> createState() => _EditTagsDialogState();
}

class _EditTagsDialogState extends State<EditTagsDialog> {
  TextEditingController _textEditingController;
  List<String> _selectedTags;
  List<String> _allTags;
  TagService _tagService;

  @override
  void initState() {
    super.initState();
    _tagService = TagService();
    _textEditingController = TextEditingController();
    _selectedTags = this.widget.tags;
    _allTags = _selectedTags;
    _tagService.findAll().then((tags) {
      setState(() {
        _allTags = tags;
      });
    });
  }

  @override
  Widget build(BuildContext context) => AlertDialog(
    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
    title: Container(
      alignment: Alignment.center,
      child: Text(AppLocalizations.of(context).translate("select_tags"),
          style: TextStyle(
              color: Theme.of(context).textTheme.display1.color))),
    content: ListView.builder(

      itemCount: _allTags.length +1,
      itemBuilder: (context, index) {
        return GestureDetector(
            onTap: () {
              if(index > 0) {
                  _onRowTap(_allTags[index]);
              } 
            },
            child: _buildRow(index)
        );
      },
    ),
    actions: <Widget>[
          CancelButton(),
          SaveButton(save: () {
            this.widget.saveCallback(_selectedTags);
          })
        ],
  );

  void _onRowTap(String tag) {
    setState(() {
      _selectedTags.contains(tag)
          ? _selectedTags.remove(tag)
          : _selectedTags.add(tag);
    });
  }

  Widget _buildRow(int index) {
    if(index > 0) {
      return Row(
        children: <Widget>[
          Flexible(
            flex: 1,
            child: Checkbox(
                value: _selectedTags.contains(_allTags[index-1]),
                onChanged: (bool selected) {
                  setState(() {
                    selected
                        ? _selectedTags.add(_allTags[index-1])
                        : _selectedTags.remove(_allTags[index-1]);
                  });
                }),
          ),
          Flexible(
            flex: 3,
            child: Text(_allTags[index-1],
              style: TextStyle(
                  color: Theme.of(context)
                      .textTheme
                      .display1
                      .color)
              )
          )
        ],
      );
    } else {
      return Row(
        children: <Widget>[
          SizedBox(
            width: 160,
            child:  TextField(
              decoration: InputDecoration(hintText: AppLocalizations.of(context).translate("add_tag"), hintStyle: TextStyle(color:  Theme.of(context).textTheme.display2.color)),
              textInputAction: TextInputAction.done,
              controller: _textEditingController,
              style: TextStyle(color: Theme.of(context).textTheme.display1.color),
            ),
          ),
          IconButton(
            icon: Icon(Icons.check, color: Theme.of(context).buttonColor),
            onPressed: (){
              setState(() {
                _allTags.add(_textEditingController.text);
              });
              TagService().createTagIfNotExisting(_textEditingController.text);
              _textEditingController.clear();
            },
          )
        ],
      );
    }
  }
}
...