styled_widget은 Dart 2.7.0 부터 소개된 extension method 기능을 활용해 메서드로 flutter의 위젯 트리를 간단하게 만들어주는 라이브러리다. flutter 개발이 손쉬워진다.
예제
- styled_component를 활용한 코드 예제
Icon(OMIcons.home, color: Colors.white)
.padding(all: 10)
.decorated(color: Color(0xff7AC1E7), shape: BoxShape.circle)
.padding(all: 15)
.decorated(color: Color(0xffE8F2F7), shape: BoxShape.circle)
.padding(all: 20)
.card(
elevation: 10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
)
.alignment(Alignment.center)
.backgroundColor(Color(0xffEBECF1));
- flutter raw 코드 예제
DecoratedBox(
decoration: BoxDecoration(
color: Color(0xffEBECF1),
),
child: Align(
alignment: Alignment.center,
child: Card(
elevation: 10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: Padding(
padding: EdgeInsets.all(20),
child: DecoratedBox(
decoration: BoxDecoration(
color: Color(0xffE8F2F7),
shape: BoxShape.circle,
),
child: Padding(
padding: EdgeInsets.all(15),
child: DecoratedBox(
decoration: BoxDecoration(
color: Color(0xff7AC1E7),
shape: BoxShape.circle,
),
child: Padding(
padding: EdgeInsets.all(10),
child: Icon(
OMIcons.home,
color: Colors.white,
),
),
),
),
),
),
),
),
);
flutter 코드만 쓰는 것과 비교했을 때 크게 간단해지는 것을 알 수 있다.
준비
- pubspec.yaml
dependencies:
flutter:
sdk: flutter
styled_widget: ^0.3.1
데모
import 'package:flutter/material.dart';
import 'package:styled_widget/styled_widget.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: Scaffold(
body: SafeArea(
child: _UserPage(),
),
),
);
}
}
class _UserPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Styled.widget(
child: Column(
children: [
Text(
'User settings',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 32),
).alignment(Alignment.center).padding(bottom: 20),
_UserCard(),
_ActionsRow(),
_Settings(),
],
)
.padding(vertical: 30, horizontal: 20)
.constrained(minHeight: MediaQuery.of(context).size.height - (2 * 30))
.scrollable(),
);
}
}
class _UserCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildUserRow(),
_buildUserStats(),
],
)
.padding(horizontal: 20, vertical: 10)
.decorated(
color: Color(0xff3977ff),
borderRadius: BorderRadius.circular(20),
)
.elevation(5,
shadowColor: Color(0xff3977ff),
borderRadius: BorderRadius.circular(20))
.height(175)
.alignment(Alignment.center);
}
Widget _buildUserRow() {
return Row(
children: [
Icon(Icons.account_circle)
.decorated(
color: Colors.white, borderRadius: BorderRadius.circular(30))
.constrained(height: 50, width: 50)
.padding(right: 10),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Rein Gundersen Bentdal',
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold,
),
).padding(bottom: 5),
Text(
'Creative builder',
style: TextStyle(
color: Colors.white.withOpacity(0.6),
fontSize: 12,
),
),
],
),
],
);
}
Widget _buildUserStats() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildUserStatsItem('846', 'Collect'),
_buildUserStatsItem('51', 'Attention'),
_buildUserStatsItem('267', 'Track'),
_buildUserStatsItem('39', 'Coupons'),
],
).padding(vertical: 10);
}
Widget _buildUserStatsItem(String value, String text) => Column(
children: [
Text(value, style: TextStyle(fontSize: 20, color: Colors.white)),
Text(text).textColor(Colors.white.withOpacity(0.6)).fontSize(12),
],
);
}
class _ActionsRow extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildActionItem('Wallet', Icons.attach_money),
_buildActionItem('Delivery', Icons.card_giftcard),
_buildActionItem('Message', Icons.message),
_buildActionItem('Service', Icons.room_service),
],
);
}
Widget _buildActionItem(String name, IconData icon) {
return Column(
children: [
Icon(icon, size: 20, color: Color(0xFF42526F))
.alignment(Alignment.center)
.ripple()
.constrained(width: 50, height: 50)
.backgroundColor(Color(0xfff6f5f8))
.clipOval()
.padding(bottom: 5),
Text(
name,
style: TextStyle(color: Colors.black.withOpacity(0.8), fontSize: 12),
)
],
).gestures(
onTap: () => {
print(name)
}
).padding(vertical: 20);
}
}
class SettingsItemModel {
final IconData icon;
final Color color;
final String title;
final String description;
const SettingsItemModel(
{required this.icon,
required this.color,
required this.title,
required this.description});
}
const List<SettingsItemModel> settingsItems = [
SettingsItemModel(
icon: Icons.location_on,
color: Color(0xff8D7AEE),
title: 'Address',
description: 'Ensure your harvesting address',
),
SettingsItemModel(
icon: Icons.lock,
color: Color(0xffF468B7),
title: 'Privacy',
description: 'System permission change',
),
SettingsItemModel(
icon: Icons.menu,
color: Color(0xffFEC85C),
title: 'General',
description: 'Basic functional settings',
),
SettingsItemModel(
icon: Icons.notifications,
color: Color(0xff5FD0D3),
title: 'Notifications',
description: 'Take over the news in time',
),
SettingsItemModel(
icon: Icons.question_answer,
color: Color(0xffBFACAA),
title: 'Support',
description: 'We are here to help',
),
];
class _Settings extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: settingsItems
.map((e) => _SettingsItem(
e.icon,
e.color,
e.title,
e.description,
))
.toList(),
);
}
}
class _SettingsItem extends StatefulWidget {
_SettingsItem(this.icon, this.iconBgColor, this.title, this.description);
final IconData icon;
final Color iconBgColor;
final String title;
final String description;
@override
State<StatefulWidget> createState() => _SettingsItemState();
}
class _SettingsItemState extends State<_SettingsItem> {
bool pressed = false;
@override
Widget build(BuildContext context) {
return Row(
children: [
Icon(widget.icon, size: 20, color: Colors.white)
.padding(all: 12)
.decorated(
color: widget.iconBgColor,
borderRadius: BorderRadius.circular(30),
)
.padding(left: 15, right: 10),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(widget.title,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
)).padding(bottom: 5),
Text(
widget.description,
style: TextStyle(
color: Colors.black26,
fontWeight: FontWeight.bold,
fontSize: 12,
),
)
],
),
],
)
.alignment(Alignment.center)
.borderRadius(all: 15)
.ripple()
.backgroundColor(Colors.white)
.clipRRect(all: 25)
// .borderRadius(all: 25, animate: true)
.elevation(
pressed ? 0 : 10,
borderRadius: BorderRadius.circular(25),
shadowColor: Color(0x30000000),
)
.constrained(height: 80)
.padding(vertical: 8)
.gestures(
onTapChange: (tapStatus) => setState(() => pressed = tapStatus),
onTapDown: (details) => print('tapDown'),
onTap: () => print('onTap'),
)
.scale(all: pressed ? 0.95 : 1.0);
}
}
Dart에서 const constructor의 의미
The Dart language supports the const keyword, which results in values or identifiers that are derived and assigned at compile time. The values are then immutable. A const differs from a final in that finals are assigned at run time.
Dart에서 const는 컴파일 타임에 값이 초기화되고 immutable이다. final과는 final이 런타임에 할당받는다는 점에서 다르다.
Uploaded by Notion2Tistory v1.1.0