swiftify 1.5.0 copy "swiftify: ^1.5.0" to clipboard
swiftify: ^1.5.0 copied to clipboard

For SwiftUi Developers.

Swiftify 🚀 #

Swiftify brings the elegance of SwiftUI's modifier syntax to Flutter! This package introduces a streamlined way to build Flutter UIs by extending widgets with chainable, modifier-style methods. Say goodbye to deeply nested widget trees and hello to clean, readable, and maintainable code.

pub package License: MIT


✨ Features #

  • SwiftUI-like Modifiers — Apply common widget properties (padding, text styles, shadows, transforms, etc.) with intuitive .modifier() methods.
  • Chainable Methods — Combine multiple modifications into a single statement for a clean, declarative style.
  • Cleaner Codebase — Reduce widget nesting and improve code readability.
  • Comprehensive Coverage — 27 extension files covering sizing, layout, decoration, animation, navigation, theming, accessibility, and more.
  • Debug-Friendly Assertions — Detailed assert messages catch invalid parameters early in development.

📦 Installation #

Add the package to your pubspec.yaml:

dependencies:
  swiftify: ^1.5.0

Run flutter pub get, then import:

import 'package:swiftify/swiftify.dart';

🔄 Before & After #

Before (deeply nested) #

Center(
  child: Opacity(
    opacity: 0.8,
    child: Container(
      decoration: BoxDecoration(
        boxShadow: [BoxShadow(blurRadius: 10)],
        borderRadius: BorderRadius.circular(12),
      ),
      child: Padding(
        padding: EdgeInsets.all(16),
        child: Text("Hello"),
      ),
    ),
  ),
)

After (with Swiftify ✅) #

Text("Hello")
    .padding()
    .shadow(blurRadius: 10)
    .borderRadius(radius: 12)
    .opacity(0.8)
    .center()

📚 API Reference #

📐 Sizing — SizingModifier #

Extension on Widget

Modifier Description
.frame(width:, height:) Wraps in SizedBox with given dimensions
.expanded(flex:) Wraps in Expanded — must be inside Row/Column/Flex
.flexible(flex:, fit:) Wraps in Flexible — must be inside Row/Column/Flex
.intrinsicWidth(stepWidth:, stepHeight:) Sizes to intrinsic width
.intrinsicHeight() Sizes to intrinsic height
.aspectRatio(ratio) Enforces an aspect ratio
.fittedBox(fit:, alignment:) Scales child within parent
.constrainedBox(minWidth:, maxWidth:, minHeight:, maxHeight:) Applies box constraints
.unconstrained(constrainedAxis:, alignment:) Removes parent constraints
.limitedBox(maxWidth:, maxHeight:) Limits size in unbounded layouts
Icon(Icons.star)
    .frame(width: 100, height: 100)
    .expanded(flex: 2)
    .aspectRatio(16 / 9)

🎨 Padding — PaddingModifier #

Extension on Widget

Modifier Description
.padding(paddingStyle:, padding:, top:, bottom:, left:, right:, vertical:, horizontal:) Adds padding with flexible style options

Supports PaddingStyle.all, PaddingStyle.only, PaddingStyle.symmetric, and PaddingStyle.fromViewPadding.

Text("Hello").padding()                                          // default 8.0 all
Text("Hello").padding(paddingStyle: PaddingStyle.only, top: 16)  // top-only
Text("Hello").padding(paddingStyle: PaddingStyle.symmetric, vertical: 12, horizontal: 24)

🎯 Center — CenterModifier #

Extension on Widget

Modifier Description
.center() Wraps in Center widget
Text("Centered").center()

📍 Alignment — AlignmentModifier #

Extension on Widget

Modifier Description
.align(alignment) Wraps in Align with given alignment
.positioned(top:, bottom:, left:, right:, width:, height:) Wraps in Positioned for use inside Stack
.positionedFill(top:, bottom:, left:, right:) Fills a Stack with optional insets
.centerLeft() Aligns to center-left
.centerRight() Aligns to center-right
Text("Top Left").align(Alignment.topLeft)
widget.positioned(top: 10, left: 20)
widget.positionedFill()

👁️ Visibility — VisibilityModifier #

Extension on Widget

Modifier Description
.opacity(value) Sets opacity (0.0–1.0)
.visible(isVisible, maintainSize:, ...) Controls visibility with layout options
.offstage(offstage) Removes from layout without removing from tree
.ignorePointer(ignoring:) Lets pointer events pass through
.absorbPointer(absorbing:) Absorbs pointer events, blocking those below
Text("Faded").opacity(0.5)
widget.visible(showWidget, maintainSize: true)
button.ignorePointer(ignoring: isLoading)

🖼️ Container & Background — ContainerModifier #

Extension on Widget

Modifier Description
.backgroundColor(color) Adds a background color
.container(color:, decoration:, padding:, margin:, alignment:, width:, height:) Full Container wrapper
Text("Hello").backgroundColor(Colors.blue)
widget.container(padding: EdgeInsets.all(16), margin: EdgeInsets.all(8))

🌈 Decoration — DecorationModifier #

Extension on Widget

Modifier Description
.shadow(color:, blurRadius:, spreadRadius:, offset:, borderRadius:) Adds a box shadow
.border(color:, width:, style:, radius:) Adds a border
.gradient(gradient, borderRadius:) Applies a gradient background
.shape(boxShape, color:) Applies a box shape (circle, rectangle)
.decorated(BoxDecoration) Full decoration control
.foregroundDecoration(Decoration) Overlay decoration
widget.shadow(blurRadius: 10, offset: Offset(0, 4))
widget.border(color: Colors.grey, width: 2, radius: 12)
widget.gradient(LinearGradient(colors: [Colors.blue, Colors.purple]))
Image.asset('avatar.png').shape(BoxShape.circle)

🔄 Border Radius — RadiusModifier #

Extension on Widget

Modifier Description
.borderRadius(radius:, topLeft:, topRight:, bottomLeft:, bottomRight:) Clips with rounded corners
widget.borderRadius()                         // default 25
widget.borderRadius(radius: 16)               // uniform
widget.borderRadius(topLeft: 20, topRight: 20) // per-corner

✂️ Clip — ClipModifier #

Extension on Widget

Modifier Description
.clipOval(clipper:, clipBehavior:) Clips to oval/ellipse
.clipRect(clipper:, clipBehavior:) Clips to rectangle
.clipPath(clipper:, clipBehavior:) Clips to custom path
.clipCircle() Convenience for circular clip
.clipRoundedRect(radius:, borderRadius:, clipBehavior:) Clips to rounded rectangle
Image.network(url).clipCircle()
widget.clipRoundedRect(radius: 16)

🔀 Transform — TransformModifier #

Extension on Widget

Modifier Description
.rotate(angle:, alignment:, origin:) Rotates by radians
.rotateDegrees(degrees, alignment:, origin:) Rotates by degrees
.scale(all:, scaleX:, scaleY:, alignment:, origin:) Scales uniformly or per-axis
.translate(offset:, transformHitTests:) Translates position
.flip(flipX:, flipY:, alignment:) Mirrors horizontally/vertically
Icon(Icons.refresh).rotateDegrees(45)
widget.scale(all: 1.5)
Icon(Icons.arrow_back).flip(flipX: true)

📜 Scroll — ScrollModifier #

Extension on Widget

Modifier Description
.scrollable(direction:, reverse:, physics:, padding:, controller:) Wraps in SingleChildScrollView
.scrollbar(controller:, thumbVisibility:, thickness:, radius:) Adds a Scrollbar
Column(children: [...]).scrollable()
ListView(...).scrollbar(thumbVisibility: true)

🛡️ Safe Area — SafeAreaModifier #

Extension on Widget

Modifier Description
.respectSafeArea() Wraps in SafeArea
Image.asset('bg.png').respectSafeArea()

👆 Gestures — CombinedGestureModifier #

Extension on Widget

Modifier Description
.onGesture(onTap:, onDoubleTap:, onLongPress:, behavior:) Adds gesture detection
widget.onGesture(
    onTap: () => print("tapped"),
    onLongPress: () => print("long press"),
)

🎭 Material — MaterialModifier #

Extension on Widget

Modifier Description
.card(color:, elevation:, shape:, margin:, ...) Wraps in Card
.material(type:, elevation:, color:, shape:, borderRadius:, ...) Wraps in Material
.inkWell(onTap:, splashColor:, borderRadius:, ...) Adds Material ripple via InkWell
ListTile(title: Text("Item")).card(elevation: 4)
widget.inkWell(onTap: () => print("tap"), borderRadius: BorderRadius.circular(12))

✍️ Text Styling — TextModifiers #

Extension on Text

Modifier Description
.fontSize(size) Sets font size
.fontWeight(weight) Sets font weight
.fontFamily(family) Sets font family
.color(color) Sets text color
.italic() Makes text italic
.bold() Makes text bold
.align(textAlign) Sets text alignment
Text("Hello")
    .fontSize(24)
    .bold()
    .color(Colors.blue)
    .italic()
    .align(TextAlign.center)

🎨 Text Theme — TextThemeModifier #

Extension on Text

Apply theme-based text styles directly:

Modifier TextTheme Style
.displayLarge(context) textTheme.displayLarge
.displayMedium(context) textTheme.displayMedium
.displaySmall(context) textTheme.displaySmall
.headlineLarge(context) textTheme.headlineLarge
.headlineMedium(context) textTheme.headlineMedium
.headlineSmall(context) textTheme.headlineSmall
.titleLarge(context) textTheme.titleLarge
.titleMedium(context) textTheme.titleMedium
.titleSmall(context) textTheme.titleSmall
.bodyLarge(context) textTheme.bodyLarge
.bodyMedium(context) textTheme.bodyMedium
.bodySmall(context) textTheme.bodySmall
.labelLarge(context) textTheme.labelLarge
.labelMedium(context) textTheme.labelMedium
.labelSmall(context) textTheme.labelSmall
Text("Page Title").headlineLarge(context).bold()
Text("Body content").bodyMedium(context).color(Colors.grey)

🎬 Animation — AnimationModifier #

Extension on Widget

Modifier Description
.hero(tag:, ...) Wraps in Hero for shared element transitions
.animatedSwitcher(duration:, ...) Wraps in AnimatedSwitcher
.animatedOpacity(opacity:, duration:, curve:, ...) Animated opacity changes
.animatedScale(scale:, duration:, curve:, ...) Animated scale changes
.animatedSlide(offset:, duration:, curve:, ...) Animated position changes
.animatedRotation(turns:, duration:, curve:, ...) Animated rotation changes
.animatedContainer(duration:, padding:, decoration:, ...) Animated container properties
.animatedPadding(padding:, duration:, curve:, ...) Animated padding changes
Image.asset('photo.png').hero(tag: 'photo-1')

widget.animatedOpacity(
    opacity: isVisible ? 1.0 : 0.0,
    duration: Duration(milliseconds: 300),
    curve: Curves.easeInOut,
)

Icon(Icons.refresh).animatedRotation(turns: isLoading ? 1.0 : 0.0)

🧭 Navigation — NavigationModifier #

Extension on Widget

Modifier Description
.onTapNavigate(context, page:, fullscreenDialog:) Pushes a page on tap
.onTapPushNamed(context, routeName:, arguments:) Pushes a named route on tap
.showAsDialog(context, dialog:, ...) Shows a dialog on tap
.showAsBottomSheet(context, builder:, ...) Shows a modal bottom sheet on tap
.onTapPop(context, result:) Pops the current route on tap
ListTile(title: Text("Settings"))
    .onTapNavigate(context, page: SettingsPage())

Icon(Icons.info).showAsDialog(
    context,
    dialog: AlertDialog(title: Text("Info"), content: Text("Details")),
)

Icon(Icons.arrow_back).onTapPop(context)

🎭 Theme — ThemeModifier #

Extension on Widget

Modifier Description
.withTheme(ThemeData) Overrides theme for subtree
.overrideTheme((current) => ...) Copies and modifies current theme
widget.withTheme(ThemeData.dark())
widget.overrideTheme((theme) => theme.copyWith(primaryColor: Colors.purple))

🔲 Overlay & Stack — OverlayModifier #

Extension on Widget

Modifier Description
.overlay(child:, alignment:, fit:, ...) Places widget on top via Stack
.stackBackground(child:, alignment:, fit:, ...) Places widget behind via Stack
.badge(child:, backgroundColor:, size:, alignment:, ...) Adds a badge overlay
Image.asset('product.png')
    .overlay(child: Icon(Icons.favorite), alignment: Alignment.topRight)

Icon(Icons.shopping_cart)
    .badge(child: Text("3", style: TextStyle(color: Colors.white, fontSize: 10)))

❓ Conditional — ConditionalModifier #

Extension on Widget

Modifier Description
.applyIf(condition, modifier) Applies modifier only when condition is true
.applyUnless(condition, modifier) Applies modifier only when condition is false
.let(transform) Pipes widget through a transform function
.withBuilder((context, child) => ...) Builder with context access
.when(condition, ifTrue:, ifFalse:) Applies one of two modifiers
Text("Welcome")
    .applyIf(isLoggedIn, (w) => w.bold())
    .applyIf(isHighlighted, (w) => w.backgroundColor(Colors.yellow))
    .applyUnless(isEnabled, (w) => w.opacity(0.5))

widget.when(
    isDarkMode,
    ifTrue: (w) => w.backgroundColor(Colors.black),
    ifFalse: (w) => w.backgroundColor(Colors.white),
)

📋 List Extensions — GenericListViewBuilder #

Extension on List<T>

Modifier Description
.asListViewBuilder(itemBuilder:, ...) Converts list to ListView.builder
.asSeparatedListView(itemBuilder:, separatorBuilder:, ...) Converts list to ListView.separated
final items = ["Apple", "Banana", "Cherry"];

items.asListViewBuilder(
    itemBuilder: (context, index, item) => ListTile(title: Text(item)),
)

items.asSeparatedListView(
    itemBuilder: (context, index, item) => ListTile(title: Text(item)),
    separatorBuilder: (context, index) => Divider(),
)

🔲 Grid Extensions — GenericGridViewBuilder #

Extension on List<T>

Modifier Description
.asGridView(crossAxisCount:, itemBuilder:, ...) Fixed column count grid
.asGridViewExtent(maxCrossAxisExtent:, itemBuilder:, ...) Max extent grid
items.asGridView(
    crossAxisCount: 2,
    mainAxisSpacing: 8,
    crossAxisSpacing: 8,
    itemBuilder: (context, index, item) => Card(child: Center(child: Text(item))),
)

🖼️ Image Modifiers — ImageModifier #

Extension on Image

Modifier Description
.resizable(fit:) Sets the BoxFit
.colorBlend(color, mode) Applies color blend
.imageSize(width:, height:) Sets image dimensions
Image.asset('photo.png')
    .resizable(fit: BoxFit.cover)
    .imageSize(width: 200, height: 200)
    .colorBlend(Colors.blue, BlendMode.srcIn)

📱 Responsive — ResponsiveModifier #

Extension on Widget

Modifier Description
.responsive(mobile:, tablet:, desktop:, ...) Breakpoint-based widget switching
.onOrientation(portrait:, landscape:) Orientation-based widget switching
.responsivePadding(fraction:, min:, max:) Screen-width-based padding
.maxWidth(maxWidth) Centers content with max width constraint
widget.responsive(
    mobile: MobileLayout(),
    tablet: TabletLayout(),
    desktop: DesktopLayout(),
)

widget.maxWidth(800)  // center-constrained content
widget.responsivePadding(fraction: 0.05)

♿ Semantics & Accessibility — SemanticsModifier #

Extension on Widget

Modifier Description
.tooltip(message, ...) Adds a tooltip
.semanticLabel(label, ...) Adds a semantic label for screen readers
.excludeSemantics(excluding:) Hides from accessibility tree
.mergeSemantics() Merges child semantics into one node
IconButton(icon: Icon(Icons.info), onPressed: () {})
    .tooltip('More information')
Image.asset('decoration.png').excludeSemantics()

⌨️ Focus & Keyboard — FocusModifier #

Extension on Widget

Modifier Description
.dismissKeyboardOnTap() Dismisses keyboard on tap
.autoFocus(autofocus:) Sets autofocus
.onFocusChange(callback) Focus change listener
.focusTraversalGroup(policy:) Groups focus traversal
Scaffold(body: form).dismissKeyboardOnTap()
TextField().autoFocus()

📜 Sliver Extensions #

Extensions on Widget and List<T>

Modifier Description
.asSliver() Converts to SliverToBoxAdapter
.sliverPadding(padding) Adds padding to a sliver
.asSliverFillRemaining(...) Fills remaining viewport space
.asSliverList(itemBuilder:) Converts list to SliverList
.asSliverGrid(crossAxisCount:, itemBuilder:, ...) Converts list to SliverGrid
CustomScrollView(
  slivers: [
    Text("Header").padding().asSliver(),
    items.asSliverList(
      itemBuilder: (context, index, item) => ListTile(title: Text(item)),
    ),
    Center(child: Text("End")).asSliverFillRemaining(hasScrollBody: false),
  ],
)

🛡️ Debug Assertions #

All modifiers include detailed assertions that catch invalid parameters during development:

// ✅ These work fine
widget.opacity(0.5)
widget.frame(width: 100, height: 100)
widget.constrainedBox(minWidth: 50, maxWidth: 200)

// ❌ These throw helpful assertion errors in debug mode
widget.opacity(1.5)
// → 'Opacity must be between 0.0 and 1.0, got 1.5'

widget.frame(width: -10)
// → 'Frame width must be non-negative, got -10.0.'

widget.constrainedBox(minWidth: 200, maxWidth: 50)
// → 'minWidth (200.0) must be less than or equal to maxWidth (50.0).'

widget.flip()
// → 'At least one of "flipX" or "flipY" must be true.'

🤝 Contributing #

Contributions are welcome! Feel free to open issues or submit pull requests on GitHub.


📄 License #

This project is licensed under the MIT License — see the LICENSE file for details.

4
likes
140
points
100
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

For SwiftUi Developers.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter

More

Packages that depend on swiftify