0

I have a problem. I want to create a own button class with Icon and text. Unfortunately I got on my screen Null check operator used on a null value and Bottom Overflowed by 99516 Pixels.

How can I solve this kind of issues?

I tried with an if condition, as you can see here

                ? Text(label!.name)
                : Container(), // Text unter dem Icon

But nothing worked

Button class

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import '../utils/definitions.dart';
import 'icons.dart';
import '../model/label.dart';

class LabelButton extends StatelessWidget {
  final Label? label;
  final VoidStringCallback? process;

  LabelButton({required this.label, required this.process, Key? key})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        process!(label!.name);
        HapticFeedback.lightImpact();
      },
      child: Container(
        width: 100, // Breite anpassen
        height: 100, // Höhe anpassen
        decoration: BoxDecoration(
          color: Colors.grey, // Hintergrundfarbe anpassen
          border: Border.all(
            color: Colors.black, // Rahmenfarbe anpassen
            width: 2, // Rahmendicke anpassen
          ),
          borderRadius: BorderRadius.circular(12), // Eckradius anpassen
        ),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Icon(iconList
                .firstWhere((element) => element.name == label!.uiIcon)
                .icon),
            (label != Null)
                ? Text(label!.name)
                : Container(), // Text unter dem Icon
          ],
        ),
      ),
    );
  }

  const LabelButton._(this.label, this.process, {Key? key}) : super(key: key);

  static LabelButton createBlank() {
    return const LabelButton._(null, null);
  }
}

How I am calling this inside my Main

  @override
  Widget build(BuildContext context) {
    var widgetList = labels.map((Label l) {
      return LabelButton(label: l, process: processClick);
    }).toList();

    const int buttonCountPerRow = 5;
    var chunks = [];

    for (var i = 0; i < widgetList.length; i += buttonCountPerRow) {
      var end = (i + buttonCountPerRow < widgetList.length)
          ? i + buttonCountPerRow
          : widgetList.length;
      chunks.add(widgetList.sublist(i, end));
    }
    if (chunks.isNotEmpty) {
      var remainder = buttonCountPerRow - chunks.last.length;
      for (var i = 0; i != remainder; ++i) {
        chunks.last.add(LabelButton.createBlank());
      }
    }
Test
  • 571
  • 13
  • 32
  • If I look at the rest of your code, there seem to be quite some places where you expect the `label` to just exist. If you want to be certain the label exists, don't make the variable nullable (`Label?`). The same holds for `process`. And if null is allowed, you have to perform the checks everywhere. Or you can use `label?.name`, which will also return `null` – Marnix Jun 13 '23 at 07:01
  • @Marnix Thank you for your answer. Isn't this `final Label? label;` not enough? – Test Jun 13 '23 at 07:02
  • `final Label? label` makes it nullable, meaning that the value can be `null`, meaning it doesn't exist. You cannot call things like `label!.name`, because you tell dart that label is definitely not null. While it is (`createBlank`). – Marnix Jun 13 '23 at 07:03
  • @Marnix ahh I see. Thanks. But when I remove the `!` from e.g. `label!.name` I got `The function can't be unconditionally invoked because it can be 'null'. (Documentation) Try adding a null check ('!').`. Should I try with a normal `ìf-condition`? – Test Jun 13 '23 at 07:04
  • In the onTap event, your default process has a value. But in fact you assign null to the process. So when you use process, it is best to judge whether it is null. – Nullable Jun 13 '23 at 07:05
  • I think `LabelButton._` is the problem, because when I am calling `createBlank()` it should create an "empty icon with text" (so nothing should be show). – Test Jun 13 '23 at 07:08
  • I tried with an if-conditon `if (label != Null) { return GestureDetector(`....` but still the same error... :/ – Test Jun 13 '23 at 07:17
  • You have two problems, the first problem: `Null check operator used on a null value`, you can refer to this [answer](https://stackoverflow.com/questions/64278595/null-check-operator-used-on -a-null-value). The second question, beyond the screen, you can use the scrollview as the parent widget. – Nullable Jun 13 '23 at 07:53

1 Answers1

0

Make sure that you check all the uses of label and process for null or not. Depending on what you want to do with the fact that label is null, you have to check if the code can continue or not.

There are multiple options for null checking, depending on your use case.

For example you could do: label?.name, which means that it will return null if label is null, otherwise the name. This might work in some cases of your code, if your process accepts null for example.

In the case of the column with icon and label you will have to do some other checks. For example, check if the label is null and only then create a Column with children.

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import '../utils/definitions.dart';
import 'icons.dart';
import '../model/label.dart';

class LabelButton extends StatelessWidget {
  final Label? label;
  final VoidStringCallback? process;

  LabelButton({required this.label, required this.process, Key? key})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        process?.call(label?.name); // call process if it is not null, with name if label is not null, otherwise with null.
        HapticFeedback.lightImpact();
      },
      child: Container(
        width: 100, // Breite anpassen
        height: 100, // Höhe anpassen
        decoration: BoxDecoration(
          color: Colors.grey, // Hintergrundfarbe anpassen
          border: Border.all(
            color: Colors.black, // Rahmenfarbe anpassen
            width: 2, // Rahmendicke anpassen
          ),
          borderRadius: BorderRadius.circular(12), // Eckradius anpassen
        ),
        // I added an if check here so we are sure that label is not null in the code below
        child: if(label != null) Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Icon(iconList
                .firstWhere((element) => element.name == label!.uiIcon)
                .icon),
            Text(label!.name)
          ],
        ),
      ),
    );
  }

  const LabelButton._(this.label, this.process, {Key? key}) : super(key: key);

  static LabelButton createBlank() {
    return const LabelButton._(null, null);
  }
}
Marnix
  • 6,384
  • 4
  • 43
  • 78
  • Thank you for your answer! With that I got the following error `9:30: Error: Expected ':' before this. process?(label?.name); // call process if it is not null, with name if label is not null, otherwise with null.`. – Test Jun 13 '23 at 08:13
  • Also `rror: Expected an identifier, but got ';'. Try inserting an identifier before ';'. process?(label?.name); // call process if it is not null, with name if label is not null, otherwise with null.` – Test Jun 13 '23 at 08:25
  • I changed it for you, needed to change the line to `?.call()` – Marnix Jun 13 '23 at 11:32