Ошибка: LayoutBuilder не поддерживает возврат внутренних размеров

Ошибка: LayoutBuilder не поддерживает возврат внутренних размеров.

void showDialogWithLayoutBuilder(){
    showDialog(context: context, builder: (context){
      return AlertDialog(
        content: LayoutBuilder(
          builder: (context, constraints){
            return Text("Very loooooong text");
          },
        ),
      );
    });
  }

Как заставить это работать? Я не хочу обертывать его, устанавливая жестко закодированные значения height и width. Это минимальный воспроизводимый код реальной проблемы. В реальном случае LayoutBuilder — это пакет под названием AutoSizeText.

Итак, какова цель использования LayoutBuilder, кроме использования его родительских ограничений для наложения на его дочерний элемент, вы должны обернуть этот текст виджетом поля с ограничениями min^height построителя макета.

A-E 14.06.2024 04:33

Я не понимаю, почему AlertDialog вообще использует IntrinsicWidth. Я проверил код, похоже Dialog его не использует. Мне любопытно, что произойдет, если мы удалим эту оболочку IntrinsicWidth.

TSR 14.06.2024 04:44
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
83
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам нужно обернуть LayoutBuilderRenderBox, который игнорирует внутренние функции, как и LayoutBuilder, но без ошибок и, возможно, без дефектов макета.

AlertDialog использует InstrinsicWidth, чтобы диалог выглядел так, как он есть. В примере вы можете видеть два SizedBox разных размеров, но оба виджета в конечном итоге имеют одинаковую ширину 280, это значение берется из ограничения minWidth в Dialog; в этом макете столбец выберет самую большую minWidth из своих дочерних элементов в качестве ширины для всех из них.

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/foundation.dart';

void main() {
  if (kDebugMode) {
    debugCheckIntrinsicSizes = true;
  }

  runApp(MaterialApp(home: Home()));
}

class Home extends StatelessWidget {
  const Home({super.key});

  String get o => List.generate(1000, (i) => 'o').join();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: () => showDialog(
          context: context,
          builder: (_) => AlertDialog(
            scrollable: true,
            title: const SizedBox(
              width: 0.0,
              child: Text('Short title'),
            ),
            content: SizedByChild(
              child: LayoutBuilder(
                builder: (_, __) => SizedBox(
                  width: double.infinity,
                  child: Text('Very l${o}ng text'),
                ),
              ),
            ),
          ),
        ),
        child: const Icon(Icons.add),
      ),
    );
  }
}

class SizedByChild extends SingleChildRenderObjectWidget {
  const SizedByChild({super.key, super.child});

  @override
  RenderObject createRenderObject(BuildContext context) => RenderWithChildSize();
}

class RenderWithChildSize extends RenderBox with RenderObjectWithChildMixin<RenderBox> {
  @override
  void performLayout() {
    child?.layout(constraints, parentUsesSize: true);
    size = child?.size ?? constraints.smallest;
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    if (child != null) {
      context.paintChild(child as RenderBox, offset);
    }
  }

  @override
  bool hitTest(BoxHitTestResult result, {required Offset position}) {
    return child?.hitTest(result, position: position) ?? false;
  }

  @override
  double? computeDistanceToActualBaseline(TextBaseline baseline) {
    return child?.getDistanceToActualBaseline(baseline);
  }
}

Не могли бы вы объяснить, каковы ограничения/компромиссы этого решения? Особенно эта часть "но без ошибок и возможно без дефектов верстки".

TSR 20.06.2024 19:29

Потому что решение просто обходит проверки. Я не знаю, как LayoutBuilder мог бы сделать плохую разметку, но предполагаю, что есть как минимум один крайний случай. Я пробовал использовать анимированный контейнер, и у меня не возникло никаких проблем, так что это может быть просто выбор разработчиков, чтобы стимулировать использование более качественных/быстрых макетов, как в случае с setState (см. обсуждение дизайна).

SrPanda 20.06.2024 20:39

Другие вопросы по теме

Как получить состояние CanPop PopScope на дочернем виджете Flutter?
Ошибка: сопоставление шаблонов в экземпляре не поддерживается в -source 8, во Flutter
Почему ListView.builder зависает приложение, когда из обратного вызова itemBuilder возвращается пустой виджет-контейнер?
App_plugin_loader Плагин Gradle обязательно использует метод Apply script, который устарел и будет удален в будущем выпуске. Ошибка во flutter
Flutter - значок пользовательского маркера Google Maps BitmapDescriptor.asset() не отображается
Не могу запустить приложение Flutter на устройстве Iphone для отладки на Mac M1
Приложение Flutter показывает пустой экран после интеграции Firebase
Как я могу условно изменить цвет текста на плитке во время воспроизведения звука
Нетерпеливые флаттера против ленивых одиночек. Загрузка и создание экземпляров
Флаттерная нижняя навигация исчезает при нажатии на другую страницу с помощью кнопки