Flutter padding 위젯 util화

2024. 4. 13. 09:26개발/Flutter

 

 

 

 

 

회사에서 피그마 value 값을 토큰화 시키는 작업을 진행중이다.

(참고로 style dictionary 는 아래와 같은 토큰값을 지원한다)

color
dimension
custom-radius
custom-spacing
custom-fontStyle
custom-icon

 

 

 

https://github.com/aloisdeniel/style-dictionary-figma-flutter

 

GitHub - aloisdeniel/style-dictionary-figma-flutter: Custom style-dictionary transforms and formats to generate Flutter resource

Custom style-dictionary transforms and formats to generate Flutter resources from a Figma Design Token plugin export.. - aloisdeniel/style-dictionary-figma-flutter

github.com

 

 

 

 

 

 

 

 

아무튼

code generator를 사용해서 만들어지는 값들은(ex: style dictionary) 영 마음에 안들어서...

  final Color colorsMultipleFills0;
  final Color colorsMultipleFills1;
  final Color colorsRefBlue;
  final Color colorsSingleBlue;
  final Color colorsSpecialCharacters;
  final Color colorsSpecialCharactersNderung;
  final Color darkBackground;
  final Color invalidEmpty;
  final Color lightBackground;

이런식으로 이름 그대로 지정이 된다.

 

 

 

 

 

 

 

 

 

 

 

color는 material color 사용하는것처럼 color를 만들고, (이건 다음 글로)

static const dsRed = MaterialColor(_dsRedPrimaryValue, <int, Color>{
    100: Color(0xFFFFD6DA),
    200: Color(0xFFFFA3AC),
    300: Color(0xFFFF808B),
    400: Color(0xFFFF5262),
    500: Color(_dsRedPrimaryValue),
    600: Color(0xFFCC0013),
    700: Color(0xFF99000E),
    800: Color(0xFF66000A),
    900: Color(0xFF330005),
  });
  static const _dsRedPrimaryValue = 0xFFFF0018;

(이렇게 사용하면 dsRed[100]과 같은 형태로 사용이 가능하다)

 

 

 

 

 

 

 

 

 

 

 

 

padding widget은 side flag를 넣어서 아래와 같이 방향, 픽셀값만 지정하면 사용할 수 있게끔 util화 시켰다.

import 'package:flutter/material.dart';

class Dimension {
  late _DimensionSide _left;
  late _DimensionSide _top;
  late _DimensionSide _right;
  late _DimensionSide _bottom;
  late _DimensionSide _horizontal;
  late _DimensionSide _vertical;
  late _DimensionSide _all;

  Dimension() {
    _left = _DimensionSide(_SideFlag(1, 0, 0, 0));
    _top = _DimensionSide(_SideFlag(0, 1, 0, 0));
    _right = _DimensionSide(_SideFlag(0, 0, 1, 0));
    _bottom = _DimensionSide(_SideFlag(0, 0, 0, 1));
    _horizontal = _DimensionSide(_SideFlag(1, 0, 1, 0));
    _vertical = _DimensionSide(_SideFlag(0, 1, 0, 1));
    _all = _DimensionSide(_SideFlag(1, 1, 1, 1));
  }

  _DimensionSide get left => _left;
  _DimensionSide get top => _top;
  _DimensionSide get right => _right;
  _DimensionSide get bottom => _bottom;
  _DimensionSide get horizontal => _horizontal;
  _DimensionSide get vertical => _vertical;
  _DimensionSide get all => _all;
}

class _DimensionSide {
  _SideFlag sideFlag;

  _DimensionSide(this.sideFlag);

  EdgeInsets get none {
    return _DimensionSize(sideFlag, _Helper.none).data;
  }

  EdgeInsets get px_4 {
    return _DimensionSize(sideFlag, _Helper.px_4).data;
  }

  EdgeInsets get px_6 {
    return _DimensionSize(sideFlag, _Helper.px_6).data;
  }

  EdgeInsets get px_8 {
    return _DimensionSize(sideFlag, _Helper.px_8).data;
  }

  EdgeInsets get px_12 {
    return _DimensionSize(sideFlag, _Helper.px_12).data;
  }

  EdgeInsets get px_16 {
    return _DimensionSize(sideFlag, _Helper.px_16).data;
  }

  EdgeInsets get px_24 {
    return _DimensionSize(sideFlag, _Helper.px_24).data;
  }
}

class _DimensionSize {
  _SideFlag sideFlag;
  double factor;

  _DimensionSize(this.sideFlag, this.factor);

  get data => EdgeInsets.fromLTRB(
        sideFlag.leftFlag * factor,
        sideFlag.topFlag * factor,
        sideFlag.rightFlag * factor,
        sideFlag.bottomFlag * factor,
      );
}

class _SideFlag {
  double leftFlag = 0;
  double topFlag = 0;
  double rightFlag = 0;
  double bottomFlag = 0;

  _SideFlag(
    this.leftFlag,
    this.topFlag,
    this.rightFlag,
    this.bottomFlag,
  );
}

class _Helper {
  static double none = 0;
  static double px_4 = 4;
  static double px_6 = 6;
  static double px_8 = 8;
  static double px_12 = 12;
  static double px_16 = 16;
  static double px_24 = 24;
}

Dimension spacer = Dimension();

 

 

코드를 보면 알겠지만, sideflag는 boxshadow등등, 방향 지정이 필요한 곳에서 반복적으로 사용될것이므로 private로 선언했다.

helper 키워드 같은 경우에는, 피그마에서 토큰 값이 추가될 경우 변경되는 부분이다. 현재 우리는 저 7가지 값만을 사용중이다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

전역으로 사용 가능한 객체인 spacer를 사용하면

class DSDotTag extends StatelessWidget {
  final String label;
  final Color? backgroundColor;
  final Color? textColor;
  final TextStyle textStyle;

  const DSDotTag({
    super.key,
    required this.label,
    required this.backgroundColor,
    required this.textColor,
    required this.textStyle,
  });

  @override
  Widget build(BuildContext context) {
    return Card(
      elevation: 0,
      color: backgroundColor,
      shape: RoundedRectangleBorder(
        borderRadius: borderRadiusWidget.px_6,
      ),
      child: Padding(
        padding: spacer.top.px_4 + spacer.bottom.px_4 + spacer.left.px_8 + spacer.right.px_6,
        child: Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(
              size: 4,
              Icons.circle,
              color: textColor,
            ),
            sizedBox.horizontal.px_4,
            Text(
              label,
              style: textStyle.copyWith(color: textColor),
            ),
          ],
        ),
      ),
    );
  }
}

이 예시처럼

 

 

 

요런 식으로..

        padding: spacer.top.px_4 + spacer.bottom.px_4 + spacer.left.px_8 + spacer.right.px_6,

 

spacer를 불러와 어느 위젯에서든 자유자재로 지정이 가능하다.

 

 

 

 

 

 

 

회사 디자인 시스템의 uikit를 flutter로 구현하면서,

구체적인 하드코딩 값을 사용하지 않는 위젯 코드를 끊임없이 연구중이다.

 

 

 

 

 

앞으로도 자주 구체적인 사례를 공유하러 와야지..

 

 

 

끗!