😇
FlutterでSwiftUIのような class modifier再現できるのか?
Tips💡
結論できるしかしあっているのか...
実験なので、これは使い道あるのか???
昔からある方法でできるらしい?
extension WidgetModifier on Widget {
Widget padding(double value) {
return Padding(
padding: EdgeInsets.all(value),
child: this,
);
}
Widget background(Color color) {
return Container(
color: color,
child: this,
);
}
Widget alignment(Alignment alignment) {
return Align(
alignment: alignment,
child: this,
);
}
}
思いつきで書いたコード
// enum & typedef
enum BoxStyle {
rounded,
shadow,
}
typedef ApplyBoxStyle = Widget Function(Widget);
extension WidgetModifiers on Widget {
Widget applyStyle(BoxStyle style) {
switch (style) {
case BoxStyle.rounded:
return borderRadius(10.0);
case BoxStyle.shadow:
return boxShadow();
}
}
Widget borderRadius(double radius) {
return ClipRRect(
borderRadius: BorderRadius.circular(radius),
child: this,
);
}
Widget boxShadow() {
return Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
spreadRadius: 1,
blurRadius: 10,
),
],
),
child: this,
);
}
}
Dart3.0のextetion typeを使うと、on
がいらないらしい?
extension type ClassModifier(Widget widget) {
Widget padding(double value) {
return Padding(
padding: EdgeInsets.all(value),
child: widget,
);
}
Widget background(Color color) {
return Container(
color: color,
child: widget,
);
}
Widget alignment(Alignment alignment) {
return Align(
alignment: alignment,
child: widget,
);
}
}
使うときは、.
で繋げて使う。 SwiftUIぽくはなってはいる?
class HomePage extends StatelessWidget {
const HomePage({super.key});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home Page'),
),
body: Center(
child: Column(
children: [
const Text('Hello, World!').padding(16).
background(Colors.blue).
alignment(Alignment.bottomLeft),
// WidgetModifiersを使ってスタイルを適用
const Text('enum typedef').
padding(16).
applyStyle(BoxStyle.rounded),
// ClassModifierを使ってスタイルを適用
const Text('extension type').padding(16).
background(Colors.red).
alignment(Alignment.topRight),
],
),
),
);
}
}
SwiftUIだとこのように書く。alignmentは適用されていないけど。
import SwiftUI
struct ShopModalView: View {
var body: some View {
VStack {
Text("ffffff")
.padding()
.background(Color.red)
.frame(alignment: .topLeading)
Text("ffffff")
.padding()
.background(Color.blue)
.frame(alignment: .topTrailing)
Text("ffffff")
.padding()
.background(Color.green)
.frame(alignment: .bottomLeading)
}
}
}
#Preview {
ShopModalView()
}
感想
ネットで、FlutterでもSwiftUIのような、class modifierを真似した書き方をする人がいた。これでスタイルを適用すると、「何かメリットがあるのか?」わからないですね。コンポーネントを作るか、スタイルをドットで繋げて使えるようにした方が良いのか、探究してみないとわからない。
Discussion