Skip to content

Instantly share code, notes, and snippets.

@Pregum
Last active February 15, 2024 23:41
Show Gist options
  • Save Pregum/8c03b099d5d121378ef5290c6a2b73cf to your computer and use it in GitHub Desktop.
Save Pregum/8c03b099d5d121378ef5290c6a2b73cf to your computer and use it in GitHub Desktop.
platform_flutter_widgetsを真似た自作ウィジェット
import 'package:flutter/cupertino.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
class PlatformListView extends HookWidget {
final List<Widget> children;
final Widget header;
final Color? backgroundColor;
final bool hasLeading;
final EdgeInsetsGeometry? margin;
final EdgeInsetsGeometry? padding;
const PlatformListView({
super.key,
this.children = const [],
this.header = const SizedBox.shrink(),
this.backgroundColor,
this.hasLeading = true,
this.margin,
this.padding,
});
@override
Widget build(BuildContext context) {
final platformTarget = platform(context);
return switch (platformTarget) {
PlatformTarget.iOS => _buildIos(context),
PlatformTarget.android => _buildAndroid(context),
(_) => _buildAndroid(context),
};
}
Widget _buildIos(BuildContext context) {
return CupertinoListSection.insetGrouped(
margin: margin,
hasLeading: hasLeading,
dividerMargin: 14.0,
additionalDividerMargin: hasLeading ? null : 0.0,
backgroundColor:
backgroundColor ?? CupertinoColors.systemGroupedBackground,
header: header,
children: [
...children,
],
);
}
Widget _buildAndroid(BuildContext context) {
return ListView(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
padding: margin,
children: [
Container(
color: backgroundColor,
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
child: header,
),
...children,
],
);
}
}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
class PlatformSliverAppBar extends StatelessWidget {
final Widget? title;
/// Cupertino style only use.
final Widget? largeTitle;
/// Material style only use.
final bool floating;
/// Material style only use.
final bool pinned;
final Widget? leading;
final Widget? trailing;
// Cupertino style only use.
final bool alwaysShowMiddle;
const PlatformSliverAppBar({
super.key,
this.title,
this.largeTitle,
this.floating = false,
this.pinned = false,
this.leading,
this.trailing,
this.alwaysShowMiddle = true,
});
@override
Widget build(BuildContext context) {
final platformTarget = platform(context);
return switch (platformTarget) {
PlatformTarget.iOS => _buildIos(context),
PlatformTarget.android => _buildAndroid(context),
(_) => _buildAndroid(context),
};
}
Widget _buildIos(BuildContext context) {
return CupertinoSliverNavigationBar(
largeTitle: largeTitle ?? title,
alwaysShowMiddle: alwaysShowMiddle,
middle: title,
leading: leading,
trailing: trailing,
);
}
Widget _buildAndroid(BuildContext context) {
final filteredTrailing = [trailing].whereType<Widget>().toList();
return SliverAppBar(
title: title,
leading: leading,
actions: filteredTrailing,
floating: floating,
pinned: pinned,
);
}
}
@Pregum
Copy link
Author

Pregum commented Feb 15, 2024

プルリクを出す際には以下の2点を直すつもり

  • paddingなどのパラメタはMaterialListViewDataとCupertinoListSectionDataを経由して渡すように修正
  • ドキュメントの整備
  • flutter_hooksを削除してStatelessWidgetとして作成
  • iOSとAndroid以外のPlatformの場合は他のPlatform Widgetに倣って、UnsupportedErrorを throwする

@Pregum
Copy link
Author

Pregum commented Feb 15, 2024

ウィジェット名は以下のプラグインに寄せています。
https://pub.dev/documentation/flutter_platform_widgets/latest/

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