Flutter Package: When your desired layout or animation is too complex for Columns and Rows, this widget lets you position/size/rotate/transform its child in complex ways.

Overview

pub package

align_positioned

Widgets in this package:

  • AlignPositioned
  • AnimatedAlignPositioned
  • AnimChain

Why are these widgets an indispensable tool?

When your desired layout feels too complex for Columns and Rows, AlignPositioned is a real lifesaver. Flutter is very composable, which is good, but sometimes it's unnecessarily complex to translate some layout requirement into a composition of simpler widgets.

The AlignPositioned aligns, positions, sizes, rotates and transforms its child in relation to both the container and the child itself. In other words, it lets you easily and directly define where and how a widget should appear in relation to another.

For example, you can tell it to position the top-left of its child at 15 pixels to the left of the top-left corner of the container, plus move it two thirds of the child's height to the bottom plus 10 pixels, and then rotate 15 degrees. Do you even know how to start doing this by composing basic Flutter widgets? Maybe, but with AlignPositioned it's much easier, and it takes a single widget.

Besides layout, AlignPositioned is specially helpful for explicit animations (those that use a controller), since you can just calculate the final position, size and rotation you want for each frame. Without it, you may find yourself having to animate a composition of widgets.

Meanwhile, AnimatedAlignPositioned and AnimChain widgets are helpful for implicit animations, which are very easy to create. If you change their parameters they animate automatically, interpolating between the old and new parameter values.

How it works

Add align_positioned as a dependency in your pubspec.yaml file, then import it:

import 'package:align_positioned/align_positioned.dart';

Pass a child to the AlignPositioned or the AnimatedAlignPositioned, and then one or more of the following parameters:

AlignPositioned(
   child: child,
   alignment: ...,
   dx: ...,
   dy: ...,
   moveByChildWidth: ...,
   moveByChildHeight: ...,
   moveByContainerWidth: ...,
   moveByContainerHeight: ...,
   moveVerticallyByChildWidth: ...,
   moveHorizontallyByChildHeight: ...,
   moveVerticallyByContainerWidth: ...,
   moveHorizontallyByContainerHeight: ...,
   childWidth: ...,
   childHeight: ...,
   minChildWidth: ...,
   minChildHeight: ...,
   maxChildWidth: ...,
   maxChildHeight: ...,
   childWidthRatio: ...,
   childHeightRatio: ...,
   minChildWidthRatio: ...,
   minChildHeightRatio: ...,
   maxChildWidthRatio: ...,
   maxChildHeightRatio: ...,
   rotateDegrees: ...,
   matrix4Transform: ...,
   wins: ...,
   touch: ...,
   );

Let's study each parameter in detail:

Align and Position parameters

The alignment parameter works as expected. For example, Alignment.bottomRight represents the bottom right of the container, and Alignment(0.0, 0.0) represents the center of the container. The distance from -1.0 to +1.0 is the distance from one side of the rectangle to the other side of the rectangle.

If touch is Touch.inside, then alignment works just like the alignment for the Align widget, aligning the child inside the container.

However, if touch is Touch.outside, then the alignment happens outside the container; and if it's Touch.middle, the center of the child will be aligned to the container edge.

As another example, if touch is Touch.inside, then Alignment(1.0, 0.0) makes the child's right side touch the right side of the container (it touches the container from the inside).

But if touch is Touch.outside, then Alignment(1.0, 0.0) makes the child's left side touch the right side of the container (it touches the container from the outside).

But if touch is Touch.middle, then Alignment(1.0, 0.0) makes the child's center touch the right side of the container (it touches the container from the middle).

Parameters dx and dy can be positive or negative, and move the child horizontally and vertically, in pixels.

Parameters moveByChildWidth and moveByChildHeight can be positive or negative, and move the child horizontally and vertically, but the unit here is not pixels, but child widths and heights.

Parameters moveByContainerWidth and moveByContainerHeight can be positive or negative, and move the child horizontally and vertically, but the unit here is not pixels, but container widths and heights.

Parameters moveVerticallyByChildWidth, moveHorizontallyByChildHeight, moveVerticallyByContainerWidth and moveHorizontallyByContainerHeight allow you to move in some direction according to the size (width or height) of the orthogonal direction. For example, while moveByChildWidth: 0.2 would move horizontally by 20% of the child's width, moveVerticallyByChildWidth would move vertically by 20% of the child's width.

Align and Position Examples

The below image shows the center of the child positioned 15 pixels to the right of the top-left corner of the container:

AlignPositioned(
   child: child,
   alignment: Alignment.topLeft,
   touch: Touch.inside,
   dx: 15.0, // Move 4 pixels to the right.
   moveByChildWidth: -0.5, // Move half child width to the left.
   moveByChildHeight: -0.5); // Move half child height to the top.

Then, to move the child one container width to the right, and one container height to the bottom:

AlignPositioned(
   child: child,
   alignment: Alignment.topLeft,
   touch: Touch.inside,
   dx: 15.0, // Move 4 pixels to the right.
   moveByChildWidth: -0.5, // Move half child width to the left.
   moveByChildHeight: -0.5, // Move half child height to the top.
   moveByContainerWidth: 1.0, // Move one container width to the right.
   moveByContainerHeight: 1.0); // Move one container height to the bottom.

Please try the example that showcases the effects seen below:

Size Parameters

Optionally, you can also define the child size:

  • childWidth is the child width, in pixels.

  • childHeight is the child height, in pixels.

  • minChildWidth is the minimum width, in pixels. It has precedence over childWidth.

  • minChildHeight is the minimum height, in pixels. It has precedence over childHeight.

  • maxChildWidth is the maximum width, in pixels. It has precedence over childWidth.

  • maxChildHeight is the maximum height, in pixels. It has precedence over childHeight.

  • childWidthRatio is the child width, as a fraction of the container width. If between 0.0 and 1.0, the child will be smaller than its container. If more than 1.0, the child will be larger than its container. If you define both childWidthRatio and childWidth they will be added.

  • childHeightRatio is the child height, as a fraction of the container height. If between 0.0 and 1.0, the child will be smaller than its container. If more than 1.0, the child will be larger than its container. If you define both childHeightRatio and childHeight they will be added.

  • minChildWidthRatio is the minimum child width, as a fraction of the container width. It has precedence over childWidth. If both minChildWidth and minChildWidthRatio are defined, both will be applied (the minimum will be the larger one).

  • minChildHeightRatio. is the minimum child height, as a fraction of the container height. It has precedence over childHeight. If both minChildHeight and minChildHeightRatio are defined, both will be applied (the minimum will be the larger one).

  • maxChildWidthRatio is the maximum child width, as a fraction of the container width. It has precedence over childWidth. If both maxChildWidth and maxChildWidthRatio are defined, both will be applied (the maximum will be the smaller one).

  • maxChildHeightRatio is the maximum child height, as a fraction of the container height. It has precedence over childHeight. If both maxChildHeight and maxChildHeightRatio are defined, both will be applied (the maximum will be the smaller one).

  • wins decides what happens if the minimum size is larger than the maximum size. If wins is Wins.min, the default, the minimum size will be used. If wins is Wins.max, the maximum size will be used.

Rotate and Transform

Optionally, you can also define rotation and transformation:

  • rotateDegrees is the rotation, in degrees (1 turn is 360 degrees). The position of the axis of the rotation (the "origin") depends on the alignment parameter and the parent. So, for example, Alignment.center means the axis of rotation is at the center of the parent.

  • matrix4Transform lets you apply any transformation to the child. This uses Matrix4Transform instead of Matrix4, since it's easier to use. However, you can still use Matrix4 directly with the constructor Matrix4Transform.from(matrix4).

One widget relative to another

Use the AlignPositioned.relative() factory if you have a main widget, and you want to position/size/rotate/translate another widget relative to the main one, but the second is not a child of the first.

Example, to center the main container widget, and then put a relative child widget vertically below it (in the Y-axis):

Center(
   child: AlignPositioned.relative(
       container: widgetA(),
       child: widgetB(),
       moveByContainerHeight: 0.5,
       moveByChildHeight: 0.5));

The invert parameter controls which widget overlaps the other. If invert is false (the default), the container widget is below the child widget in the Z-axis (will be painted before). If invert is true, the container widget to be on top of the child widget, in the Z-axis (will be painted after).

Using AlignPositioned inside a Stack

A Stack positions its children relative to the edges of its box. The Stack documentation contains this text:

In particular, when using a Stack you can't position children relative to their size or the stack's own size.

However, by using AlignPositioned you can do precisely that: position (and size, rotate and transform) children relative to their size or the Stack's own size, and consequently in relation to the other widgets inside the Stack.

If you recall how a Stack works, each of its child widgets is either positioned or non-positioned. The stack sizes itself to contain all the non-positioned children, which are positioned according to the stacks' alignment parameter. Next, the positioned children are laid out.

If you use the AlignPositioned default constructor and put it inside a Stack, it will be a ** non-positioned** child.

To create a positioned widget, use the AlignPositioned.expand() factory. The AlignPositioned will then expand and fix itself to the corners of the Stack. In other words, the Stack will size itself to their other non-positioned widgets, and then you can use the AlignPositioned to lay out its child in relation to the Stack.

Example:

Stack(
  children: [
    Container(...),
    Positioner(child: Container(...)),
    AlignPositioned(...),
    AlignPositioned.expand(...),
    ...
    ]);

Implicit Animation

If you change the AnimatedAlignPositioned parameters it will animate automatically:

return AnimatedAlignPositioned(
    duration: Duration(seconds: 3)
    alignment: Alignment.bottomCenter,
    rotateDegrees: isOk ? 0 : 180,
    child: AnimatedContainer(
        color: isOk ? Colors.yellow : Colors.red,
        duration: Duration(seconds: 2)
        ),
    );

How to Chain Implicit Animation Widgets

The AnimChain widget lets you define a sequence of widgets, where each one will be displayed after the previous after some wait time.

You can chain widgets which are totally different from one another. For example:

AnimChain(repeat: true, initialDelay: Duration(milliseconds: 150))

      // Yellow box for 700 milliseconds
      .next(
        wait: Duration(milliseconds: 700),
        widget: Container(color: Colors.yellow, width: 95, height: 95, margin: const EdgeInsets.all(2.5)))
      
      // Red text for 1000 milliseconds
      .next(
        wait: Duration(milliseconds: 1000),
        widget: Container(child: Text("Hello world!", style: TextStyle(color: Colors.red, fontSize: 25)), width: 100, height: 100))

      // Blue icon for 1200 milliseconds
      .next(
        wait: Duration(milliseconds: 1200),
        widget: Icon(Icons.accessibility, color: Colors.blue, size: 100));

Try running the example.


However, if you define implicitly animated widgets (like AnimatedAlignPositioned, AnimatedContainer, AnimatedOpacity, AnimatedPadding etc.) then you can easily create a smooth animation.

For example:

return AnimChain(repeat: true, initialDelay: Duration(milliseconds: 150))
   // Show the yellow box and wait 5 seconds.
   .next(
      wait: Duration(seconds: 5),
      widget: AnimatedAlignPositioned(
         alignment: Alignment.bottomCenter,
         rotateDegrees: 0,
         child: Container(color: Colors.yellow),
         ),
      )
   // Rotate to the red box in 3 seconds.
   .next(
      wait: Duration(seconds: 3),
      widget: AnimatedAlignPositioned(
         duration: Duration(seconds: 3),
         rotateDegrees: 180,
         child: Container(color: Colors.red),
         ),
      )
   // Finally, translate the blue in the vertical axis.
   .next(
      widget: AnimatedAlignPositioned(
         duration: Duration(seconds: 15),
         alignment: Alignment.bottomCenter,
         dy: 150,
         rotateDegrees: 180,
         child: Container(color: Colors.blue),
         ),
      ),
    );

Try running the example.


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
  • [Feature Request] Add the `.expand()`constructor for the AnimatedAlignPositioned widget.

    [Feature Request] Add the `.expand()`constructor for the AnimatedAlignPositioned widget.

    Hi dear @marcglasberg . I hope you are doing great.

    I've been a user of this package for a long time. I just forgot to say you that it is needed to add the.expand() constructor for the AnimatedAlignPositioned widget.

    You already added it for the AlignPositioned. Currently, I am solving this issue by wrapping the widgets like this:

    Stack(
      children: [
        Positioned(
          top: 0,
          right: 0,
          left: 0,
          bottom: 0,
            child: AnimatedAlignPositioned(
    ...
    ...
    ...
    

    So the the Positioned(top: 0, right: 0, left: 0, bottom: 0, child: child) widget let the AnimatedAlignPositioned take the size of the parent Stack widget.

    Use Case

    I have another widget inside the stack that basically shows an image pager whose height is determined by an AspectRatio. Since I use the AspectRatio widget, the non-positioned child of the stack (the image pager) has no height value. However, it can be laid out. So in such a case, without the .expand() constructor, I have to use a Positioned widget.

    Not a big deal but it could be easier to implement. (Also there might be people that do not know how the stack widget works. Sometimes, even I forget to wrap it with the Positioned(top: right: left: bottom: 0, child: child) that makes me wonder "What I did wrong?" There can be a documentation update too.)

    Thanks a lot!

    opened by yasinarik 4
  • GestureDetector outside the original area.

    GestureDetector outside the original area.

    Try to recreate a sample code from the first example (with a semi-transparent circle on the left of the red container) and wrap that circle into Material -> InkWell.

    Tap will be recognized only if you tap on the overlapping with the red container section of the circle, otherwise, it will be ignored.

    Working tap area is this:

    edInkedalignPos1_LI

    Whereas anyone would expect it to be the whole circle widget.

    enhancement 
    opened by egorikem 4
  • Problem with SingleChildScrollView

    Problem with SingleChildScrollView

    Hi and thank you for share you very good library with us... I've a problem when use it with SingleChildScrollView. I use SingleChildScrollView as child of AlignPositioned and the scrolling is not handled by SingleChildScrollView.

    opened by carmas123 3
  • Offset by 50% of child width, when parent widget has no fixed size, and child size is unknown

    Offset by 50% of child width, when parent widget has no fixed size, and child size is unknown

    Assume we have a parent widget (a Container), with no fixed size, and positioned absolutely (within it's own parent) at a top/left (x/y) coordinate. Then we place a child widget (with no fixed or known size) within the parent. Using your library, is there a way to position the child at -0.5 of its own width and height, such that the child's center appears at the x/y coordinate of its parent? I'm trying to achieve this using your (fantastic) library but when I don't specify the width/height of the parent, I get the following error.

    RenderBox was not laid out: _RenderAlignPositionedBox#7e614 relayoutBoundary=up10
    'package:flutter/src/rendering/box.dart':
    Failed assertion: line 1694 pos 12: 'hasSize'
    
    enhancement 
    opened by ROTGP 2
  • childHeightRatio as a proportion to parent's Width

    childHeightRatio as a proportion to parent's Width

    Is there any way to set child's height as a proportion to parent's width? This is a very common need and it would be very nice if it would be supported internally from the plugin (without writing a setState manually). Example use case: size a container with the same width and heigh that equals to 1/5 of parent's width.

    Kudos for your excellent work with all your published plugins!

    enhancement 
    opened by Magenda 2
  • Aligning Overflowed Children

    Aligning Overflowed Children

    https://stackoverflow.com/questions/72583553/flutter-aligning-overflowed-children Can this library solve this problem?

    Although dx and dw can be used to move the middle image of the 3x3 array to the middle of the parent container, it seems difficult to operate in a reactive manner on multiple devices.

    Can the center image(2x2) always be centered in the parent widget in a reactive 3x3 array?

    opened by hyun97 1
  • Is it possible with nested stacks?

    Is it possible with nested stacks?

    First of all, thank you for making this library, very easy to use.

    The issue I am facing now is that when I try to use AlignPositioned in another stack nested inside the parent AlignPositioned widget, the layout is messed up.

    I am wondering if there is any solution for this. Thanks

    Stack
     |-- AlignPositioned
           |-- Stack
                 |-- AlignPositioned
    
    question 
    opened by lei-cao 1
  • Is it possible to make secondary widget bigger than main one in .relative

    Is it possible to make secondary widget bigger than main one in .relative

    AlignPositioned.relative(
      widgetA(),
      widgetB(),
      moveByContainerHeight: 0.5,
      moveByChildHeight: 0.5,
    ),
    

    Seems like widgetB can't be bigger than widgetA. Is it possible to do? What I want to achieve is to make widgetA an icon and widgetB a GestureDetector of a bigger size. So that button icon perfectly fits into the design but with a bigger touch area.

    opened by bambuh 1
  • Documentation Request

    Documentation Request

    Hi there, feel free to close if it's not within the scope of this project. I would be nice to have a couple animated GIF examples, especially AnimChained. Thanks!

    documentation 
    opened by lukepighetti 2
Owner
Marcelo Glasberg
Marcelo Glasberg
A widget that imposes different constraints on its child than it gets from its parent

A widget that imposes different constraints on its child than it gets from its parent, possibly allowing the child to overflow the parent. Similar to `OverflowBox` except that the unconstrained width or height is sized to the intrinsic size of the child, instead of being assumed to be infinite, which allows IntrinsicSizeOverflowBox to be used in a `Scrollable` widget.

Ron Booth 3 Dec 7, 2022
A widget which implicitly launches a hero animation when its position changed within the same route.

local_hero A widget which implicitly launches a hero animation when its position changed within the same route. Getting started In the pubspec.yaml of

Romain Rastel 174 Jan 6, 2023
Custom-Position-Popup - Custom Position Popup For Flutter

Custom-Position-Popup before clone the GitHub repository please give a star on t

Blackshadow Software Ltd 11 Oct 17, 2022
A Flutter widget that will give a Glitch Animation Effect to it's child widget.

GlitchEffect A Flutter widget that will give a Glitch Animation Effect to it's child widget. Installation Add the latest version of package to your pu

Sameer Singh 6 Nov 25, 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 carousel widget, support infinite scroll, and custom child widget.

carousel_slider A carousel slider widget. Features Infinite scroll Custom child widgets Auto play Supported platforms Flutter Android Flutter iOS Flut

Bart T 1 Nov 25, 2021
Animated Search Bar package lets you add a beautiful search bar to your Flutter app.

Animated Search Bar Animated Search Bar package lets you add a beautiful search bar to your Flutter app. Installation Add the latest version of packag

Mohammad Saleh 5 Aug 7, 2022
A dice game made with Flutter and its Animation Widget

Jogo de dado feito com animação em flutter Esse projeto é um jogo de dado feito com Flutter e seus Widget de animação. Não foi necessário uso de pacot

Francis Santos 0 May 10, 2022
Responsive Widgets Prefix allows you to add the "Responsive" prefix to any widget that needs scaling or font size increases

Responsive Widgets Prefix allows you to add the Responsive prefix to any widget that needs scaling or font size increases (for varying device screen sizes).

The Mobile Applications Community 2 Apr 18, 2022
Rows_Columns with Child and Children Widget Demo

Rows_Columns with Child and Children Widget Demo A new Flutter project.This project is to show the combination of Rows and Columns and Child and Child

Avinandan Bose 1 Mar 17, 2022
Flutter package: Similar to a ListView, but lets you programmatically jump to any item, by index.

indexed_list_view Similar to a ListView, but lets you programmatically jump to any item, by index. The index jump happens instantly, no matter if you

Marcelo Glasberg 244 Dec 27, 2022
Flutter ScrollView Observer - a library of widget that can be used to listen for child widgets those are being displayed in the scroll view

Flutter ScrollView Observer - a library of widget that can be used to listen for child widgets those are being displayed in the scroll view

林洵锋 67 Jan 6, 2023
An alternative to Overlay which allows you to easily render and hit test a widget outside its parent bounds

An alternative to Overlay which allows you to easily render and hit test a widget outside its parent bounds. Based on the original idea by @shrouxm he

gskinner team 26 Dec 31, 2022
An advanced switch widget, that can be fully customized with size, text, color, radius of corners.

flutter_advanced_switch An advanced switch widget, that can be fully customized with size, text, color, radius of corners. Switch Light Switch Dark Ge

Alex Melnyk 13 Dec 15, 2022
Flutter Sticky Headers - Lets you place

Flutter Sticky Headers Lets you place headers on scrollable content that will stick to the top of the container whilst the content is scrolled. Usage

Flutter Community 901 Dec 28, 2022
Displays a scrollable timeline with custom child widgets and custom icons.

Flutter Timeline Widget Displays a scrollable timeline with custom child widgets and custom icons. Installation In your pubspec.yaml file within your

Furkan Tektas 375 Nov 20, 2022
Flutter package: Assorted layout widgets that boldly go where no native Flutter widgets have gone before.

assorted_layout_widgets I will slowly but surely add interesting widgets, classes and methods to this package. Despite the package name, they are not

Marcelo Glasberg 122 Dec 22, 2022
AdvFAB - An Advanced floating action button that expands itself to reveal its hidden widget

AdvFAB (More Than Just A Floating Action Button) AdvFAB is An Advanced floating action button that expands itself to reveal its hidden widget. It can

null 19 Nov 4, 2022
A custom dropdown button lets the user select from a number of items

CircularDropDownMenu Description A custom dropdown button lets the user select from a number of items. The button shows the currently selected item as

Surya Dev Singh 2 Dec 5, 2020