📜 Curtains

Wrap a scrollable with scrim 📜 Curtains while not at the start or end, alluding to unrevealed content.

 

📖 Reference

Peruse the 📜 Curtains pub.dev documention for a full breakdown.

  • Advanced usage with 📜 Curtains.fancy
  • Animated usage with 📜 Curtains.regal
  • This is simple package to use, but it is also a package that was easy to implement.
    • It is, however, overly documented so that any beginners may learn from its code.
    • Utilizes a simple NotificationListener in lieu of ScrollController, which were both elusive when starting Flutter.

🕴 Elevation

The Elevation paradigm is handled by 👥 package:shadows

 

🧫 Examples

See demonstrations of this Flutter package:

Simple 📜 Curtains

final curtains = Curtains(
  child: ListView(
    children: List.generate(
      25,
      (i) => ListTile(title: Text('ListTile #: ${i+1}')),
    ),
  ),
  elevation: 24.0 // optional, defaults to `9.0`
  // Optional color; will maintain Material elevation opacities.✝
  color: Colors.red
);

It's that easy!

👥 Shadows - See: Elevation.asBoxShadows

 

Fancy 📜 Curtains

final fancy = Curtains.fancy(
  /// 🕴 Default constructor 📜 [Curtains] employs `Elevation.asBoxDecoration` to
  /// render its decorations; but feel free to use these static methods, too,
  /// if you opt for 👥 [package:shadows].
  startCurtain: const BoxDecoration(. . .) // Elevation.asBoxDecoration(12.0), // 🕴
  endCurtain: BoxDecoration(boxShadow: Elevation.asBoxShadows(12.0)), // 🕴
  child: ListView(
    children: List.generate(
      25,
      (i) => ListTile(title: Text('ListTile #${i+1}')),
    ),
  ),
);

It's similarly easy!

 

Regal 📜 Curtains

This instance of regal 📜 Curtains has custom, animated BoxDecorations as well as sensitivity at the start and end.

final regal = Curtains.regal(
  startCurtain: buildCurtain(),
  endCurtain: buildCurtain(isStart: false),
  // Provide `spread` to [Curtains] for decoration support beyond [BoxShadow]s.
  // (Gives "girth" to individual [_Curtain] containers; otherwise `0`.)
  spread: 50.0,
  // ⚖ `start` appears once scrolled `350` px beyond start
  // ⚖ `end` appears once scrolled `175` px beyond end
  sensitivity: const [350.0, 175.0], // ⚖
  // Regal 📜 Curtains are animated:
  duration: const Duration(milliseconds: 600),
  curve: Curves.fastOutSlowIn,
  // ↔ If wrapping a horizontal scrollable, initialize here, too:
  scrollDirection: Axis.horizontal, // ↔
  child: ListView(
    scrollDirection: Axis.horizontal, // ↔
    itemExtent: 100.0,
    children: List.generate(
      25,
      (i) => ListTile(title: Text('ListTile #${i+1}')),
    ),
  ),
);

BoxDecoration buildCurtain({bool isStart = true}) => BoxDecoration(
  gradient: LinearGradient(
    colors: [Colors.green[400]!, Colors.green[400]!.withOpacity(0)],
    begin: (isStart) ? Alignment.centerLeft : Alignment.centerRight,
    end: (isStart) ? Alignment.centerRight : Alignment.centerLeft,
  ),
  boxShadow: const [
    BoxShadow(color: Color(0x22FF0000), spreadRadius: 0.0, blurRadius: 5.0),
    BoxShadow(color: Color(0x66FF0000), spreadRadius: 10.0, blurRadius: 30.0),
    BoxShadow(color: Color(0x22FF0000), spreadRadius: 60.0, blurRadius: 150.0),
  ],
);

But look here, and we can get pretty complex and creative.

Notice the spread initialization for gradient support in the _Curtains.

 

🐞 Bugs

One known bug:

  1. Even with Curtains.spread set non-negligibly, BoxDecoration.backgroundBlendMode does not work correctly.

Libraries

curtains
📜 Curtains Library [...]