Skip to content

Instantly share code, notes, and snippets.

@internetova
Created March 29, 2023 11:27
Show Gist options
  • Save internetova/1b194d05fe33ef176570055a3127ef32 to your computer and use it in GitHub Desktop.
Save internetova/1b194d05fe33ef176570055a3127ef32 to your computer and use it in GitHub Desktop.
AdaptiveContainer
import 'package:flutter/material.dart';
class CustomAdaptivePage extends StatelessWidget {
const CustomAdaptivePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: const [
AdaptiveContainer.adaptive(),
],
),
),
);
}
}
class AdaptiveContainer extends StatelessWidget with AdaptiveWidget{
final PlatformWidgetType _widgetType;
const AdaptiveContainer({Key? key})
: _widgetType = PlatformWidgetType.material,
super(key: key);
const AdaptiveContainer.adaptive({Key? key})
: _widgetType = PlatformWidgetType.adaptive,
super(key: key);
@override
Widget build(BuildContext context) {
return buildPlatformWidget(context);
}
@override
PlatformWidgetType get widgetType => _widgetType;
@override
WidgetBuilder get widgetBuilderAndroid => (_) => const _MaterialContainer();
@override
WidgetBuilder get widgetBuilderCupertino => (_) => const _CupertinoContainer();
}
class _MaterialContainer extends StatelessWidget {
const _MaterialContainer({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const SizedBox(
width: 300,
height: 300,
child: DecoratedBox(
decoration: BoxDecoration(
color: Colors.green,
),
child: Center(
child: Text(
'MaterialContainer',
style: TextStyle(
color: Colors.white,
fontSize: 24,
),
),
),
),
);
}
}
class _CupertinoContainer extends StatelessWidget {
const _CupertinoContainer({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const SizedBox(
width: 300,
height: 300,
child: DecoratedBox(
decoration: BoxDecoration(
color: Colors.redAccent,
shape: BoxShape.circle,
),
child: Center(
child: Text(
'CupertinoContainer',
style: TextStyle(
color: Colors.white,
fontSize: 24,
),
),
),
),
);
}
}
/// По такому принципу сделана реализация виджетов с адаптивным конструктором
/// только для каждого виджета свой enum
/// enum _SwitchType { material, adaptive }
/// enum _ActivityIndicatorType { material, adaptive }
enum PlatformWidgetType { material, adaptive }
mixin AdaptiveWidget on Widget {
WidgetBuilder get widgetBuilderAndroid;
WidgetBuilder get widgetBuilderCupertino;
PlatformWidgetType get widgetType;
Widget buildPlatformWidget(BuildContext context) {
switch (widgetType) {
case PlatformWidgetType.adaptive:
{
final ThemeData theme = Theme.of(context);
switch (theme.platform) {
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
return widgetBuilderAndroid(context);
case TargetPlatform.iOS:
case TargetPlatform.macOS:
return widgetBuilderCupertino(context);
}
}
case PlatformWidgetType.material:
default:
return widgetBuilderAndroid(context);
}
}
}
@internetova
Copy link
Author

Можно добавить билдеры под остальные платформы, но оно надо? 🧐
WidgetBuilder? get widgetBuilderLinux;

@dshevchenkoo
Copy link

dshevchenkoo commented Mar 29, 2023

у меня гист в dart.pad не запускается

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const Scaffold(
        body: AdaptiveContainer.adaptive(),
      ),
    );
  }
}

class AdaptiveContainer extends StatelessWidget with AdaptiveWidget{
  final PlatformWidgetType _widgetType;

  const AdaptiveContainer({Key? key})
      : _widgetType = PlatformWidgetType.material,
        super(key: key);

  const AdaptiveContainer.adaptive({Key? key})
      : _widgetType = PlatformWidgetType.adaptive,
        super(key: key);

  @override
  Widget build(BuildContext context) {
    return buildPlatformWidget(context);
  }

  @override
  PlatformWidgetType get widgetType => _widgetType;

  @override
  WidgetBuilder get widgetBuilderAndroid => (_) => const _MaterialContainer();

  @override
  WidgetBuilder get widgetBuilderCupertino => (_) => const _CupertinoContainer();
}

class _MaterialContainer extends StatelessWidget {
  const _MaterialContainer({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const SizedBox(
      width: 300,
      height: 300,
      child: DecoratedBox(
        decoration: BoxDecoration(
          color: Colors.green,
        ),
        child: Center(
          child: Text(
            'MaterialContainer',
            style: TextStyle(
              color: Colors.white,
              fontSize: 24,
            ),
          ),
        ),
      ),
    );
  }
}

class _CupertinoContainer extends StatelessWidget {
  const _CupertinoContainer({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const SizedBox(
      width: 300,
      height: 300,
      child: DecoratedBox(
        decoration: BoxDecoration(
          color: Colors.redAccent,
          shape: BoxShape.circle,
        ),
        child: Center(
          child: Text(
            'CupertinoContainer',
            style: TextStyle(
              color: Colors.white,
              fontSize: 24,
            ),
          ),
        ),
      ),
    );
  }
}

/// По такому принципу сделана реализация виджетов с адаптивным конструктором
/// только для каждого виджета свой enum
/// enum _SwitchType { material, adaptive }
/// enum _ActivityIndicatorType { material, adaptive }
enum PlatformWidgetType { material, adaptive }

mixin AdaptiveWidget on Widget {
  WidgetBuilder get widgetBuilderAndroid;

  WidgetBuilder get widgetBuilderCupertino;

  PlatformWidgetType get widgetType;

  Widget buildPlatformWidget(BuildContext context) {
    switch (widgetType) {
      case PlatformWidgetType.adaptive:
        {
          final ThemeData theme = Theme.of(context);
          switch (theme.platform) {
            case TargetPlatform.android:
            case TargetPlatform.fuchsia:
            case TargetPlatform.linux:
            case TargetPlatform.windows:
              return widgetBuilderAndroid(context);
            case TargetPlatform.iOS:
            case TargetPlatform.macOS:
              return widgetBuilderCupertino(context);
          }
        }
      case PlatformWidgetType.material:
      default:
        return widgetBuilderAndroid(context);
    }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment