GithubHelp home page GithubHelp logo

pingbird / boxy Goto Github PK

View Code? Open in Web Editor NEW
431.0 431.0 25.0 16.2 MB

Overcome limitations of built-in layouts, advanced flex, custom multi-child layouts, slivers, and more!

Home Page: https://boxy.wiki

License: Other

Dart 90.21% Kotlin 0.03% Swift 0.10% Objective-C 0.01% HTML 0.87% Shell 0.04% CSS 1.51% CMake 2.45% C++ 4.60% C 0.18%
flutter

boxy's Introduction

A wild ping appears!

You may know me from my work on Flutter or one of many other projects:

  • Boxy - A popular package for creating complex layouts in Flutter.
  • Puro - A high-tech version manager for Flutter.
  • DZ3 - High level Dart bindings to the Z3 theorem prover.
  • Notes - A place for my personal notes.

I also do a lot of low-level systems, robotics, cybersecurity, proof assistants, and cloud infrastructure.

boxy's People

Contributors

jtarkowski27 avatar mattermoran avatar pingbird avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

boxy's Issues

How to use column as dominant?

I want circleavatar's radius to be equal to the text column

BoxyRow(
        children: [
          CircleAvatar(
            backgroundColor: Colors.white,
            child: Padding(
              padding: const EdgeInsets.all(5.0),
              child: CircleAvatar(
                backgroundImage: imageProvider,
              ),
            ),
          ),
          const SizedBox(width: 8),
          Dominant(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisSize: MainAxisSize.min,
              children: [
                Text(
                  authorName,
                  style: Theme.of(context)
                      .textTheme
                      .headline2!
                      .copyWith(color: Colors.black),
                ),
                Text(
                  title,
                  style: Theme.of(context)
                      .textTheme
                      .headline3!
                      .copyWith(color: Colors.black),
                )
              ],
            ),
          )
        ],
      ),

In the code above the circle avatar never takes radius of text column and defaults back to 20. but if I give radius some very large value like 100 then circle avatar never exceeded the boundary of the textcolumn.

[Question] - Can I use Boxy to build a Flutter version of Angular FlexLayouts

Hi, I am pretty impressed by what you did with boxy!

I am looking to build Angular FlexLayout for Flutter.

Responsive API - https://github.com/angular/flex-layout/wiki/Responsive-API

I am wondering if I can use Boxy for this. I'd appreciate it if you have any advice/ideas on how to accomplish the example shown below, or if you want to collaborate. I would be more than happy to be a part of it.

Psuedo Code

FxLayout (
 layout: FxLayout.row,                               // by default  - displays as column
 md: FxLayout.column,                             // on medium screen - displays as column
 ltMd: FxLayout.column,                          // less than medium screens - displays as column
 mainAxisAlign: FxLayoutAlign.center,
 crossAxisAlign: FxLayoutAlign.center,
 gap: FxSize(size: 10, unit: FxUnit.dp /*default*/)
  children: [
    FxFlex (
       fill: true                                                   // very similar to Dominant
       order: 0,
       align: FxFlexAlign.start,
       child: Text('1st Child'),
     ),
    FxFlex (
       order: 1,                                                  // You can switch the order of the flex.
       align: FxFlexAlign.center,
       size: FxSize(size: 90, unit: FxUnit.percentage ),
       child: Text('2nd Child'),
     )
  ]
)

Cheers!

Sliver in CustomBoxy

Hello, can we have a sliver inside a customboxy?
I am getting error.

Thanks in advance.

Child of Dominant widget overflows when Text has more than one line.

Hello,
I'm using a BoxyRow to size the image on left with the height of the content on the right.

Consider the code:

import 'package:boxy/flex.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(home: MyHomePage()));
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Boxy Test')),
      body: ListView(children: [
        Card(
          child: BoxyRow(children: [
            SizedBox(
              width: 100,
              child: Image.network(
                'https://repository-images.githubusercontent.com/31792824/fb7e5700-6ccc-11e9-83fe-f602e1e1a9f1',
                fit: BoxFit.cover,
              ),
            ),
            Dominant.expanded(
              child: Column(
                children: [
                  Text(
                    'some very long text that does not fit in one single line',
                    overflow: TextOverflow.ellipsis,
                    // maxLines: 2,
                    style: Theme.of(context).textTheme.headline6,
                  ),
                  Container(
                    padding: const EdgeInsets.all(8),
                    height: 100,
                    color: Colors.grey,
                    child: Text('Some other widgets'),
                  ),
                ],
              ),
            )
          ]),
        ),
      ]),
    );
  }
}

It works as intended:
Screenshot_20210604-090257~2

However, uncommenting maxLines: 2 in the Text Widget, an overflow occurs.
Screenshot_20210604-093614~2

I'm unsure what's going wrong or if that is the intended behavior.

Help needed on animating with layout.

Hi, I need some help on using Boxy.

Basically what I want to make is an expandable card widget. In which it's height can dynamically change depending on the length of the title.

What I basically did is make two widgets. ListCardLayer and ExpansionButtonLayer. The ExpansionButtonLayer's size should depend on the ListCardLayer. And for the most part I got it working. One thing to note (this is what causing my problem) is that the height of the expansion button, should be the same as the ListCard when it is not expanded, and is shortened to 51 px when expanded.

test

The problem that I face is when animating the expansion button. I tried using AnimatedContainer and gave it a height of null when it is not expanded and 51 when it is expanded. But I got this error.

Cannot interpolate between finite constraints and unbounded constraints.

Some advice on this would be greatly appreciated. If you'd want me to give a recording of the error while animating do tell me. (the error only pops up while animating. After the animation is finished, the expansion button is of correct size)

class ListCardBoxyDelegate extends BoxyDelegate {
  final bool isExpanded;

  ListCardBoxyDelegate({
    required this.isExpanded,
  });

  @override
  Size layout() {
    final listCardLayer = getChild(#listCardLayer);
    final expansionButtonLayer = getChild(#expansionButtonLayer);

    final listCardLayerSize = listCardLayer.layout(constraints);
    listCardLayer.position(Offset.zero);

    layoutData = listCardLayerSize;

    expansionButtonLayer.layout(constraints.tighten(
      width: listCardLayerSize.width,
      height: listCardLayerSize.height,
    ));

    return Size(listCardLayerSize.width, listCardLayerSize.height);
  }

  @override
  bool shouldRelayout(ListCardBoxyDelegate old) => true;

  @override
  bool shouldRepaint(ListCardBoxyDelegate old) => true;
}
CustomBoxy(
              delegate: ListCardBoxyDelegate(isExpanded: isExpanded),
              children: [
                BoxyId(
                  id: #listCardLayer,
                  child: listCardLayer,
                ),
                BoxyId(
                  id: #expansionButtonLayer,
                  child: expansionButtonLayer,
                ),
              ],
            ),
class ExpansionButtonLayer extends StatelessWidget {
  final bool isExpanded;
  final VoidCallback onPressed;

  const ExpansionButtonLayer({
    Key? key,
    required this.isExpanded,
    required this.onPressed,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.topRight,
      child: AnimatedContainer(
        duration: 350.milliseconds,
        width: 51,
        //height: isExpanded ? 51 : null,
        margin: EdgeInsets.only(right: 6, top: 6, bottom: 6),
        child: Material(
          borderRadius: BorderRadius.circular(20.0),
          color: kcSecondaryLighterShadeColor,
          child: Ink(
            child: InkWell(
              borderRadius: BorderRadius.circular(20.0),
              onTap: onPressed,
              splashColor: Theme.of(context).primaryColor.withOpacity(0.20),
              highlightColor: Theme.of(context).primaryColor.withOpacity(0.15),
              child: Align(
                child: Icon(Icons.expand_more),
              ),
            ),
          ),
        ),
      ),
    );
  }
}
class ListCardLayer extends StatefulWidget {
  final Function()? onPressed;

  const ListCardLayer({
    Key? key,
    required this.isExpanded,
    required this.onPressed,
  }) : super(key: key);

  final bool isExpanded;

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

class _ListCardLayerState extends State<ListCardLayer> with AnimationMixin {
  //late AnimationController animController;
  late Animation<double> view;

  @override
  void initState() {
    super.initState();

    final CurvedAnimation curve = CurvedAnimation(
      parent: controller,
      curve: Curves.fastOutSlowIn,
      reverseCurve: Curves.fastOutSlowIn.flipped,
    );

    view = Tween<double>(begin: 0.0, end: 1.0).animate(curve);

    controller.addListener(() {
      setState(() {});
    });

    widget.isExpanded
        ? controller.play(duration: 350.milliseconds)
        : controller.playReverse(duration: 350.milliseconds);
  }

  @override
  void didUpdateWidget(covariant ListCardLayer oldWidget) {
    super.didUpdateWidget(oldWidget);
    widget.isExpanded
        ? controller.play(duration: 350.milliseconds)
        : controller.playReverse(duration: 350.milliseconds);
  }

  @override
  Widget build(BuildContext context) {
    return ClipRRect(
      borderRadius: BorderRadius.circular(20),
      child: Material(
        color: Theme.of(context).canvasColor,
        child: Ink(
          child: InkWell(
            splashColor: Theme.of(context).primaryColor.withOpacity(0.20),
            highlightColor: Theme.of(context).primaryColor.withOpacity(0.15),
            onTap: widget.onPressed,
            child: Column(
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Expanded(
                      child: Container(
                        padding: const EdgeInsets.only(
                            left: 24, right: 24, top: 18, bottom: 18),
                        alignment: Alignment.centerLeft,
                        child: Text(
                          allListSGSnip[0].sgName,
                          style: appTextTheme(context)
                              .headline2!
                              .copyWith(fontSize: 20),
                        ),
                      ),
                    ),
                    const SizedBox(width: 51)
                  ],
                ),
                ClipRect(
                  child: Align(
                    heightFactor: view.value,
                    child: Opacity(
                      opacity: view.value,
                      child: Container(
                        margin: EdgeInsets.only(left: 24, bottom: 24),
                        child: Text(
                          allListSGSnip[0].sgDesc,
                          style: appTextTheme(context).bodyText1,
                        ),
                      ),
                    ),
                  ),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Visual look of an unexpanded and expanded card which I'm trying to make.
Group Page โ€“ 2

`layers.clipPath()` does not apply `paintOffset` to `path` correctly when used in `paint()`.

layers.clipPath() does not apply paintOffset to path correctly when used in paint().
It works as expected in paintChildren()

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

void main(List<String> args) {
  runApp(MaterialApp(
    theme: ThemeData.from(colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.purple)),
    home: Scaffold(
      appBar: AppBar(
        title: Text("Demo"),
      ),
      body: MyWidget(),
    ),
  ));
}

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

  @override
  Widget build(BuildContext context) {
    return DecoratedBox(
      decoration: BoxDecoration(
        border: Border.all(color: Colors.black, width: 2.0),
      ),
      child: CustomBoxy(delegate: Delegate()),
    );
  }
}

class Delegate extends BoxyDelegate {
  @override
  Size layout() {
    return Size(300.0, 300.0);
  }

  @override
  void paint() {
    layers.clipPath(
      path: Path()..addRect(Rect.fromLTWH(100.0, 100.0, 100.0, 100.0)),
      paint: () {
        canvas.drawRect(Rect.fromLTWH(0.0, 0.0, 300.0, 300.0), Paint()..color = Colors.blue);
      },
    );
  }
}

Problem with rendering a CustomBoxy when a new item is added to an animated list

Boxy is a great library and makes a layout possible that I could not achieve with just normal Rows and Columns. However, I encounter a problem when I add an item to an animated list (of an external library), while the initial rendering of the list does not give any problems. Hopefully some help is possible.

I get the following error after adding a new item to a list:

โ•โ•โ•โ•โ•โ•โ•โ• Exception caught by rendering library โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
The following assertion was thrown during performLayout():
'package:flutter/src/rendering/object.dart': Failed assertion: line 1048 pos 12: '_debugDoingLayout': is not true.

The relevant error-causing widget was
_CustomBoxy
When the exception was thrown, this was the stack
#2      PipelineOwner._enableMutationsToDirtySubtrees
#3      RenderObject.invokeLayoutCallback
#4      InflatingRenderObjectMixin._allowSubtreeMutation
#5      InflatingRenderObjectMixin.flushInflateQueue
#6      InflatingRenderObjectMixin.performLayout.<anonymous closure>
#7      InflatingElement._wrapInflater
#8      InflatingRenderObjectMixin.performLayout
#9      RenderBoxyMixin.performLayout
#10     RenderObject.layout
#11     RenderBox.layout
#12     RenderProxyBoxMixin.performLayout
#13     RenderObject.layout
#14     RenderBox.layout
#15     RenderProxyBoxMixin.performLayout
#16     RenderObject.layout
#17     RenderBox.layout
#18     RenderProxyBoxMixin.performLayout
#19     RenderCustomPaint.performLayout
#20     RenderObject.layout
#21     RenderBox.layout
#22     RenderProxyBoxMixin.performLayout
#23     _RenderCustomClip.performLayout
#24     RenderObject.layout
#25     RenderBox.layout
#26     RenderPadding.performLayout
#27     RenderObject.layout
#28     RenderBox.layout
#29     RenderProxyBoxMixin.performLayout
#30     RenderObject.layout
#31     RenderBox.layout
#32     AnimatedRenderSliverList.measureItem.<anonymous closure>
#33     AnimatedSliverMultiBoxAdaptorElement.disposableElement.<anonymous closure>
#34     BuildOwner.lockState
#35     AnimatedSliverMultiBoxAdaptorElement.disposableElement
#36     AnimatedRenderSliverList.measureItem
#37     AnimatedRenderSliverList.measureItems.<anonymous closure>
#42     _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:192:26)
(elided 6 frames from class _AssertionError, class _Timer, dart:async, and dart:async-patch)
The following RenderObject was being processed when the exception was fired: RenderBoxy<BoxyChild>#ae96a relayoutBoundary=up8 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
RenderObject: RenderBoxy<BoxyChild>#ae96a relayoutBoundary=up8 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
    parentData: <none> (can use size)
    constraints: BoxConstraints(w=377.0, 0.0<=h<=Infinity)
    size: Size(377.0, 40.0)
    child 1: RenderPadding#43672 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
        parentData: offset=Offset(0.0, 0.0) (can use size)
        constraints: BoxConstraints(w=40.0, h=40.0)
        size: Size(40.0, 40.0)
        padding: EdgeInsets.all(8.0)
        textDirection: ltr
        child: RenderSemanticsAnnotations#f1bca NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
            parentData: offset=Offset(8.0, 8.0) (can use size)
            constraints: BoxConstraints(w=24.0, h=24.0)
            size: Size(24.0, 24.0)
            child: RenderExcludeSemantics#21afb NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
                parentData: <none> (can use size)
                constraints: BoxConstraints(w=24.0, h=24.0)
                size: Size(24.0, 24.0)
                excluding: true
                child: RenderConstrainedBox#e852e NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
                    parentData: <none> (can use size)
                    constraints: BoxConstraints(w=24.0, h=24.0)
                    size: Size(24.0, 24.0)
                    additionalConstraints: BoxConstraints(w=24.0, h=24.0)
    child 2: RenderPositionedBox#c6b42 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
        parentData: offset=Offset(0.0, 0.0) (can use size)
        constraints: BoxConstraints(w=49.0, h=40.0)
        size: Size(49.0, 40.0)
        alignment: Alignment.center
        textDirection: ltr
        widthFactor: expand
        heightFactor: expand
        child: RenderParagraph#89c15 relayoutBoundary=up1 NEEDS-PAINT
            parentData: offset=Offset(0.0, 11.5) (can use size)
            constraints: BoxConstraints(0.0<=w<=49.0, 0.0<=h<=40.0)
            size: Size(49.0, 17.0)
            textAlign: start
            textDirection: ltr
            softWrap: wrapping at box width
            overflow: clip
            locale: en_US
            maxLines: unlimited
            text: TextSpan
                debugLabel: (englishLike bodyMedium 2014).merge(blackCupertino bodyMedium)
                inherit: false
                color: Color(0xdd000000)
                family: .SF UI Text
                size: 14.0
                weight: 400
                baseline: alphabetic
                decoration: TextDecoration.none
                "index 4"
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

The (simplified) item tiles are created as follows:

  Widget itemTile(int index) {
    return Card(
      margin: const EdgeInsets.all(8),
      child: CustomBoxy(delegate: TileBoxy(widgetSpacing: 10), children: [
        const Icon(Icons.note),
        Center(child: Text("index $index"))
      ]),
    );
  }
}

With the (simplified) delegate defined as:

class TileBoxy extends BoxyDelegate {
  final double widgetSpacing;

  TileBoxy({this.widgetSpacing = 10});

  @override
  Size layout() {
    List<double> childrenWidths = [];
    for (final child in children) {
      childrenWidths.add(min(constraints.maxWidth,
          child.render.getMaxIntrinsicWidth(double.infinity)));
    }
    var totalChildrenWidth = childrenWidths.reduce((a, b) => a + b);

    var childHeight = 0.0;
    for (var i = 0; i < children.length; i++) {
      childHeight = max(
        childHeight,
        children[i].render.getMinIntrinsicHeight(childrenWidths[i]),
      );
    }

    for (var i = 0; i < children.length; i++) {
      children[i]
          .layout(BoxConstraints.tight(Size(childrenWidths[i], childHeight)));
    }

    var x = 0.0;
    for (var i = 0; i < children.length; i++) {
      children[i].position(Offset(x, 0));
      x += childrenWidths[i] + widgetSpacing;
    }

    return Size(min(totalChildrenWidth, constraints.maxWidth), childHeight);
  }
}

Possibly this problem might be caused by the external library for the animated list (great_list_view). However, the error only occurs when I use CustomBoxy and does not occur when using a standard Row.

Is there something I need to add in the BoxyDelegate to get rid of this error?

Expanded dominant children?

Does Boxy support Dominant children that are also Expanded? I have a row where one child should expand to fill as much horizontal space as possible, and the other children should match its height.

Can boxy deal with adjusting listview position when an item changes height?

Im a boxy noob, but stumbled here in what looks promising

My problem

I have a listview of variable sized items. Inside these variable sized items are images loaded from a CachedNetworkImage. These images load at whatever rate the network allows, which then expands the height of the listview item.

This becomes a problem when the user is in the middle of a listview and an image somewhere above their position loads and it invariably pushes their scroll position down, now they aren't looking at the content they were looking at before

My solution so far

What I've done is basically use a MeasureSize widget

typedef void OnWidgetSizeChange(Size size);

class MeasureSizeRenderObject extends RenderProxyBox {
  Size? oldSize;
  final OnWidgetSizeChange onChange;

  MeasureSizeRenderObject(this.onChange);

  @override
  void performLayout() {
    super.performLayout();

    Size newSize = child!.size;
    if (oldSize == newSize) return;

    oldSize = newSize;
    WidgetsBinding.instance!.addPostFrameCallback((_) {
      onChange(newSize);
    });
  }
}

class MeasureSize extends SingleChildRenderObjectWidget {
  final OnWidgetSizeChange onChange;

  const MeasureSize({
    Key? key,
    required this.onChange,
    required Widget child,
  }) : super(key: key, child: child);

  @override
  RenderObject createRenderObject(BuildContext context) {
    return MeasureSizeRenderObject(onChange);
  }
}
MeasureSize(
                    onChange: (size){
                      _processItemSizeChange(index: index, size:size);
                    },
               child: (...) /// My list item

Which detects a change in the widget size in then moves the listview _scrollController by the height of the image. _postHeights is a map that stores the last known widget height for each listview item

  void _processItemSizeChange({index, size})
  {
   if (_postHeights[index] == null)
    {
      //first layout so lets put the height of this widget into the map
      _postHeights[index] = size.height;
    }
    else
    {
      //this item has changed its height, so lets deal with that
      debugPrint(index.toString()+' changed height from: '+_postHeights[index].toString() + '  to:'+size.height.toString());
        _scrollController.jumpTo(_scrollController.position.pixels+(size.height - _postHeights[index]!));

        _postHeights[index] = size.height;
      }
  }

The problem with this 'solution'

The problem with this solution as you might guess is there is frame flicker between when the image starts to display (changes the height of the listview item) and when this hacky solution detects the change and does a scrollController.jumpTo

Can boxy help?

So I started using boxy to try to solve this problem

return CustomBoxy(
              delegate: MyDelegate(scrollController: _scrollController),
              children: [
                BoxyId(
                  id:#body,
                  child: (...) ///My list item
class MyDelegate extends BoxyDelegate {
  MyDelegate({required this.scrollController});
  final scrollController;

@override Size layout(){

  final body = getChild(#body);
  body.layout(constraints);
  
  scrollController.jumpTo(10); //Lets try to jump to position 10 just as an initial test if this would even work

  return body.size;

}
}

But I get a million errors trying to manipulate scrollController like that.

Before I go any further, do you think boxy can help with my situation, of trying to get the listview to jump to a new position at the same exact time the image changes the size of the layout without having a screen flicker as this happens?

Im just not even sure this is the intended use of boxy

Thank you!!

Finding child Offeset

I would like to be able to find Global Offset of a child of Widget nested down below in Widget.

So let's say I have following Widget tree:

W0
|--W01
|--W02
|--W03
W1
|--W11
|--W12
|--W13

I would like to layout W0 and W1, find Offset of W02 and W12 and inflate with widget which is positioned between W02 and W12.

What's the best way to do it?

I believe Boxy took me 1 step closer to achieving that but iterating over children to find their Offset seem problematic, approach I've taken is with

RenderBox rb = element.findRenderObject() as RenderBox;
connectorOffset = rb.localToGlobal(Offset.zero);

...but I'm told I should not read Offset this way by framework.

[Question] Centered widget or Scrollable widget

Scenario:

I'm using Flutter Desktop and Web, so the window size is totally arbitrary.

I want to create a login screen that have a Column containing a logo, title, e-mail text input, password text input, forgot password link and a button.

What I need is:

  • If the widget doesn't fit on the screen, encapsulate it with a SingleChildScrollView.
  • If the widget fits the screen, encapsulate it with a Center, so it always appears in the middle of the screen.

How to achieve that?

SliverContainer fill available space

Hi once again...

I recently encountered the use of SliverContainer (very useful one!). Can we have option to provide BoxConstraints manually? Actually, I am wrapping a sliver inside it (which is scrollable) and it shrinks in a way that occupies only space taken by the sliver itself.

Is it possible that the SliverContainer fills the available space in parent (just like Expanded in Column) or option to provide manually?

I tried digging the source code. Unfortunately, I am new to such layout things and couldn't understand how these constraints work ๐Ÿ˜

Thanks.

How to remove a rendered widget?

In onLayout(), I have some code like this:

final source = getChild(#source);
final sourceSize = source.layout(constraints);
source.position(const Offset(-10000, 0));

I am using sourceSize to determine source's size and apply this size to another widget. This is working for me. But, I want to remove source completely instead of hiding it at (-10000, 0). How can I do this?

How could I extend BoxyChild?

I'm trying to expose an extra property on BoxyChild so the parent delegate can use it in its layout. I tried to understand the overall structure of the Boxy classes but couldn't wrap my head around it. So my question is:

Is it possible to extend BoxyChild and instance it as a child of a CustomBoxy? How could I accomplish that?

My final goal is to build a Widget kinda like OverflowPadding, except that it exposes the child's fullRect (including the overflow) as well. If that should only be possible with a custom RenderObject, please let me know.

[Feature request] `BaseBoxyDelegate.getChildOrNull`

For convenience sake, I'd like to suggest adding a simple non-throwable method getChildOrNull to BaseBoxyDelegate. With that it wouldn't be necessary to always write code like this:

BoxyChild? child = null;
if (hasChild(#child)) {
  child = getChild(#child);
}

Implementation is simple and would go as follows:

/// Gets the child handle with the specified [id] or returns null if there
/// is no child with given [id].
T? getChildOrNull<T extends ChildHandleType>(Object id) {
  if (hasChild(id)) {
    return getChild(id);
  }
  return null;
}

`RedirectPointer` is not importable

Heya.
I saw the new release with 2 widgets added but noticed I can't import the RedirectPointer and digging a bit showed that it was exported differently compared to other widgets.
RedirectPointer -> export 'package:boxy/redirect_pointer.dart';
Scale and others -> export 'src/scale.dart';

I guess just fixing the export should do the trick.

P.S any reason why the package version was not bumped to 2.2.0 as these are the new features and not just bug fixes?
it's not really that important it's just that I like to manually update packages and seeing minor updates more likely to make me go to changelog :)

Get widget's global position inside custom layout delegate

Hello, Andre,

I need to get a "future" global position for one specific widget to properly lay out its child.
Is it possible in Boxy? (I know, that the widget knows nothing about its position as it is his parent's responsibility, but still).

I know about the (context.findRenderObject() as RenderBox?)?.localToGlobal(Offset.zero) ?? Offset.zero approach, but the first zero offset is a bummer.

You have a very good knowledge of the things under the Flutter's hood, so, maybe, you can point me in the proper direction.

Thanks!

BoxyChild receives null parentData on first layout

The first time BoxyDelegate.layout() is processed, trying to access a child's parentData evaluates to null.

After a hot reload or changing the screen state to rebuild it, layout is called again but parentData is now accessible.

Code example:

import 'package:boxy/boxy.dart';
import 'package:flutter/widgets.dart';

class TestBug extends StatelessWidget {
  const TestBug({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: CustomBoxy(
        delegate: MyBoxy(),
        children: [
          BoxyId<String>(
            id: 'child-0',
            data: "I'm a child",
            child: SizedBox(width: 50, height: 50),
          ),
        ],
      ),
    );
  }
}

class MyBoxy extends BoxyDelegate {
  @override
  Size layout() {
    final child = getChild('child-0');
    print(child.parentData);
    print(child.parentData as String?);
    child.layout(constraints);
    child.position(Offset.zero);
    return constraints.biggest;
  }
}

Putting this widget in a Scaffold's body prints null twice, which is unexpected. Hitting Ctrl+S to save the file triggers a hot reload and prints "I'm a child" twice, as expected.

Strange behavior occurs when a Wrap widget is used in a Custom boxy.

The last child in the Wrap always appears on a new line, regardless of whether there is still enough space. It seems as if the intrinsic width is determined incorrectly. However, if I set the spacing in the Wrap to 0, everything is displayed correctly.

Without a custom boxy the alignment also works properly. What might go wrong here?

simulator_screenshot_CD47EB47-2497-429C-89E7-5B564F680E68

Minimal reproducible code:

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Issue with Wrap and Custom Boxy"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text("A custom boxy is used"),
            CustomBoxy(delegate: ExampleBoxy(), children: [
              createWrapWidget(),
            ]),
            const SizedBox(height: 20),
            const Text("No custom boxy is used "),
            createWrapWidget()
          ],
        ),
      ),
    );
  }

  Widget createWrapWidget() => Wrap(
        direction: Axis.horizontal,
        runSpacing: 5,
        spacing: 10,
        children: List.generate(
          5,
          (index) => SizedBox(
            width: 30,
            height: 40,
            child: Container(color: Colors.green),
          ),
        ),
      );
}

class ExampleBoxy extends BoxyDelegate {
  ExampleBoxy();

  @override
  Size layout() {
    List<double> childrenWidths = [];
    for (final child in children) {
      childrenWidths.add(min(constraints.maxWidth,
          child.render.getMaxIntrinsicWidth(double.infinity)));
    }
    var totalChildrenWidth = childrenWidths.reduce((a, b) => a + b);

    var childHeight = 0.0;
    for (var i = 0; i < children.length; i++) {
      childHeight = max(
        childHeight,
        children[i].render.getMinIntrinsicHeight(childrenWidths[i]),
      );
    }

    for (var i = 0; i < children.length; i++) {
      children[i]
          .layout(BoxConstraints.tight(Size(childrenWidths[i], childHeight)));
    }

    var x = 0.0;
    for (var i = 0; i < children.length; i++) {
      children[i].position(Offset(x, 0));
      x += childrenWidths[i];
    }

    return Size(min(totalChildrenWidth, constraints.maxWidth), childHeight);
  }
}

Custom layout protocols

It would be cool if we could use a custom constraints and geometry in children, this would allow you to pass data calculated at layout time such as the child's relative offset.

Need help in CustomBoxy with CustomScrollView

Hi @PixelToast ๐Ÿ‘‹

Thanks for this great package.
I am stuck at a place and need some help. Actually, I was experimenting with CustomBoxy.

The thing is, the child of my CustomBoxy is a CustomScrollView itself (To be clear, I am trying to show this: https://pub.dev/packages/implicitly_animated_reorderable_list).

First, let me show code:

class MyDelegate extends BoxyDelegate {
  @override
  layout() {
    final list = getChild(#list);

    final listSize = list.layout(constraints.copyWith(
      maxHeight: 250,
    ));

    list.position(Offset.zero);

    return Size(listSize.width, listSize.height);
  }
}

///
/// Somewhere...
///
return CustomBoxy(
  delegate: MyDelegate(),
  children: [
    LayoutId(
      id: #list,
      child: ImplicitlyAnimatedReorderableList<String>(
        // ... ... ...
      ),
    ),
  ],
);

The error I get:

โ•โ•โ•ก EXCEPTION CAUGHT BY RENDERING LIBRARY โ•žโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
The following assertion was thrown during performLayout():
'package:flutter/src/widgets/framework.dart': Failed assertion: line 2598 pos 12: '!_debugBuilding':
is not true.
Either the assertion indicates an error in the framework itself, or we should provide substantially
more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
  https://github.com/flutter/flutter/issues/new?template=BUG.md
The relevant error-causing widget was:
  ImplicitlyAnimatedReorderableList<String>

What I wanted to do?

I wanted to achieve a similar effect of ProductTile example that you have provided where this list would be shown at top with a FAB at bottom.

I am pretty new to this. If this can't be done using CustomBoxy, what I should I try to do??

Thanks...

Is there a way to get the widget contained by a BoxyChild?

I'm trying to write a list-like custom layout where all the list items are ordered in the screen according to their properties. I have created a list of items List<BoxyChild> using the inflate method of BoxyDelegate and now I would like to sort this list and then position the items on the screen accordingly. But the class InflatedChildHandle (which is inherited by BoxyChild) has _widget as a private field. Is there any other way to get the widget contained by the BoxyChild?

Something wrong when using custom boxy and layer link

Recursion or something wrong happens when I use CustomBoxy and PortalTarget from flutter_portal packages.

The root cause may be in the composition phase, PortalTarget using LayerLink behind the scene.

This only occurs when JIT mode, AOT works fine.

E/Dart    ( 5717): ../../third_party/dart/runtime/vm/compiler/frontend/kernel_translation_helper.cc: 2163: error: Unexpected tag 32 (ConstConstructorInvocation) in ?, expected expression
E/DartVM  ( 5717): version=3.0.0-366.0.dev (dev) (Fri Mar 24 06:44:03 2023 -0700) on "android_arm64"
E/DartVM  ( 5717): pid=5717, thread=5764, isolate_group=main(0xb40000757cf0f8b0), isolate=(nil)(0x0)
E/DartVM  ( 5717): os=android, arch=arm64, comp=yes, sim=no
E/DartVM  ( 5717): isolate_instructions=73dd8d3ca0, vm_instructions=73dd8d3ca0
E/DartVM  ( 5717): fp=73e51a1830, sp=73e51a0708, pc=73dd9ec760
E/DartVM  ( 5717):   pc 0x00000073dd9ec760 fp 0x00000073e51a1830 /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so+0x1bc1760
E/DartVM  ( 5717): -- End of DumpStackTrace
E/DartVM  ( 5717):   pc 0x0000000000000000 fp 0x00000073e51a3d98 sp 0x0000000000000000 [Stub] CallToRuntime
E/DartVM  ( 5717):   pc 0x00000073db183000 fp 0x00000073e51a3dc8 sp 0x00000073e51a3da8 [Stub] LazyCompile
E/DartVM  ( 5717):   pc 0x0000007443151954 fp 0x00000073e51a3e08 sp 0x00000073e51a3dd8 [Unoptimized] _LayoutBuilderElement@1105188862._layout@1105188862
E/DartVM  ( 5717):   pc 0x00000073c573fa08 fp 0x00000073e51a3e58 sp 0x00000073e51a3e18 [Unoptimized] RenderObject.invokeLayoutCallback.<anonymous closure>
E/DartVM  ( 5717):   pc 0x00000073c573f010 fp 0x00000073e51a3eb0 sp 0x00000073e51a3e68 [Unoptimized] PipelineOwner._enableMutationsToDirtySubtrees@376266271
E/DartVM  ( 5717):   pc 0x00000073c573e910 fp 0x00000073e51a3f18 sp 0x00000073e51a3ec0 [Unoptimized] RenderObject.invokeLayoutCallback
E/DartVM  ( 5717):   pc 0x000000744315141c fp 0x00000073e51a3f68 sp 0x00000073e51a3f28 [Unoptimized] __RenderLayoutBuilder&RenderBox&RenderObjectWithChildMixin&[email protected]
E/DartVM  ( 5717):   pc 0x0000007443150eb0 fp 0x00000073e51a3fa8 sp 0x00000073e51a3f78 [Unoptimized] [email protected]
E/DartVM  ( 5717):   pc 0x00000073c57dddf8 fp 0x00000073e51a4050 sp 0x00000073e51a3fb8 [Unoptimized] RenderObject.layout
E/DartVM  ( 5717):   pc 0x00000073c57dbcf0 fp 0x00000073e51a40c8 sp 0x00000073e51a4060 [Unoptimized] RenderBox.layout
E/DartVM  ( 5717):   pc 0x0000007443150304 fp 0x00000073e51a4130 sp 0x00000073e51a40d8 [Unoptimized] RenderStack.layoutPositionedChild
E/DartVM  ( 5717):   pc 0x00000073c5726564 fp 0x00000073e51a41b0 sp 0x00000073e51a4140 [Unoptimized] RenderStack.performLayout
E/DartVM  ( 5717):   pc 0x00000073c57dddf8 fp 0x00000073e51a4258 sp 0x00000073e51a41c0 [Unoptimized] RenderObject.layout
E/DartVM  ( 5717):   pc 0x00000073c57dbcf0 fp 0x00000073e51a42d0 sp 0x00000073e51a4268 [Unoptimized] RenderBox.layout
E/DartVM  ( 5717):   pc 0x000000744314de98 fp 0x00000073e51a4318 sp 0x00000073e51a42e0 [Unoptimized] BoxyChild.layout
E/DartVM  ( 5717):   pc 0x000000744314bae0 fp 0x00000073e51a43a8 sp 0x00000073e51a4328 [Unoptimized] _NodeMapViewDelegate@96153274._layout@96153274
E/DartVM  ( 5717):   pc 0x000000744314b674 fp 0x00000073e51a4438 sp 0x00000073e51a43b8 [Unoptimized] [email protected]
E/DartVM  ( 5717):   pc 0x000000744314b358 fp 0x00000073e51a4488 sp 0x00000073e51a4448 [Unoptimized] RenderBoxy.performInflatingLayout.<anonymous closure>
E/DartVM  ( 5717):   pc 0x000000744314a918 fp 0x00000073e51a4500 sp 0x00000073e51a4498 [Unoptimized] _RenderBoxy&RenderBox&ContainerRenderObjectMixin&InflatingRenderObjectMixin&[email protected]
E/DartVM  ( 5717):   pc 0x000000744314a6ac fp 0x00000073e51a4550 sp 0x00000073e51a4510 [Unoptimized] RenderBoxy.performInflatingLayout
E/DartVM  ( 5717):   pc 0x000000744314a240 fp 0x00000073e51a45a0 sp 0x00000073e51a4560 [Unoptimized] _RenderBoxy&RenderBox&ContainerRenderObjectMixin&[email protected].<anonymous closure>
E/DartVM  ( 5717):   pc 0x0000007443149f90 fp 0x00000073e51a4600 sp 0x00000073e51a45b0 [Unoptimized] InflatingElement._wrapInflater@1271121873
E/DartVM  ( 5717):   pc 0x0000007443143a28 fp 0x00000073e51a4640 sp 0x00000073e51a4610 [Unoptimized] _RenderBoxy&RenderBox&ContainerRenderObjectMixin&[email protected]
E/DartVM  ( 5717):   pc 0x00000074431436b4 fp 0x00000073e51a4678 sp 0x00000073e51a4650 [Unoptimized] _RenderBoxy&RenderBox&ContainerRenderObjectMixin&InflatingRenderObjectMixin&[email protected]
E/DartVM  ( 5717):   pc 0x00000073c57dddf8 fp 0x00000073e51a4720 sp 0x00000073e51a4688 [Unoptimized] RenderObject.layout
E/DartVM  ( 5717):   pc 0x00000073c57dbcf0 fp 0x00000073e51a4798 sp 0x00000073e51a4730 [Unoptimized] RenderBox.layout
E/DartVM  ( 5717):   pc 0x00000073c57e9ad8 fp 0x00000073e51a47e8 sp 0x00000073e51a47a8 [Unoptimized] RenderConstrainedBox.performLayout
E/DartVM  ( 5717):   pc 0x00000073c57dddf8 fp 0x00000073e51a4890 sp 0x00000073e51a47f8 [Unoptimized] RenderObject.layout
E/DartVM  ( 5717):   pc 0x00000073c57dbcf0 fp 0x00000073e51a4908 sp 0x00000073e51a48a0 [Unoptimized] RenderBox.layout
E/DartVM  ( 5717):   pc 0x00000073c57fcd10 fp 0x00000073e51a4968 sp 0x00000073e51a4918 [Unoptimized] RenderPadding.performLayout
E/DartVM  ( 5717):   pc 0x00000073c57dddf8 fp 0x00000073e51a4a10 sp 0x00000073e51a4978 [Unoptimized] RenderObject.layout
E/DartVM  ( 5717):   pc 0x00000073c57dbcf0 fp 0x00000073e51a4a88 sp 0x00000073e51a4a20 [Unoptimized] RenderBox.layout
E/DartVM  ( 5717):   pc 0x00000073c57f22b8 fp 0x00000073e51a4ad0 sp 0x00000073e51a4a98 [Unoptimized] MultiChildLayoutDelegate.layoutChild
E/DartVM  ( 5717):   pc 0x00000073c57efd44 fp 0x00000073e51a4ba0 sp 0x00000073e51a4ae0 [Unoptimized] [email protected]
E/DartVM  ( 5717):   pc 0x00000073c57edd60 fp 0x00000073e51a4c08 sp 0x00000073e51a4bb0 [Unoptimized] MultiChildLayoutDelegate._callPerformLayout@947472081
E/DartVM  ( 5717):   pc 0x00000073c57eced0 fp 0x00000073e51a4c50 sp 0x00000073e51a4c18 [Unoptimized] RenderCustomMultiChildLayoutBox.performLayout
E/DartVM  ( 5717):   pc 0x00000073c57dddf8 fp 0x00000073e51a4cf8 sp 0x00000073e51a4c60 [Unoptimized] RenderObject.layout
E/DartVM  ( 5717):   pc 0x00000073c57dbcf0 fp 0x00000073e51a4d70 sp 0x00000073e51a4d08 [Unoptimized] RenderBox.layout
E/DartVM  ( 5717):   pc 0x00000073c57df074 fp 0x00000073e51a4db8 sp 0x00000073e51a4d80 [Unoptimized] _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&[email protected]
E/DartVM  ( 5717):   pc 0x00000073c57dddf8 fp 0x00000073e51a4e60 sp 0x00000073e51a4dc8 [Unoptimized] RenderObject.layout
E/DartVM  ( 5717):   pc 0x00000073c57dbcf0 fp 0x00000073e51a4ed8 sp 0x00000073e51a4e70 [Unoptimized] RenderBox.layout
E/DartVM  ( 5717):   pc 0x00000073c57df074 fp 0x00000073e51a4f20 sp 0x00000073e51a4ee8 [Unoptimized] _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&[email protected]
E/DartVM  ( 5717):   pc 0x00000073c57ecc3c fp 0x00000073e51a4f68 sp 0x00000073e51a4f30 [Unoptimized] [email protected]
E/DartVM  ( 5717):   pc 0x00000073c57dddf8 fp 0x00000073e51a5010 sp 0x00000073e51a4f78 [Unoptimized] RenderObject.layout
E/DartVM  ( 5717):   pc 0x00000073c57dbcf0 fp 0x00000073e51a5088 sp 0x00000073e51a5020 [Unoptimized] RenderBox.layout
E/DartVM  ( 5717):   pc 0x00000073c57df074 fp 0x00000073e51a50d0 sp 0x00000073e51a5098 [Unoptimized] _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&[email protected]
E/DartVM  ( 5717):   pc 0x00000073c57dddf8 fp 0x00000073e51a5178 sp 0x00000073e51a50e0 [Unoptimized] RenderObject.layout
E/DartVM  ( 5717):   pc 0x00000073c57dbcf0 fp 0x00000073e51a51f0 sp 0x00000073e51a5188 [Unoptimized] RenderBox.layout
E/DartVM  ( 5717):   pc 0x00000073c57df074 fp 0x00000073e51a5238 sp 0x00000073e51a5200 [Unoptimized] _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&[email protected]
E/DartVM  ( 5717):   pc 0x00000073c57dddf8 fp 0x00000073e51a52e0 sp 0x00000073e51a5248 [Unoptimized] RenderObject.layout
E/DartVM  ( 5717):   pc 0x00000073c57dbcf0 fp 0x00000073e51a5358 sp 0x00000073e51a52f0 [Unoptimized] RenderBox.layout
E/DartVM  ( 5717):   pc 0x00000073c57df074 fp 0x00000073e51a53a0 sp 0x00000073e51a5368 [Unoptimized] _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&[email protected]
E/DartVM  ( 5717):   pc 0x00000073c57dddf8 fp 0x00000073e51a5448 sp 0x00000073e51a53b0 [Unoptimized] RenderObject.layout
E/DartVM  ( 5717):   pc 0x00000073c57dbcf0 fp 0x00000073e51a54c0 sp 0x00000073e51a5458 [Unoptimized] RenderBox.layout
E/DartVM  ( 5717):   pc 0x00000073c57df074 fp 0x00000073e51a5508 sp 0x00000073e51a54d0 [Unoptimized] _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&[email protected]
E/DartVM  ( 5717):   pc 0x00000073c57dddf8 fp 0x00000073e51a55b0 sp 0x00000073e51a5518 [Unoptimized] RenderObject.layout
E/DartVM  ( 5717):   pc 0x00000073c57dbcf0 fp 0x00000073e51a5628 sp 0x00000073e51a55c0 [Unoptimized] RenderBox.layout
E/DartVM  ( 5717):   pc 0x00000073c57df074 fp 0x00000073e51a5670 sp 0x00000073e51a5638 [Unoptimized] _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&[email protected]
E/DartVM  ( 5717):   pc 0x00000073c57dddf8 fp 0x00000073e51a5718 sp 0x00000073e51a5680 [Unoptimized] RenderObject.layout
E/DartVM  ( 5717):   pc 0x00000073c57dbcf0 fp 0x00000073e51a5790 sp 0x00000073e51a5728 [Unoptimized] RenderBox.layout
E/DartVM  ( 5717):   pc 0x00000073c57df074 fp 0x00000073e51a57d8 sp 0x00000073e51a57a0 [Unoptimized] _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&[email protected]
E/DartVM  ( 5717):   pc 0x00000073c57dddf8 fp 0x00000073e51a5880 sp 0x00000073e51a57e8 [Unoptimized] RenderObject.layout
E/DartVM  ( 5717):   pc 0x00000073c57dbcf0 fp 0x00000073e51a58f8 sp 0x00000073e51a5890 [Unoptimized] RenderBox.layout
E/DartVM  ( 5717):   pc 0x00000073c57df074 fp 0x00000073e51a5940 sp 0x00000073e51a5908 [Unoptimized] _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&[email protected]
E/DartVM  ( 5717):   pc 0x00000073c57dddf8 fp 0x00000073e51a59e8 sp 0x00000073e51a5950 [Unoptimized] RenderObject.layout
E/DartVM  ( 5717):   pc 0x00000073c57dbcf0 fp 0x00000073e51a5a60 sp 0x00000073e51a59f8 [Unoptimized] RenderBox.layout
E/DartVM  ( 5717):   pc 0x00000073c57df074 fp 0x00000073e51a5aa8 sp 0x00000073e51a5a70 [Unoptimized] _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&[email protected]
E/DartVM  ( 5717):   pc 0x00000073c57dddf8 fp 0x00000073e51a5b50 sp 0x00000073e51a5ab8 [Unoptimized] RenderObject.layout
E/DartVM  ( 5717):   pc 0x00000073c57dbcf0 fp 0x00000073e51a5bc8 sp 0x00000073e51a5b60 [Unoptimized] RenderBox.layout
E/DartVM  ( 5717):   pc 0x00000073c57df074 fp 0x00000073e51a5c10 sp 0x00000073e51a5bd8 [Unoptimized] _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&[email protected]
E/DartVM  ( 5717):   pc 0x00000073c57dddf8 fp 0x00000073e51a5cb8 sp 0x00000073e51a5c20 [Unoptimized] RenderObject.layout
E/DartVM  ( 5717):   pc 0x00000073c57dbcf0 fp 0x00000073e51a5d30 sp 0x00000073e51a5cc8 [Unoptimized] RenderBox.layout
E/DartVM  ( 5717):   pc 0x00000073c57eca14 fp 0x00000073e51a5d80 sp 0x00000073e51a5d40 [Unoptimized] RenderOffstage.performLayout
E/DartVM  ( 5717):   pc 0x00000073c57dddf8 fp 0x00000073e51a5e28 sp 0x00000073e51a5d90 [Unoptimized] RenderObject.layout
E/DartVM  ( 5717):   pc 0x00000073c57dbcf0 fp 0x00000073e51a5ea0 sp 0x00000073e51a5e38 [Unoptimized] RenderBox.layout
E/DartVM  ( 5717):   pc 0x00000073c57df074 fp 0x00000073e51a5ee8 sp 0x00000073e51a5eb0 [Unoptimized] _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&[email protected]
E/DartVM  ( 5717):   pc 0x00000073c57dddf8 fp 0x00000073e51a5f90 sp 0x00000073e51a5ef8 [Unoptimized] RenderObject.layout
E/DartVM  ( 5717):   pc 0x00000073c57dbcf0 fp 0x00000073e51a6008 sp 0x00000073e51a5fa0 [Unoptimized] RenderBox.layout
E/DartVM  ( 5717):   pc 0x00000073c57e7194 fp 0x00000073e51a6080 sp 0x00000073e51a6018 [Unoptimized] __RenderTheater&RenderBox&ContainerRenderObjectMixin&[email protected]
E/DartVM  ( 5717):   pc 0x00000073c57d9ec4 fp 0x00000073e51a60e0 sp 0x00000073e51a6090 [Unoptimized] RenderObject._layoutWithoutResize@376266271
E/DartVM  ( 5717):   pc 0x00000073c57d8708 fp 0x00000073e51a6150 sp 0x00000073e51a60f0 [Unoptimized] PipelineOwner.flushLayout
E/DartVM  ( 5717):   pc 0x00000073c57d7a14 fp 0x00000073e51a6188 sp 0x00000073e51a6160 [Unoptimized] _WidgetsFlutterBinding&BindingBase&GestureBinding&SchedulerBinding&ServicesBinding&PaintingBinding&SemanticsBinding&[email protected]
E/DartVM  ( 5717):   pc 0x00000073c57cd66c fp 0x00000073e51a61e0 sp 0x00000073e51a6198 [Unoptimized] _WidgetsFlutterBinding&BindingBase&GestureBinding&SchedulerBinding&ServicesBinding&PaintingBinding&SemanticsBinding&RendererBinding&[email protected]
E/DartVM  ( 5717):   pc 0x00000073c57ccf6c fp 0x00000073e51a6218 sp 0x00000073e51a61f0 [Unoptimized] _WidgetsFlutterBinding&BindingBase&GestureBinding&SchedulerBinding&ServicesBinding&PaintingBinding&SemanticsBinding&RendererBinding@524399801._handlePersistentFrameCallback@946452173
E/DartVM  ( 5717):   pc 0x00000073c57cce64 fp 0x00000073e51a6258 sp 0x00000073e51a6228 [Unoptimized] _WidgetsFlutterBinding&BindingBase&GestureBinding&SchedulerBinding&ServicesBinding&PaintingBinding&SemanticsBinding&RendererBinding@524399801._handlePersistentFrameCallback@946452173
E/DartVM  ( 5717):   pc 0x00000073c57cc884 fp 0x00000073e51a6300 sp 0x00000073e51a6268 [Unoptimized] _WidgetsFlutterBinding&BindingBase&GestureBinding&SchedulerBinding@524399801._invokeFrameCallback@979222615
E/DartVM  ( 5717):   pc 0x00000073c57cb3c8 fp 0x00000073e51a6380 sp 0x00000073e51a6310 [Unoptimized] _WidgetsFlutterBinding&BindingBase&GestureBinding&[email protected]
E/DartVM  ( 5717):   pc 0x00000073c5499e70 fp 0x00000073e51a63b8 sp 0x00000073e51a6390 [Unoptimized] _WidgetsFlutterBinding&BindingBase&GestureBinding&SchedulerBinding@524399801._handleDrawFrame@979222615
E/DartVM  ( 5717):   pc 0x00000073c5499bcc fp 0x00000073e51a63f0 sp 0x00000073e51a63c8 [Unoptimized] _WidgetsFlutterBinding&BindingBase&GestureBinding&SchedulerBinding@524399801._handleDrawFrame@979222615
E/DartVM  ( 5717):   pc 0x00000073ce298ff8 fp 0x00000073e51a6428 sp 0x00000073e51a6400 [Unoptimized] _invoke@15065589
E/DartVM  ( 5717):   pc 0x00000073ce2b48e4 fp 0x00000073e51a6468 sp 0x00000073e51a6438 [Unoptimized] PlatformDispatcher._drawFrame@15065589
E/DartVM  ( 5717):   pc 0x00000073ce2b4790 fp 0x00000073e51a6498 sp 0x00000073e51a6478 [Unoptimized] _drawFrame@15065589
E/DartVM  ( 5717):   pc 0x00000073ce2b46c0 fp 0x00000073e51a64c0 sp 0x00000073e51a64a8 [Unoptimized] _drawFrame@15065589
E/DartVM  ( 5717):   pc 0x00000073db183514 fp 0x00000073e51a6590 sp 0x00000073e51a64d0 [Stub] InvokeDartCode
E/DartVM  ( 5717): === Crash occurred when compiling package:flutter/src/widgets/layout_builder.dart__LayoutBuilderElement@1105188862__layout@1105188862 in unoptimized JIT mode in unknown pass
E/DartVM  ( 5717): === Flow Graph not available
F/libc    ( 5717): Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 5764 (1.ui), pid 5717 (.example.tidmid)
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'google/sdk_gphone64_arm64/emu64a:13/TPB4.220624.004/8808248:userdebug/dev-keys'
Revision: '0'
ABI: 'arm64'
Timestamp: 2023-04-04 11:56:28.179076529+0700
Process uptime: 7s
Cmdline: com.example.tidmid
pid: 5717, tid: 5764, name: 1.ui  >>> com.example.tidmid <<<
uid: 10167
tagged_addr_ctrl: 0000000000000001 (PR_TAGGED_ADDR_ENABLE)
pac_enabled_keys: 000000000000000f (PR_PAC_APIAKEY, PR_PAC_APIBKEY, PR_PAC_APDAKEY, PR_PAC_APDBKEY)
signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
Abort message: '../../third_party/dart/runtime/vm/compiler/frontend/kernel_translation_helper.cc: 2163: error: Unexpected tag 32 (ConstConstructorInvocation) in ?, expected expression'
    x0  0000000000000000  x1  0000000000001684  x2  0000000000000006  x3  00000073e51a17b0
    x4  0000000000000010  x5  0000000000000010  x6  0000000000000010  x7  7f7f7f7f7f7f7f7f
    x8  00000000000000f0  x9  00000076f8d0ba00  x10 0000000000000001  x11 00000076f8d49ce4
    x12 00000073e519ffc0  x13 000000000000001e  x14 00000073e51a0070  x15 00000a1b315e6e98
    x16 00000076f8daed60  x17 00000076f8d8bb70  x18 00000073e471c000  x19 0000000000001655
    x20 0000000000001684  x21 00000000ffffffff  x22 0000000000000005  x23 00000000ffffffff
    x24 000000000000145f  x25 0000000000000fb1  x26 000000000084144c  x27 00000073ddddc690
    x28 00000073dd23293c  x29 00000073e51a1830
    lr  00000076f8d3b868  sp  00000073e51a1790  pc  00000076f8d3b894  pst 0000000000001000
backtrace:
      #00 pc 0000000000051894  /apex/com.android.runtime/lib64/bionic/libc.so (abort+164) (BuildId: 058e3ec96fa600fb840a6a6956c6b64e)
      #01 pc 0000000001aa8ef4  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #02 pc 0000000001d5bcf8  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #03 pc 0000000001d5727c  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #04 pc 0000000001d56868  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #05 pc 0000000001d647ac  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #06 pc 0000000001d64450  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #07 pc 0000000001d63df0  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #08 pc 0000000001d639f0  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #09 pc 0000000001d63510  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #10 pc 0000000001d6269c  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #11 pc 0000000001bbf494  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #12 pc 0000000001d32b48  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #13 pc 0000000001d32980  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #14 pc 0000000001d42c04  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #15 pc 0000000001c3834c  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #16 pc 0000000001c394a8  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #17 pc 0000000001c39e64  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #18 pc 0000000001c39aa0  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #19 pc 0000000001b69c6c  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #20 pc 0000000001c387b0  /data/app/~~Mr3MfKpSQSHTMvqcut70GA==/com.example.tidmid-J8JvxuCdTraGWKulfTKONQ==/lib/arm64/libflutter.so (BuildId: a20578bbc00d8a803ad56da4623feb4a0342e6b3)
      #21 pc 0000000000002f78  [anon:dart-code]
Lost connection to device.

Exited.

Use children's instrics when calculating intrinsics in CustomBoxy

I'm probably not using this correctly, but I couldn't find a good example.

I want my CustomBoxy's intrinsic dimensions to be calculated based on the intrinsic dimensions of its children. In the simplest case, let's say something like:

class MyDelegate extends BoxyDelegate {
  // ...

  @override
  double minIntrinsicHeight(double width) =>
      children.map((e) => e.render.getMinIntrinsicHeight(width)).fold(0, max);
}

What I noticed is that when I do this, the intrinsic size changes as soon as I interact with the app. By adding some logging, it seems that children returns an empty array on the first pass (and getChild(#id) throws The MyDelegate boxy delegate attempted to get a nonexistent child.). But after any interaction, subsequent calls correctly return the list of children. Because of this, I cannot make the intrinsic size depend on children since on first calculation they are not available.

So my questions are:

  • Is this supported at all? (e.g. is there a different way I should get children (or their intrinsic sizes) for this calculation?)
  • If not, is that just something that's currently missing, or is it fundamentally difficult because of architectural reasons?

Make `BoxyFlex` Implement `Flex`

Packages like gap and flutter_gutter use Flex.direction/RenderFlex.direction to determine if they are in a vertically or horizontally aligned layout.

BoxyFlex and BoxyRenderFlex should implement their Flutter counterparts so that these packages' widgets will work properly with BoxyRow and BoxyColumn out of the box(y).

Here's a related Flutter/flutter issue that if accepted would change how this should be implemented:
flutter/flutter#133394

OverflowPadding hitTest

The part of the child that is inside the negative insets does not receive hit tests. Can this be solved?

If not, then a warning in the documentation would be really useful to inform users about this limitation

Overriden shouldRelayout doesn't have access to BoxyDelegate

I'm not sure if I'm being stupid, or if this is a bug or if the error message is wrong and this is not allowed (though it seems like it should?).

Consider this implementation of BoxyDelegate. The important part is the shouldRelayout function.

class TestBoxy extends BoxyDelegate {
  @override
  Size layout() {
    // do layout
  }

  @override
  bool shouldRelayout(covariant TestBoxy oldDelegate) {
    return children.length != oldDelegate.children.length;
  }
}

This will throw the following error on rebuild when the shouldRelayout function is trying to access either its own children or those of oldDelegate.

The EvenlySizedBoxy boxy delegate attempted to get the context outside of its normal lifecycle.
You should only access the BoxyDelegate from its overridden methods.

Am I doing something wrong, is the error message wrong or is this a bug? I am accessing the properties of either delegate in an overridden method.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.