Flutter package: Assorted layout widgets that boldly go where no native Flutter widgets have gone before.

Overview

pub package

assorted_layout_widgets

I will slowly but surely add interesting widgets, classes and methods to this package.

Despite the package name, they are not only related to layout. Here they are:

  • ColumnSuper
  • RowSuper
  • FitHorizontally
  • Box
  • WrapSuper
  • ButtonBarSuper
  • TextOneLine
  • Delayed
  • Pad
  • NormalizedOverflowBox
  • showDialogSuper and showCupertinoDialogSuper
  • TimeBuilder
  • GlobalValueKey and GlobalStringKey

Note: The widgets you don't use will be removed by Flutter's tree shaking. So feel free to add the library even if you want to use only one of them.


ColumnSuper

Given a list of children widgets, this will arrange them in a column. It can overlap cells, add separators and more.

ColumnSuper({
  List<Widget> children,
  double outerDistance,
  double innerDistance,
  bool invert,
  Alignment alignment,
  Widget separator,
  bool separatorOnTop,  
  bool removeChildrenWithNoHeight,
});

  • children is the list of widgets that represent the column cells, just like in a regular Column widget. However, the list may contain nulls, which will be ignored.

  • outerDistance is the distance in pixels before the first and after the last widget. It can be negative, in which case the cells will overflow the column (without any overflow warnings).

  • innerDistance is the distance in pixels between the cells. It can be negative, in which case the cells will overlap.

  • invert if true will paint the cells that come later on top of the ones that came before. This is specially useful when cells overlap (negative innerDistance).

  • alignment will align the cells horizontally if they are smaller than the available horizontal space.

  • separator is a widget which will be painted between each cells. Its height doesn't matter, since the distance between cells is given by innerDistance (in other words, separators don't occupy space). The separator may overflow if its width is larger than the column's width.

  • separatorOnTop if true (the default) will paint the separator on top of the cells. If false will paint the separator below the cells.

  • removeChildrenWithNoHeight if true, children with zero height will not result in an extra innerDistance and separator. If all children have zero height, the outerDistance will also be removed. In other words, it's as if children with zero height are removed, except for the fact they still occupy width. The default is false. See this interactive example.

Note: This is not a substitute for Flutter's native Column, it doesn't try to have a similar API, and it doesn't do all that Column does. In special, Expanded and Flexible widgets don't work inside of ColumnSuper, and it will overflow if the column is not big enough to fit its contents. ColumnSuper is meant only for certain use cases where Column won't work, like when you need overlapping cells or separators.

Try running the ColumnSuper example.

Also, try ColumnSuper Playground.


RowSuper

Given a list of children widgets, this will arrange them in a row. It can overlap cells, add separators and more.

RowSuper({
  List<Widget> children,
  double outerDistance,
  double innerDistance,
  bool invert,
  Alignment alignment,
  Widget separator,
  bool separatorOnTop,
  bool fitHorizontally,
  double shrinkLimit,
  MainAxisSize mainAxisSize,
});

On contrary to ColumnSuper and the native Row (which will overflow if the children are too large to fit the available free space), RowSuper may resize its children proportionately to their minimum intrinsic width.

Try running the RowSuper example.

Also, try RowSuper Playground.

Most parameters are the same as the ones of ColumnSuper, except:

  • fill if true will force the children to grow their widths proportionately to their minimum intrinsic width, so that they fill the whole row width. This parameter is only useful if the children are not wide enough to fill the whole row width. In case the children are larger than the row width, they will always shrink proportionately to their minimum intrinsic width, and the fill parameter will be ignored. See: RowSuper Fill example.

  • fitHorizontally if true will shrink the children, horizontally only, until the shrinkLimit is reached. This parameter is only useful if the children are not wide enough to fill the whole row width. Avoid using fitHorizontally together with fill: true.

  • shrinkLimit by default is 67%, which means the cell contents will shrink until 67% of their original width, and then overflow. Make shrinkLimit equal to 0.0 if you want the cell contents to shrink with no limits. Note, if fitHorizontally is false, the shrinkLimit is not used.

  • mainAxisSize by default is MainAxisSize.min, which means the row will occupy no more than its content's width. Make it MainAxisSize.max to expand the row to occupy the whole horizontal space.

You can also use a RowSpacer to add empty space (if available) between cells. For example:

RowSuper(
  children: [
    widget1,
    RowSpacer(),
    widget2,
    widget3,
    ],
);   

Try running the RowSuper with FitHorizontally example.

Note: This is not a substitute for Flutter's native Row, it doesn't try to have a similar API, and it doesn't do all that Row does. In special, Expanded and Flexible widgets don't work inside of RowSuper, since RowSuper will resize cells proportionately when content doesn't fit. RowSuper is meant only for certain use cases where Row won't work, like when you need overlapping cells, or when you need to scale the contents of the cells when they don't fit.


FitHorizontally

FitHorizontally({
  Widget child,
  double shrinkLimit,
  bool fitsHeight,
  AlignmentGeometry alignment,
});

The child will be asked to define its own intrinsic height. If fitsHeight is true, the child will be proportionately resized (keeping its aspect ratio) to fit the available height.

Then, if the child doesn't fit the width, it will be shrinked horizontally only (not keeping its aspect ratio) until it fits, unless shrinkLimit is larger than zero, in which case it will shrink only until that limit. Note if shrinkLimit is 1.0 the child will not shrink at all. The default is 0.67 (67%).

This is specially useful for text that is displayed in a single line. When text doesn't fit the container it will shrink only horizontally, until it reaches the shrink limit. From that point on it will clip, display ellipsis or fade, according to the text's Text.overflow property.

Note: FitHorizontally with shrinkLimit 0.0 is not the same as FittedBox with BoxFit.fitWidth, because FitHorizontally will only scale horizontally, while FittedBox will maintain the aspect ratio.

Try running the FitHorizontally example.


Box

Box is something between a Container and a SizedBox, which is less verbose and can be made const.

const Box({
  bool show = true,
  Color color,
  EdgeInsetsGeometry padding,
  double width,
  double height,
  Alignment alignment,
  Widget child,
});

Since Box can be made const, it's good for creating colored boxes, with or without a child and padding:

const Box(color: Colors.red, width: 50, height:30);

It allows you to make const large blocks of code. For example, the following code uses a Box, and couldn't be const if we were to use a SizedBox or a Container:

static const progressIndicator =
  Opacity(
    opacity: 0.6,
    child: Box( // Can't use SizedBox or Container here. 
      color: Colors.blue,
      alignment: Alignment.center,
      child: Padding(
          padding: Pad(all: 5.0),
          child: AspectRatio(
              aspectRatio: 1,
              child: CircularProgressIndicator(
                  valueColor: AlwaysStoppedAnimation<Color>(Colors.white)))),),);}

Const objects are final/immutable and created in compile time. So you don't waste time creating them. Also, all const objects of the same type with the same parameters are the same instance. So you don't waste memory creating more than one of them. In other words, const objects make your program faster and more memory efficient. They can also be used as default values in constructors, and they work well with hot-reload, while final values do not.

Extra Box features

  • You can hide the box by making the show parameter equal to false.

  • If you make removePaddingWhenNoChild: true, the padding is only applied if the child is not null. If the child is null and width and height are also null, this means the box will occupy no space (will be hidden).

  • Note: You can use the Pad class (provided in this package) for the padding, instead of EdgeInsets. For example:

    Box(padding: Pad(horizontal: 8, top: 20));
    
  • You can change a box with the copyWith method. For example:

    myBox.copyWith(color: Colors.blue);
    
  • You can create boxes by adding a Box to one these types: bool, Color, EdgeInsetsGeometry, AlignmentGeometry, or Widget:

    // To hide the box:
    Box(...) + false;
    
    // To show the box:
    Box(...) + true;
    
    // To change the box color:
    Box(...) + Colors.green;
    
    // To change the box padding:
    Box(...) + Pad(all: 10);
    
    // To substitute the box child:
    Box(...) + Text('abc');
    
    // To put a box inside of another:
    Box(...) + Box(...);
    

    Note: If you add null, that's not an error. It will simply return the same Box. However, if you add an invalid type it will throw an error in RUNTIME.

    // Not an error:
    Box(...) + null;
    
    // Throws:
    Box(...) + MyObj();
    
  • Methods to change width and height of the box: add, subtract.

Debugging:

  • If need to quickly and temporarily add a color to your box so that you can see it, you can use the constructors Box.r for red, Box.g for green, Box.b for blue, and Box.y for yellow.

    Box(child: myChild);
    Box.r(child: myChild);
    Box.g(child: myChild);
    Box.b(child: myChild);
    Box.y(child: myChild);
    
  • If you want to see rebuilds, you can use the Box.rand constructor. It will then change its color to a random one, whenever its build method is called.

    Box.rand(child: myChild);  
    

All these debugging constructors are marked as deprecated so that you don't forget to remove them.


WrapSuper

WrapSuper is similar to the native Wrap widget with direction = Axis.horizontal, but it allows you to choose different algorithms for the line-breaks.

WrapSuper displays its children in lines. It will leave spacing horizontal space between each child, and it will leave lineSpacing vertical space between each line. The contents of each line will then be aligned according to the alignment. The algorithm for the line-breaks is chosen by wrapType.

WrapSuper({
  Key key,
  WrapType wrapType,
  double spacing,
  double lineSpacing,
  WrapSuperAlignment alignment,
  List<Widget> children,
});

WrapSuper with WrapType.fit uses a greedy algorithm for line breaks, which is the same one used by the native Wrap widget.

However, WrapSuper with WrapType.balanced (the default) uses a minimum raggedness algorithm for line breaks. It will position its child widgets in the same number of lines as the greedy algorithm, but these lines will tend to be more similar in width.

For example:

  • Here is my original StackOverflow question that resulted in this widget.
  • The algorithm I used was based on this one (Divide and Conquer), which always considers spacing: 1.0. It was changed (with the help of CodeChef) to allow for other spacings.

  • Add your thumbs up here if you want native Text widgets to also allow for better line-breaks.

WrapFit

After WrapSuper distributes its children in each line, the wrapFit parameter defines the width of the widgets:

  • min (the default) will keep each widget's original width.

  • divided will make widgets fit all the available horizontal space. All widgets in a line will have the same width, even if it makes them smaller that their original width.

  • proportional will make widgets larger, so that they fit all the available space. Each widget width will be proportional to their original width.

  • larger will make widgets larger, so that they fit all the available space. Will try to make all widgets the same width, but won't make any widgets smaller than their original width. In more detail: 1) First, divide the available line width by the number of widgets in the line. That is the preferred width. 2) Keep the width of all widgets larger than that preferred width. 3) Calculate the remaining width and divide it equally by the remaining widgets.

Some examples:

Try running the WrapFit example.


ButtonBarSuper

ButtonBarSuper has a similar API to a regular ButtonBar, but will distribute its buttons by using a WrapSuper.

The default (which may be changed) is WrapType.balanced and WrapFit.larger, which means it will distribute the buttons in as little lines as possible in a balanced way; will make the buttons fill all the available horizontal space; and will try to make buttons have similar width in each line, without reducing their widths.

Try running the ButtonBarSuper example.


TextOneLine

TextOneLine is a substitute for Text when maxLines: 1, to fix this issue: https://github.com/flutter/flutter/issues/18761 filled by myself a long time ago.

It renders ellipsis as expected, much better than the current/ buggy and ugly-looking ellipsis of the native Text widget, which cuts the whole word.

For example, this:

Text("This isAVeryLongWordToDemonstrateAProblem", maxLines: 1, softWrap: false);  

Will print this in the screen:

This ...  

While this:

TextOneLine("This isAVeryLongWordToDemonstrateAProblem");  

Will print this:

This isAVeryLongWordToDemonst...  

Delayed

Delayed can be used to give a widget some initial value, and then, after some delay, change it to another value. As we'll see, Delayed is specially useful when used with implicitly animated widgets.

As soon as Delayed is inserted into the tree, it will build the widget returned by builder with initialized==false. Then:

  • If delay is null, it will rebuild with initialized==true in the next frame (usually 16 milliseconds later).

  • If delay is NOT null, it will rebuild with initialized==true after that delay.


For example, this shows a widget after a 2 seconds delay:

Delayed(delay: const Duration(seconds: 1),
  builder: (context, bool initialized) =>
    initialized
      ? Container(color: Colors.red, width: 50, height: 50)
      : SizedBox()));

For example, this changes a widget color after a 3 seconds delay:

Delayed(delay: const Duration(seconds: 3),
  builder: (context, bool initialized) =>
    Container(color: initialized ? Colors.red : Colors.blue,
              width: 50, 
              height: 50)
    )
)

For example, this will fade-in a widget as soon as it enters the screen:

Delayed(
  builder: (context, bool initialized) =>
    AnimatedOpacity(opacity: initialized ? 1.0 : 0.0,
                    duration: const Duration(seconds: 1),
                    child: MyWidget()
    )
);

For example, this will fade-in a widget 300 milliseconds after it enters the screen:

Delayed(delay: const Duration(milliseconds: 300),
  builder: (context, bool initialized) =>
    AnimatedOpacity(opacity: initialized ? 1.0 : 0.0,
                    duration: const Duration(seconds: 1),
                    child: MyWidget()
    )
);

Try running the Delayed example.


Pad

Pad is an EdgeInsetsGeometry which is easy to type and remember.

For example, instead of writing padding: EdgeInsets.symmetric(vertical: 12) you can write simply padding: Pad(vertical: 12).

// Instead of EdgeInsets.all(12)
padding: Pad(all: 12)

// Instead of EdgeInsets.only(top: 8, bottom: 8, left: 4, right: 2)
padding: Pad(top: 8, bottom: 8, left: 4, right: 2)

// Instead of EdgeInsets.symmetric(vertical: 12)
padding: Pad(vertical: 12)

// Instead of EdgeInsets.symmetric(vertical: 12, horizontal: 6)
padding: Pad(vertical: 12, horizontal: 6)

You can also compose paddings. For example, if you want 40 pixels of padding in all directions, except the top with 50 pixels: padding: Pad(all: 40, top: 10).

During development you sometimes need to temporarily remove the padding, for debugging reasons. Unfortunately you can't just comment the padding parameter, because the Padding widget doesn't accept null padding. But you can just add .x to the Pad class to remove it. It's marked as deprecated so that you don't forget to change it back to normal:

// This is the same as Pad.zero.
padding: Pad.x(top: 8, bottom: 8, left: 4)

NormalizedOverflowBox

A NormalizedOverflowBox is a widget that imposes different constraints on its child than it gets from its parent, possibly allowing the child to overflow the parent.

A NormalizedOverflowBox is similar to an OverflowBox. However, then OverflowBox may throw errors if it gets constraints which are incompatible with its own constraints. For example, if an OverflowBox is inside a container with maxWidth 100, and its own minWidth is 150, it will throw:

The following assertion was thrown during performLayout():
BoxConstraints has non-normalized width constraints. 

The NormalizedOverflowBox, on the other hand, will just make sure maxWidth is also 150 in the above example, and throw no errors. In other words, a NormalizedOverflowBox is safer to use, and in my opinion has the behavior OverflowBox should have had.

Try running the NormalizedOverflowBox Example. Then substitute the NormalizedOverflowBoxs with regular OverflowBoxes and see where it fails.


showDialogSuper and showCupertinoDialogSuper

Functions showDialogSuper and showCupertinoDialogSuper are identical to the native showDialog and showCupertinoDialog, except that they let you define an onDismissed callback for when the dialog is dismissed:

showDialogSuper(
   context: context,
   onDismissed: (dynamic result) { print("Dialog dismissed"); }
   builder: ...
} 

Usually there are 3 ways to close a dialog:

  1. Pressing some button on the dialog that closes it (usually by calling Navigator.pop(context)).
  2. Tapping the barrier.
  3. Pressing the Android back button.

All three ways will result in the onDismissed callback being called.

However, when the dialog is popped by Navigator.of(context).pop(result) you will get the result in the onDismissed callback. That way you can differentiate between the dialog being dismissed by an Ok or a Cancel button. The result is null when the dialog is dismissed by tapping the barrier or pressing BACK in Android. Example:

showDialogSuper<int>(
...
  actions: [
    ElevatedButton( onPressed: (){Navigator.pop(context, 1);}, child: const Text("OK"),
    ElevatedButton( onPressed: (){Navigator.pop(context, 2);}, child: const Text("CANCEL"),        
  ]
  ...
  onDismissed: (int? result) {
    if (result == 1) print("Pressed the OK button.");
    else if (result == 2) print("Pressed the CANCEL button.");
    else if (result == null) print("Dismissed with BACK or tapping the barrier.");  
  });  

This method was created to solve this issue: https://github.com/flutter/flutter/issues/26542 filled by myself a long time ago.

Try running the showDialogSuper Example.


TimeBuilder

If you need some widget to change periodically (clocks, countdowns, stopwatches etc), one way of implementing this is using a Timer to rebuild it. This is, however, very inefficient and may make your app slow.

The TimeBuilder widget gives you the correct implementation of periodic rebuilds. It's based on Remi Rousselet's code and you can read all about it here.

Apart from better performance, using the TimeBuilder widget has the following advantages:

  • Compatible with DevTools "slow animations", which reduce the speed of AnimationControllers.

  • Compatible with Clock changes, allowing for testing (skip frames to target a specific moment in time).

  • The TimeBuilder widget animation is "muted" when the widget is not visible. For example, when the widget is a route that is currently not visible, or because of an ancestor widget such as Visibility.

Let's see some examples.

Periodical

To create a clock that ticks once per second, you can use the .eachSecond constructor:

TimeBuilder.eachSecond(
   builder: (BuildContext context, DateTime now, int ticks, bool isFinished) 
                => MyClock(now),
);

If you want the rebuilds to stop after 30 seconds you can add the seconds parameter:

TimeBuilder.eachSecond(
   seconds: 30,
   builder: (BuildContext context, DateTime now, int ticks, bool isFinished) 
                => MyClock(now),
);

There are also .eachMillisecond, .eachMinute and .eachHour constructors.

Countdown

You can also create a seconds countdown from a certain DateTime:

// 100 seconds countdown.
TimeBuilder.countdown(
   start: DateTime.now(),
   seconds: 15,
   builder: (BuildContext context, DateTime now, int ticks, bool isFinished,
      {required int countdown}) 
         => Text(isFinished ? "FINISHED" : countdown.toString()),
);

General animation

You can also create a general animation with the .animate constructor:

TimeBuilder.animate(
   builder: (BuildContext context, DateTime now, int ticks, bool isFinished) 
                => MyWidget(now),
   isFinished: ({required DateTime currentTime, required DateTime lastTime, required int ticks,})
                => currentTime.difference(initialTime) > Duration(seconds: 100),               
);

Creating your own

And, finally, you can also create your own TimeBuilder using the default constructor:

const TimeBuilder({
   Key? key,
   required this.builder,
   required this.ifRebuilds,
   this.isFinished,
}) : super(key: key);

You must provide the builder and ifRebuilds callbacks.

For each frame, Flutter will first call your ifRebuilds callback, which may return true or false:

typedef IfRebuilds = bool Function({

  /// The current time.
  required DateTime currentTime,

  /// The time of the last tick.
  required DateTime lastTime,

  /// The number of ticks since the timer started.
  required int ticks,
});

Only when it returns true, the builder will be asked to generate a widget. The builder callback is of type TimerWidgetBuilder:

typedef TimerWidgetBuilder = Widget Function(
  BuildContext context,

  /// The time of the current tick.
  DateTime dateTime,

  /// The number of ticks since the timer started.
  int ticks,

  /// This is false while the timer is on, and becomes true as soon as it ends.
  bool isFinished,
);

There is also an optional isFinished callback. Returning true here will generate one last rebuild, and then stop the animation for good (no more rebuilds).


GlobalValueKey and GlobalStringKey

For local keys, Flutter provides ObjectKey and ValueKey. But for global keys, it provides only GlobalObjectKey, which compares by identity:

Key keyA = GlobalObjectKey('1' + '23');
Key keyB = GlobalObjectKey('12' + '3');

keyA == keyA; // true
keyA == keyB; // false   

This package provides a GlobalValueKey to compare by equality (using operator ==).

For example:

Key keyA = GlobalValueKey('1' + '23');
Key keyB = GlobalValueKey('12' + '3');

keyA == keyA; // true
keyA == keyB; // also true   

If your key value is a String, you can also use a GlobalStringKey:

Key keyA = GlobalStringKey('1' + '23');
Key keyB = GlobalStringKey('12' + '3');

keyA == keyA; // true
keyA == keyB; // also true   

Advanced

There are many use cases for the GlobalValueKey, but I'd like to point out two in particular:

1) Creating keys inside the build method

Flutter's documentation for global keys states that:

/// Creating a new GlobalKey on every build will throw away the state of the
/// subtree associated with the old key and create a new fresh subtree for the
/// new key. Besides harming performance, this can also cause unexpected
/// behavior in widgets in the subtree. For example, a [GestureDetector] in the
/// subtree will be unable to track ongoing gestures since it will be recreated
/// on each build.
///
/// Instead, a good practice is to let a State object own the GlobalKey, and
/// instantiate it outside the build method, such as in [State.initState].

However, this is only correct for Flutter's native GlobalObjectKey. The keys provided here in this package can indeed be recreated on every build with no problems (as long, of course, as the value you use to create the key has a well-behaved operator ==).

2) Global keys from data classes

Suppose you want to derive keys from data classes, and then find widgets that correspond to them. For example, you have a User data class:

class User {
  final String name;
  User(this.name);  
  bool operator ==(Object other) => identical(this, other) || other is User && runtimeType == other.runtimeType && name == other.name;
  int get hashCode => name.hashCode;
}

Then you create a widget class from it:

class UserWidget extends StatefulWidget {
  final User user;
  UserWidget({required this.user});
  State<UserWidget> createState() => UserWidgetState();
}

class UserWidgetState extends State<UserWidget> {
  Widget build(BuildContext context) => Text(widget.user.name);  
}

To be able to find the user widget in the tree, modify your constructor as to create keys automatically, from the user:

UserWidget({required this.user}) : super(key: GlobalValueKey<UserWidgetState>(user));

And then, create a static method for easy access to the widget state:

static UserWidgetState? currentState(User user) =>
  GlobalValueKey<UserWidgetState>(user).currentState; 

You now have easy access to your widget state, from anywhere: UserWidget.currentState(someUser)

You can find a complete working example here.

Some thoughts about global keys

Global keys much more powerful than local keys, but in general, should not be used extensively. They are workarounds. I guess that's why Flutter does not provide a GlobalValueKey out of the box: Not to make global keys even more useful. Flutter has this philosophy that things that are useful, but can be used wrong, should be made difficult. In any case, I found that GlobalValueKey can sometimes make complex code orders of magnitude simpler.


AlignPositioned

See package align_positioned for widgets AlignPositioned and its siblings AnimatedAlignPositioned and AnimChain. They should be part of this package, but will remain in their own package for historical reasons.



The Flutter packages I've authored:

My Medium Articles:

My article in the official Flutter documentation:


Marcelo Glasberg:
https://github.com/marcglasberg
https://twitter.com/glasbergmarcelo
https://stackoverflow.com/users/3411681/marcg
https://medium.com/@marcglasberg

Comments
  • Not working with Flutter 1.15 (master channel): TextOneLine is missing implementations.

    Not working with Flutter 1.15 (master channel): TextOneLine is missing implementations.

    Using assorted_layout_widgets: ^1.0.15 and sdk: ">=2.3.0 <3.0.0" I'm getting this error when I've added RowSuper to a widget:

    Compiler message:
    ../../../flutter/.pub-cache/hosted/pub.dartlang.org/assorted_layout_widgets-1.0.15/lib/src/text_one_line.dart:19:7: Error: The non-abstract class 'TextOneLine' is missing implementations for these members:
     - Text.textHeightBehavior
    Try to either
     - provide an implementation,
     - inherit an implementation from a superclass or mixin,
     - mark the class as abstract, or
     - provide a 'noSuchMethod' implementation.
    
    class TextOneLine extends StatelessWidget implements Text {
          ^^^^^^^^^^^
    ../../../flutter/packages/flutter/lib/src/widgets/text.dart:432:31: Context: 'Text.textHeightBehavior' is defined here.
      final ui.TextHeightBehavior textHeightBehavior;
                                  ^^^^^^^^^^^^^^^^^^
    ../../../flutter/.pub-cache/hosted/pub.dartlang.org/assorted_layout_widgets-1.0.15/lib/src/text_one_line.dart:200:7: Error: The non-abstract class 'RenderParagraphX' is missing implementations for these members:
     - RenderParagraph.textHeightBehavior
     - RenderParagraph.textHeightBehavior=
    Try to either
     - provide an implementation,
     - inherit an implementation from a superclass or mixin,
     - mark the class as abstract, or
     - provide a 'noSuchMethod' implementation.
    
    class RenderParagraphX extends RenderBox
          ^^^^^^^^^^^^^^^^
    ../../../flutter/packages/flutter/lib/src/rendering/paragraph.dart:281:29: Context: 'RenderParagraph.textHeightBehavior' is defined here.
      ui.TextHeightBehavior get textHeightBehavior => _textPainter.textHeightBehavior;
                                ^^^^^^^^^^^^^^^^^^
    ../../../flutter/packages/flutter/lib/src/rendering/paragraph.dart:282:7: Context: 'RenderParagraph.textHeightBehavior=' is defined here.
      set textHeightBehavior(ui.TextHeightBehavior value) {
          ^^^^^^^^^^^^^^^^^^
    
    opened by Amir-P 12
  • Flutter 2 and 3 compatibility

    Flutter 2 and 3 compatibility

    Some changes in version 6.0.0 introduced changes specific to Flutter 3 only.

    https://github.com/marcglasberg/assorted_layout_widgets/blob/f7176a9dd40f1e0456c7aafafc29c91d33ee07fc/lib/src/delayed.dart#L40

    It would be great to support both Flutter 2 and 3 there using approach similar to this

    https://github.com/jonataslaw/getx/commit/9d2b87242aa5d5b54aebd4d635d1e16835635c49

    More details are at https://docs.flutter.dev/development/tools/sdk/release-notes/release-notes-3.0.0#your-code

    opened by ekuleshov 7
  • Incompatible with the latest Flutter beta (2.5.0-5.1.pre)

    Incompatible with the latest Flutter beta (2.5.0-5.1.pre)

    ../../../../.pub-cache/hosted/pub.dartlang.org/assorted_layout_widgets-5.0.2/lib/src/text_one_line_ellipsis_with_fade.dart:995:20: Error: The method 'RenderParagraphX.getBoxesForSelection' has fewer named arguments than those of overridden method 'RenderParagraph.getBoxesForSelection'.
      List<ui.TextBox> getBoxesForSelection(TextSelection selection) {
    
    opened by josh-burton 5
  • Missing implementations for RenderParagraph.getFullHeightForCaret

    Missing implementations for RenderParagraph.getFullHeightForCaret

       1 warning generated.
        ../../Library/flutter/.pub-cache/hosted/pub.dartlang.org/assorted_layout_widgets-1.3.4/lib/src/text_one_line.dart:207:7:
        Error: The non-abstract class 'RenderParagraphX' is missing implementations for these members:
         - RenderParagraph.getFullHeightForCaret
        Try to either
         - provide an implementation,
         - inherit an implementation from a superclass or mixin,
         - mark the class as abstract, or
         - provide a 'noSuchMethod' implementation.
    
        class RenderParagraphX extends RenderBox
              ^^^^^^^^^^^^^^^^
        ../../Library/flutter/packages/flutter/lib/src/rendering/paragraph.dart:750:11: Context:
        'RenderParagraph.getFullHeightForCaret' is defined here.
          double? getFullHeightForCaret(TextPosition position) {
                  ^^^^^^^^^^^^^^^^^^^^^
    
        Command PhaseScriptExecution failed with a nonzero exit code
        note: Using new build system
        note: Building targets in parallel
        note: Planning build
        note: Constructing build description
    
    Flutter 1.22.0-12.1.pre • channel beta • https://github.com/flutter/flutter.git
    Framework • revision 8b3760638a (2 days ago) • 2020-09-15 17:47:13 -0700
    Engine • revision 4654fc6cf6
    Tools • Dart 2.10.0 (build 2.10.0-110.3.beta)
    

    This is the error I got after trying to build my flutter project for ios.

    I'm using 1.22 from the beta channel which has support for Xcode12 and iOS14. Thank you

    opened by mvillanoy 4
  • Flutter v1.15.0

    Flutter v1.15.0

    Upgrading to Flutter 1.15.0 is breaks the TextOneLine Widget and prevents compilation. flutter/flutter#48346

    Since it is a breaking change I bumped the minor version as well.

    opened by passsy 3
  • Error: The non-abstract class 'TextOneLineEllipsisWithFade' is missing implementations

    Error: The non-abstract class 'TextOneLineEllipsisWithFade' is missing implementations

    Error: The non-abstract class 'TextOneLineEllipsisWithFade' is missing implementations for these members:
    ../…/src/text_one_line_ellipsis_with_fade.dart:20
     - Text.selectionColor
    Try to either
     - provide an implementation,
     - inherit an implementation from a superclass or mixin,
     - mark the class as abstract, or
     - provide a 'noSuchMethod' implementation.
    
    class TextOneLineEllipsisWithFade extends StatelessWidget implements Text {
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    : Context: 'Text.selectionColor' is defined here.
    ../…/widgets/text.dart:535
      final Color? selectionColor;
    
    opened by Solano-Furlan 2
  • Flutter 2.5.0: getBoxesForSelection has fewer named arguments than those of overridden method

    Flutter 2.5.0: getBoxesForSelection has fewer named arguments than those of overridden method

    When running my app using Flutter version 2.5.0 I get the following error in assorted_layout_widgets: 5.1.1 dependency:

    ../../.pub-cache/hosted/pub.dartlang.org/assorted_layout_widgets-5.1.1/lib/src/text_one_line_ellipsis_with_fade.dart:995:20: Error: The method 'RenderParagraphX.getBoxesForSelection' has fewer named arguments than those of overridden method 'RenderParagraph.getBoxesForSelection'.
          List<ui.TextBox> getBoxesForSelection(TextSelection selection) {
                           ^
        ../../Development/flutter/packages/flutter/lib/src/rendering/paragraph.dart:811:20: Context: This is the overridden method ('getBoxesForSelection').
          List<ui.TextBox> getBoxesForSelection(
                           ^
    

    There might have been some breaking change in Flutter 2.5.0. Can you please fix it?

    opened by WieFel 2
  • Building with flutter for web fails

    Building with flutter for web fails

    When building with flutter for web I get the following error:

    Target dart2js failed: Exception: /opt/flutter/.pub-cache/hosted/pub.dartlang.org/assorted_layout_widgets-1.1.1/lib/src/minimum_raggedness.dart:20:61:
    
    Error: The integer literal 9223372036854775807 can't be represented exactly in JavaScript.
        List<num> minimum = [0]..addAll(List<num>.filled(count, 9223372036854775807));
                                                                ^^^^^^^^^^^^^^^^^^^
    /opt/flutter/.pub-cache/hosted/pub.dartlang.org/assorted_layout_widgets-1.1.1/lib/src/minimum_raggedness.dart:26:16:
    Error: The integer literal 9223372036854775806 can't be represented exactly in JavaScript.
            return 9223372036854775806;
                   ^^^^^^^^^^^^^^^^^^^
    Error: Compilation failed.
    

    It works fine when compiling for Android

    opened by tchavet 2
  • TextOneLine doesn't respect OS-set textScaleFactor

    TextOneLine doesn't respect OS-set textScaleFactor

    First off, thanks for your work. It is useful and well done. 👍

    A minor thing: We found that using TextOneLine it does not automatically apply the OS-set textScaleFactor the way that a normal Text does. It you set the iOS or Android accessibility text scale to something larger (or smaller) than the default, the text stays the same size.

    Explicitly setting it scale factor with textScaleFactor: MediaQuery.of(context).textScaleFactor works well, which is great, but we expected this to be applied by default.

    opened by erickok 2
  • Is there something like flexShrink in css?

    Is there something like flexShrink in css?

    I have a row with text on the left and some icons on the right. I want the icon to be just next to the text all the time.

    The Row will push the icons away if the text is too long, and the RowSuper that you created will shrink the icons if there is not enough space.

    Is there something like flex_shrink in your library to allow a widget (the text in my case) to expand only if the row overflow?

    opened by danielchan303 1
  • null safety

    null safety

    build msg is: pub-cache/hosted/pub.dartlang.org/assorted_layout_widgets-6.0.0/lib/src/delayed.dart:40:29: Error: Method 'addPostFrameCallback' cannot be called on 'WidgetsBinding?' because it is potentially null.

    • 'WidgetsBinding' is from 'package:flutter/src/widgets/binding.dart' ('/D:/Android/flutter/packages/flutter/lib/src/widgets/binding.dart'). Try calling using ?. instead. WidgetsBinding.instance.addPostFrameCallback((Duration timeStamp) { ^^^^^^^^^^^^^^^^^^^^

    pls fix it

    opened by jielundewode 1
  • When using TextOneLine, we found all kinds of strange unicode characters when inspecting our app in appium.

    When using TextOneLine, we found all kinds of strange unicode characters when inspecting our app in appium.

    When inspecting the code for TextOneLine we saw this:

    String? get data => super.data == null ? null : Characters(super.data!).toList().join("\u{200B}");

    why is that?

    opened by dickverweij 0
Owner
Marcelo Glasberg
Marcelo Glasberg
A basic Flutter app that includes some native Widgets like alerts, cards, avatars, animated container, inputs, etc.

Flutter components This project was created with Flutter and some native Widgets like alerts, cards, avatars, animated container, inputs, etc. Getting

Paúl 4 Nov 15, 2021
A Flutter plugin which makes it straightforward to show the native equivalent of a CupertinoAlertDialog or CupertinoActionSheet dialog

A Flutter plugin which makes it straightforward to show the native equivalent of a CupertinoAlertDialog or CupertinoActionSheet dialog

Christoph Krassnigg 9 Dec 9, 2022
Make your native android Dialog Fancy and Gify.

Make your native android Dialog Fancy and Gify. A library that takes the standard Android Dialog to the next level with a variety of styling options and Gif's. Style your dialog from code.

Shashank Singhal 522 Jan 2, 2023
Flutter-useful-widgets - Flutter Useful Widgets

useful_widgets This package makes it easy to build apps by providing a list of simple and useful widgets. import 'package:useful_widgets/useful_widget

Ricardo Crescenti 6 Jun 20, 2022
Custom widgets and utils using Flutter framework widgets and Dart language

reuse_widgets_and_utils The custom widgets and utils using Flutter framework widgets and Dart programming language. Getting Started This project is a

null 1 Oct 29, 2021
Widgets beginner - Widgets beginner with flutter

Widgets beginner - Widgets beginner with flutter

Tukhtamurodov Sardorbek 2 Feb 6, 2022
Flutter UI Widgets Flutter Package

Flutter UI Widgets Flutter Package This package makes different Flutter UI widgets implementation easy for you. Flutter UI Widgets The list of widgets

Hassan Ur Rahman 0 May 6, 2022
Flutter Package for Easier Creation of Home Screen Widgets

Home Widget HomeWidget is a Plugin to make it easier to create HomeScreen Widgets on Android and iOS. HomeWidget does not allow writing Widgets with F

Anton Borries 405 Dec 31, 2022
A Flutter package which provides helper widgets for selecting single or multiple account/user from the given list.

account_selector A Flutter package which provides helper widgets for selecting single or multiple account/user from a list Supported Dart Versions Dar

Harpreet Singh 49 Oct 7, 2021
A new flutter package for collection of common popular social media widgets

Social Media Widgets - package A new flutter package for collection of common popular social media widgets Currently available widgets Snapchat screen

theboringdeveloper 34 Nov 12, 2022
Multi select flutter tejpal - A package for creating multi-select widgets in a variety of ways

Multi select flutter tejpal - A package for creating multi-select widgets in a variety of ways

Tejpal Singh 3 Jul 11, 2022
A flutter package which provides most commonly used widgets with their normal and neon version

This is a flutter package which provides most commonly used widgets with their normal and neon version. There are multiple different types of widgets under this package, which can be used to create more neon theme widget

ojas 24 Oct 7, 2022
Pal-Widgets - A flutter package for better onboarding

Pal widgets A flutter package for better onboarding. A set of amazing onboarding widgets for your flutter applications. Install package add in your pu

Dominique Rwema Bagirishya 31 Oct 6, 2022
This package supports drag & drop widgets inside the GridView.builder for multiplatform

This package supports drag & drop widgets inside the GridView.builder for multiplatform. It provides all the properties which are available in Gridview. builder and easy to implement with the few lines of code.

MindInventory 68 Dec 29, 2022
Various Flutter widgets that are developed by Google but not by the core Flutter team

Flutter widgets This repository contains the source code for various Flutter widgets that are developed by Google but not by the core Flutter team. Is

Google 1.1k Jan 7, 2023
React hooks for Flutter. Hooks are a new kind of object that manages a Widget life-cycles. They are used to increase code sharing between widgets and as a complete replacement for StatefulWidget.

English | Português Flutter Hooks A Flutter implementation of React hooks: https://medium.com/@dan_abramov/making-sense-of-react-hooks-fdbde8803889 Ho

Remi Rousselet 2.6k Dec 29, 2022
Code generation for Flutter Padding widgets based on your constants

Code generation for Flutter Padding widgets based on your constants

Emanuele 14 Oct 20, 2022
Flutter widgets and themes implementing the current macOS design language.

macos_ui Flutter widgets and themes implementing the current macOS design language. NOTE: This package depends on the excellent native_context_menu pl

Reuben Turner 1.1k Jan 7, 2023
This repo is for anything that can be reusable in flutter like custom widgets 🟥, animations 🌟and more

Flutter Shortcuts This repo is for anything that can be reusable in flutter like custom widgets ?? , animations ?? and more. How to Use Just get the f

Abdelrahman Mostafa Elmarakby 91 Dec 3, 2022