/// Responsive layout utilities for optimal performance across devices /// /// Features: /// - Breakpoint-based layouts /// - Adaptive grid columns /// - Performance-optimized responsive widgets /// - Device-specific optimizations import 'package:flutter/material.dart'; import '../constants/performance_constants.dart'; /// Responsive helper for device-specific optimizations class ResponsiveHelper { /// Check if device is mobile static bool isMobile(BuildContext context) { return MediaQuery.of(context).size.width < PerformanceConstants.mobileBreakpoint; } /// Check if device is tablet static bool isTablet(BuildContext context) { final width = MediaQuery.of(context).size.width; return width >= PerformanceConstants.mobileBreakpoint && width < PerformanceConstants.desktopBreakpoint; } /// Check if device is desktop static bool isDesktop(BuildContext context) { return MediaQuery.of(context).size.width >= PerformanceConstants.desktopBreakpoint; } /// Get appropriate grid column count static int getGridColumns(BuildContext context) { final width = MediaQuery.of(context).size.width; return PerformanceConstants.getGridColumnCount(width); } /// Get appropriate cache extent static double getCacheExtent(BuildContext context) { final height = MediaQuery.of(context).size.height; return PerformanceConstants.getCacheExtent(height); } /// Check if high performance mode should be enabled static bool shouldUseHighPerformance(BuildContext context) { final width = MediaQuery.of(context).size.width; return PerformanceConstants.shouldUseHighPerformanceMode(width); } /// Get value based on screen size static T getValue( BuildContext context, { required T mobile, T? tablet, T? desktop, }) { if (isDesktop(context) && desktop != null) return desktop; if (isTablet(context) && tablet != null) return tablet; return mobile; } /// Get responsive padding static EdgeInsets getResponsivePadding(BuildContext context) { if (isDesktop(context)) { return const EdgeInsets.all(24); } else if (isTablet(context)) { return const EdgeInsets.all(16); } else { return const EdgeInsets.all(12); } } /// Get responsive spacing static double getSpacing(BuildContext context) { if (isDesktop(context)) return 16; if (isTablet(context)) return 12; return 8; } } /// Responsive layout builder with performance optimization class ResponsiveLayout extends StatelessWidget { final Widget mobile; final Widget? tablet; final Widget? desktop; const ResponsiveLayout({ super.key, required this.mobile, this.tablet, this.desktop, }); @override Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { if (constraints.maxWidth >= PerformanceConstants.desktopBreakpoint) { return desktop ?? tablet ?? mobile; } else if (constraints.maxWidth >= PerformanceConstants.mobileBreakpoint) { return tablet ?? mobile; } else { return mobile; } }, ); } } /// Responsive value builder class ResponsiveValue extends StatelessWidget { final T mobile; final T? tablet; final T? desktop; final Widget Function(BuildContext context, T value) builder; const ResponsiveValue({ super.key, required this.mobile, this.tablet, this.desktop, required this.builder, }); @override Widget build(BuildContext context) { final value = ResponsiveHelper.getValue( context, mobile: mobile, tablet: tablet, desktop: desktop, ); return builder(context, value); } } /// Adaptive grid configuration class AdaptiveGridConfig { final int crossAxisCount; final double childAspectRatio; final double spacing; final double cacheExtent; const AdaptiveGridConfig({ required this.crossAxisCount, required this.childAspectRatio, required this.spacing, required this.cacheExtent, }); factory AdaptiveGridConfig.fromContext( BuildContext context, { GridType type = GridType.products, }) { final width = MediaQuery.of(context).size.width; final height = MediaQuery.of(context).size.height; return AdaptiveGridConfig( crossAxisCount: PerformanceConstants.getGridColumnCount(width), childAspectRatio: type == GridType.products ? PerformanceConstants.productCardAspectRatio : PerformanceConstants.categoryCardAspectRatio, spacing: PerformanceConstants.gridSpacing, cacheExtent: PerformanceConstants.getCacheExtent(height), ); } } enum GridType { products, categories, } /// Responsive grid view that adapts to screen size class AdaptiveGridView extends StatelessWidget { final List items; final Widget Function(BuildContext context, T item, int index) itemBuilder; final GridType type; final ScrollController? scrollController; final EdgeInsets? padding; const AdaptiveGridView({ super.key, required this.items, required this.itemBuilder, this.type = GridType.products, this.scrollController, this.padding, }); @override Widget build(BuildContext context) { final config = AdaptiveGridConfig.fromContext(context, type: type); return GridView.builder( controller: scrollController, padding: padding ?? ResponsiveHelper.getResponsivePadding(context), physics: const BouncingScrollPhysics( parent: AlwaysScrollableScrollPhysics(), ), cacheExtent: config.cacheExtent, itemCount: items.length, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: config.crossAxisCount, crossAxisSpacing: config.spacing, mainAxisSpacing: config.spacing, childAspectRatio: config.childAspectRatio, ), itemBuilder: (context, index) { final item = items[index]; return RepaintBoundary( key: ValueKey('adaptive_grid_item_$index'), child: itemBuilder(context, item, index), ); }, ); } } /// Responsive container with adaptive sizing class ResponsiveContainer extends StatelessWidget { final Widget child; final double? mobileWidth; final double? tabletWidth; final double? desktopWidth; const ResponsiveContainer({ super.key, required this.child, this.mobileWidth, this.tabletWidth, this.desktopWidth, }); @override Widget build(BuildContext context) { final width = ResponsiveHelper.getValue( context, mobile: mobileWidth, tablet: tabletWidth, desktop: desktopWidth, ); return Container( width: width, child: child, ); } } /// Extension for easier responsive values extension ResponsiveContextExtension on BuildContext { bool get isMobile => ResponsiveHelper.isMobile(this); bool get isTablet => ResponsiveHelper.isTablet(this); bool get isDesktop => ResponsiveHelper.isDesktop(this); int get gridColumns => ResponsiveHelper.getGridColumns(this); double get cacheExtent => ResponsiveHelper.getCacheExtent(this); double get spacing => ResponsiveHelper.getSpacing(this); EdgeInsets get responsivePadding => ResponsiveHelper.getResponsivePadding(this); T responsive({ required T mobile, T? tablet, T? desktop, }) { return ResponsiveHelper.getValue( this, mobile: mobile, tablet: tablet, desktop: desktop, ); } }