가을기 Workspace

[플러터] 23일차 - styled_widget 써보기 본문

개발/개인앱

[플러터] 23일차 - styled_widget 써보기

가을기_ 2021. 8. 11. 02:06

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이 런타임에 할당받는다는 점에서 다르다.

 

 

 

Comments