Skip to content

Repository files navigation

Flatter

We make Flutter flat, We are Flatter 👋

pub.dev Flatter

Gray shape shifter

The logo is contributed with ❤️ by Mahmoud Hussein

Table of contents

What's Flatter?

Flatter is an extra-light and powerful solution for the hell of nested widgets in Flutter. Flatter makes Flutter widgets flat, concise, readable, and maintainable. Flatter hides the verbosity of Flutter widgets by exposing declarative APIs for different components. Let's see it in practice

Before

InkWell(
onTap: () {},
child:constCenter(
child:Padding(
padding:EdgeInsets.all(20),
child:DecoratedBox(
decoration:BoxDecoration(boxShadow: [
BoxShadow(
color:Colors.black,
blurRadius:20,
spreadRadius:1.0,
offset:Offset(10.0, 10.0))
]),
child:Text(
'Example',
style:TextStyle(
color:Colors.black,
fontSize:17.0,
fontWeight:FontWeight.bold),
))),
),
);

After

Text('Example')
.textStyle(color:Colors.black, fontSize:18.0, fontWeight:FontWeight.bold)
.shadow(color:Colors.black, blurRadius:20, spreadRadius:1.0)
.padding(20)
.center()
.inkWell(onTap: () {});

Flatter adds the following advantages

  1. Flat: There's no nesting and the code moves from top to down. In the classic approach, the code moves from top-left to bottom-right.

Widget Nesting

Flat Widget

  1. Concise: The code is concise with zero verbosity and this make it more readable and maintainable.

  2. Natural: The code is more natural because you read it like: a text with some style that has a shadow and padding, and it's centered and handles onTap. In the classic approach, you read like: an onTap with center with shadow with text which has some style!

  3. Inside Out: Flatter is inside out, because you declare the widget then add its properties below it using . operator. In the classic approach, you declare the widget then wrap it inside its properties.

  4. Designed For Change: Changing UI in Flatter is easier than the classic approach. Suppose you need to put the padding inside the shadow in the previous example. You just need to move the shadow line after the padding like this:

Text('Example')
.textStyle(color:Colors.black, fontSize:18.0, fontWeight:FontWeight.bold)
.padding(20) // The padding is now inside the shadow!
.shadow(color:Colors.black, blurRadius:20, spreadRadius:1.0)
.center()
.inkWell(onTap: () {});

Another Example

Before

Container(
width:double.infinity,
padding:EdgeInsets.all(15.0),
decoration:BoxDecoration(
color:Colors.white,
boxShadow:const [BoxShadow(color:Colors.black, blurRadius:3)],
borderRadius:BorderRadius.vertical(top:Radius.circular(25.0))),
child:Column(
crossAxisAlignment:CrossAxisAlignment.start,
children: [
totalView(),
SizedBox(height:10.0),
totalAmountView(),
SizedBox(height:10.0),
InkWell(
child:Container(
padding:EdgeInsets.all(15.0),
width:double.infinity,
decoration:BoxDecoration(
color:Colors.lightBlue,
borderRadius:BorderRadius.all(Radius.circular(30.0))),
child:Text(
'CheckOut',
textAlign:TextAlign.center,
style:TextStyle(
color:Colors.white, fontWeight:FontWeight.bold),
),
),
),
],
),
);

After

FlatColumn(
crossAxisAlignment:CrossAxisAlignment.start,
of: () =>totalView() +SizedBox(height:10.0) +totalAmountView() +SizedBox(height:10.0) +checkoutView())
.inkWell(onTap: () {})
.padding(15)
.container(width:double.infinity)
.background(color:Colors.white, radius:25)
.shadow(color:Colors.black54, spreadRadius:1)
.paddingSymmetric(vertical:10, horizontal:10);

Widget Modifier

WidgetModifier is the heart of Flatter. A modifier that you apply to a view or another widget modifier, producing a different version of the original value. Adopt the WidgetModifier interface when you want to create a reusable modifier that you can apply to any widget. The example below combines several modifiers to create a new modifier that you can use to add background:

classBackgroundModifierimplementsWidgetModifier<Widget, DecoratedBox> {
BackgroundModifier(this.color);
Color color;
@overrideDecoratedBoxbody(Widget content) {
returnDecoratedBox(
decoration:BoxDecoration(color: color),
child: content,
);
}
}

You can apply modifier(_:) directly to a widget, but a more common and idiomatic approach uses modifier(_:) to define an extension to Widget itself that incorporates the widget modifier:

extensionBackgroundExtonWidget {
DecoratedBoxbackground(Color color) {
returnmodifier(BackgroundModifier(color));
}
}

WidgetGroup

A wrapper for a list of widgets. You can create this object by concatenating widgets using plus + operator. This allows concatenating widgets with the + operator instead of creating a list of widgets using [] operators.

For example:

FlatColumn(of: () =>Text("Hello") +Text("World")

Concatenating Text("Hello") and Text("World") returns WidgetGroup.

Components

The different components of the packages can be categorized as the following:

  • Layouts
  • Modifiers
  • Widget Extensions
  • Text Extension

Layouts

Every layout implements WidgetFunction or WidgetGroupFunction

The table below contains the available layouts

NameDescription
FlatCenterCenter widget with WidgetFunction.
FlatColumnColumn widget with WidgetGroupFunction.
FlatExpandedExpanded widget with WidgetFunction.
FlatMaterialMaterial widget with WidgetFunction.
FlatRowRow widget with WidgetGroupFunction.
FlatStackStack widget with WidgetGroupFunction.

Modifiers

The table below contains the available modifiers

NameDescription
AlignModifierModifier for Align widget
CardModifierModifier for Card widget
CenterModifierModifier for Center widget
ClipRectModifierModifier for ClipRect widget
ContainerModifierModifier for Container widget
DecoratedBoxModifierModifier for DecoratedBox widget
ExpandedModifierModifier for Expanded widget
GestureDetectorModifierModifier for GestureDetector widget
IconButtonModifierModifier for IconButton widget
InkWellModifierModifier for InkWell widget
MaterialModifierModifier for Material widget
OverlayModifierModifier for Stack widget
PaddingModifierModifier for Padding widget
TooltipModifierModifier for Tooltip widget

Widget Extensions

The table below contains the available widget extensions

NameDescription
cardApplies CardModifier
alignAtBottomCenterApplies AlignModifier
alignAtTopLeftApplies AlignModifier
alignAtBottomLeftApplies AlignModifier
alignAtBottomRightApplies AlignModifier
alignAtCenterLeftApplies AlignModifier
alignAtCenterApplies AlignModifier
alignAtCenterRightApplies AlignModifier
alignAtLERPApplies AlignModifier
alignXYApplies AlignModifier
alignAtTopCenterApplies AlignModifier
alignAtTopRightApplies AlignModifier
alignApplies AlignModifier
backgroundApplies DecoratedBoxModifier
centerApplies CenterModifier
containerApplies ContainerModifier
cornerRadiusApplies ClipRectModifier
clipRectApplies ClipRectModifier
expandedApplies ExpandedModifier
onSecondaryTapUpApplies GestureDetectorModifier
onSecondaryTapDownApplies GestureDetectorModifier
onSecondaryTapApplies GestureDetectorModifier
onTapCancelApplies GestureDetectorModifier
onTapApplies GestureDetectorModifier
onTapUpApplies GestureDetectorModifier
onTapDownApplies GestureDetectorModifier
onDoubleTapCancelApplies GestureDetectorModifier
onDoubleTapApplies GestureDetectorModifier
onDoubleTapDownApplies GestureDetectorModifier
onTertiaryTapCancelApplies GestureDetectorModifier
onTertiaryTapUpApplies GestureDetectorModifier
onTertiaryTapDownApplies GestureDetectorModifier
onSecondaryTapCancelApplies GestureDetectorModifier
onLongPressEndApplies GestureDetectorModifier
onLongPressUpApplies GestureDetectorModifier
onLongPressMoveUpdateApplies GestureDetectorModifier
onLongPressStartApplies GestureDetectorModifier
onLongPressApplies GestureDetectorModifier
onLongPressDownApplies GestureDetectorModifier
onTertiaryLongPressUpApplies GestureDetectorModifier
onTertiaryLongPressMoveUpdateApplies GestureDetectorModifier
onTertiaryLongPressStartApplies GestureDetectorModifier
onTertiaryLongPressApplies GestureDetectorModifier
onTertiaryLongPressCancelApplies GestureDetectorModifier
onTertiaryLongPressDownApplies GestureDetectorModifier
onSecondaryLongPressEndApplies GestureDetectorModifier
onSecondaryLongPressUpApplies GestureDetectorModifier
onSecondaryLongPressMoveUpdateApplies GestureDetectorModifier
onSecondaryLongPressStartApplies GestureDetectorModifier
onSecondaryLongPressApplies GestureDetectorModifier
onSecondaryLongPressCancelApplies GestureDetectorModifier
onSecondaryLongPressDownApplies GestureDetectorModifier
onVerticalDragCancelApplies GestureDetectorModifier
onVerticalDragEndApplies GestureDetectorModifier
onVerticalDragUpdateApplies GestureDetectorModifier
onVerticalDragStartApplies GestureDetectorModifier
onVerticalDragDownApplies GestureDetectorModifier
onTertiaryLongPressEndApplies GestureDetectorModifier
onForcePressStartApplies GestureDetectorModifier
onHorizontalDragCancelApplies GestureDetectorModifier
onHorizontalDragEndApplies GestureDetectorModifier
onHorizontalDragUpdateApplies GestureDetectorModifier
onHorizontalDragStartApplies GestureDetectorModifier
onHorizontalDragDownApplies GestureDetectorModifier
onScaleEndApplies GestureDetectorModifier
onScaleUpdateApplies GestureDetectorModifier
onScaleStartApplies GestureDetectorModifier
onPanCancelApplies GestureDetectorModifier
onPanEndApplies GestureDetectorModifier
onPanUpdateApplies GestureDetectorModifier
onPanStartApplies GestureDetectorModifier
onPanDownApplies GestureDetectorModifier
onForcePressEndApplies GestureDetectorModifier
onForcePressUpdateApplies GestureDetectorModifier
onForcePressPeakApplies GestureDetectorModifier
iconButtonApplies IconButtonModifier
inkWellApplies InkWellModifier
materialApplies MaterialModifier
overlayApplies OverlayModifier
paddingApplies PaddingModifier
paddingHorizontalApplies PaddingModifier
paddingVerticalApplies PaddingModifier
paddingOnlyApplies PaddingModifier
paddingLTRBApplies PaddingModifier
paddingFromWindowPaddingApplies PaddingModifier
paddingSymmetricApplies PaddingModifier
paddingInsetsApplies PaddingModifier
shadowApplies DecoratedBoxModifier
tooltipApplies TooltipModifier

Text Extensions

The table below contains the available text extensions

NameDescription
textStyleApplies TextStyle
withTextStyleApplies TextStyle
textScaleApplies textScaleFactor
boldApplies TextStyle
italicApplies TextStyle
fontWeightApplies TextStyle
fontSizeApplies TextStyle
fontFamilyApplies TextStyle
letterSpacingApplies TextStyle
wordSpacingApplies TextStyle
textShadowApplies TextStyle
textColorApplies TextStyle
textAlignmentApplies TextStyle
textDirectionApplies TextStyle
textBaselineApplies TextStyle
textWidthBasisApplies TextStyle
withUnderLineApplies TextStyle
mostThickProvides predefined TextStyle
extraBoldProvides predefined TextStyle
boldProvides predefined TextStyle
semiBoldProvides predefined TextStyle
mediumProvides predefined TextStyle
regularProvides predefined TextStyle
lightProvides predefined TextStyle
extraLightProvides predefined TextStyle
thinProvides predefined TextStyle

WidgetFunction

A function that returns a widget. It's used and an alternative better syntax for child parameter. of parameter below is a WidgetFunction.

FlatCenter(of: () =>Text("Hello world"))

WidgetGroupFunction

A function that returns a WidgetGroup. It's used and an alternative better syntax for children parameter. of parameter below is a WidgetGroupFunction.

FlatColumn(of: () =>Text("Hello") +Text("World")

👏 Contribution

All Pull Requests (PRs) are welcome. Help us make this library better.

Changelog

Look at Changelog for release notes.

License

Click to reveal License
Copyright (c) 2021 Shaban Kamel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

About

We make Flutter flat, We are Flatter 👋

Resources

Stars

15 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages