import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; class CustomNotification { static const MethodChannel _channel = MethodChannel('custom_notifications'); static Future show( Widget widget, { Duration duration = const Duration(seconds: 2), List? buttons, }) async { final imageBytes = await _widgetToImage(widget); if (imageBytes != null) { await _channel.invokeMethod('showNotification', { 'image': imageBytes, 'buttons': buttons?.map((b) => b.toMap()).toList(), }); } } static Future _widgetToImage(Widget widget) async { final renderRepaintBoundary = RenderRepaintBoundary(); final pipelineOwner = PipelineOwner(); final renderView = RenderView( child: renderRepaintBoundary, configuration: ViewConfiguration(size: const Size(300, 100)), view: WidgetsBinding.instance.renderViews.first.flutterView, ); pipelineOwner.rootNode = renderView; final buildOwner = BuildOwner(focusManager: FocusManager()); final renderObjectToWidgetAdapter = RenderObjectToWidgetAdapter( container: renderRepaintBoundary, child: Directionality( textDirection: TextDirection.ltr, child: widget, ), ); renderObjectToWidgetAdapter.attachToRenderTree(buildOwner); buildOwner.buildScope(renderRepaintBoundary); buildOwner.finalizeTree(); pipelineOwner.flushLayout(); pipelineOwner.flushCompositingBits(); pipelineOwner.flushPaint(); final image = await renderRepaintBoundary.toImage(); final byteData = await image.toByteData(format: ui.ImageByteFormat.png); return byteData?.buffer.asUint8List(); } } class NotificationButton { final String title; final String action; NotificationButton({required this.title, required this.action}); Map toMap() => {'title': title, 'action': action}; }