showWithCustomHeaderWidget static method

Future<void> showWithCustomHeaderWidget({
  1. required BuildContext context,
  2. required Widget headerBuilder(
    1. BuildContext
    ),
  3. required Widget contentBuilder(
    1. BuildContext
    ),
  4. List<CNSheetDetent> detents = const [CNSheetDetent.large],
  5. bool prefersGrabberVisible = true,
  6. bool isModal = false,
  7. bool prefersEdgeAttachedInCompactHeight = false,
  8. bool widthFollowsPreferredContentSizeWhenEdgeAttached = false,
  9. double? preferredCornerRadius,
  10. double? headerHeight,
  11. Color? headerBackgroundColor,
  12. bool showHeaderDivider = true,
  13. Color? headerDividerColor,
  14. VoidCallback? onClose,
})

Shows a native sheet with custom Flutter widget header and content using UiKitView.

Similar to showWithCustomHeaderUiKitView but allows the header (title/subtitle) to be custom Flutter widgets instead of just strings. This gives you full flexibility to style the header while maintaining the native iOS sheet presentation.

Features:

  • Native UISheetPresentationController (real iOS sheet)
  • Custom Flutter widget header (title as a widget!)
  • Custom Flutter widgets as content via UiKitView
  • Non-modal behavior (interact with background)
  • Native feel and animations

Example:

await CNNativeSheet.showWithCustomHeaderWidget(
  context: context,
  headerBuilder: (context) => Column(
    children: [
      Text('Format', style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600)),
      Text('Text formatting options', style: TextStyle(fontSize: 13, color: Colors.grey)),
    ],
  ),
  contentBuilder: (context) => Column(
    children: [
      Row(
        children: [
          IconButton(icon: Icon(CupertinoIcons.bold), onPressed: () {}),
          IconButton(icon: Icon(CupertinoIcons.italic), onPressed: () {}),
        ],
      ),
    ],
  ),
  detents: [CNSheetDetent.custom(300)],
  isModal: false,
);

Implementation

static Future<void> showWithCustomHeaderWidget({
  required BuildContext context,
  required Widget Function(BuildContext) headerBuilder,
  required Widget Function(BuildContext) contentBuilder,
  List<CNSheetDetent> detents = const [CNSheetDetent.large],
  bool prefersGrabberVisible = true,
  bool isModal = false,
  bool prefersEdgeAttachedInCompactHeight = false,
  bool widthFollowsPreferredContentSizeWhenEdgeAttached = false,
  double? preferredCornerRadius,
  double? headerHeight,
  Color? headerBackgroundColor,
  bool showHeaderDivider = true,
  Color? headerDividerColor,
  VoidCallback? onClose,
}) async {
  if (isModal) {
    // For modal sheets, use CupertinoModalPopupRoute
    await Navigator.of(context).push(
      CupertinoModalPopupRoute(
        builder: (context) => _NativeSheetWithCustomWidgetHeader(
          headerBuilder: headerBuilder,
          contentBuilder: contentBuilder,
          detents: detents,
          prefersGrabberVisible: prefersGrabberVisible,
          isModal: isModal,
          prefersEdgeAttachedInCompactHeight:
              prefersEdgeAttachedInCompactHeight,
          widthFollowsPreferredContentSizeWhenEdgeAttached:
              widthFollowsPreferredContentSizeWhenEdgeAttached,
          preferredCornerRadius: preferredCornerRadius,
          headerHeight: headerHeight,
          headerBackgroundColor: headerBackgroundColor,
          showHeaderDivider: showHeaderDivider,
          headerDividerColor: headerDividerColor,
          onClose: onClose,
        ),
        barrierDismissible: false,
        barrierColor: CupertinoColors.black.withOpacity(0.4),
      ),
    );
  } else {
    // For non-modal sheets, use Overlay to allow background interaction
    final overlay = Overlay.of(context);
    late OverlayEntry overlayEntry;

    overlayEntry = OverlayEntry(
      builder: (context) => _NativeSheetWithCustomWidgetHeader(
        headerBuilder: headerBuilder,
        contentBuilder: contentBuilder,
        detents: detents,
        prefersGrabberVisible: prefersGrabberVisible,
        isModal: isModal,
        prefersEdgeAttachedInCompactHeight:
            prefersEdgeAttachedInCompactHeight,
        widthFollowsPreferredContentSizeWhenEdgeAttached:
            widthFollowsPreferredContentSizeWhenEdgeAttached,
        preferredCornerRadius: preferredCornerRadius,
        headerHeight: headerHeight,
        headerBackgroundColor: headerBackgroundColor,
        showHeaderDivider: showHeaderDivider,
        headerDividerColor: headerDividerColor,
        onClose: () {
          overlayEntry.remove();
          onClose?.call();
        },
      ),
    );

    overlay.insert(overlayEntry);
  }
}