<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jason_hwang.log</title>
        <link>https://velog.io/</link>
        <description>Flutter, iOS</description>
        <lastBuildDate>Sun, 08 Aug 2021 06:28:49 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jason_hwang.log</title>
            <url>https://images.velog.io/images/jason_hwang/profile/9c5edbf2-b95c-4baa-aee0-d1aee181e111/KakaoTalk_Photo_2021-02-16-21-47-35.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jason_hwang.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jason_hwang" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[👨‍🎨 Flutter 에서 Customizing 가능한 디자인 시스템 사용하기]]></title>
            <link>https://velog.io/@jason_hwang/Flutter-%EC%97%90%EC%84%9C-Customizing-%EA%B0%80%EB%8A%A5%ED%95%9C-%EB%94%94%EC%9E%90%EC%9D%B8-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@jason_hwang/Flutter-%EC%97%90%EC%84%9C-Customizing-%EA%B0%80%EB%8A%A5%ED%95%9C-%EB%94%94%EC%9E%90%EC%9D%B8-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 08 Aug 2021 06:28:49 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/jason_hwang/post/0f59cd16-5fb1-4c3c-8661-aeedd8a30977/paining-bob-ross.gif" alt=""></p>
<p><strong>flutter에서는</strong> MaterialApp 위젯에 ThemeData 위젯을 넘겨주어 내가 원하는 Theme 으로 정의된 앱을 만들 수 있습니다.</p>
<p>하지만, 프로젝트의 규모가 커지다 보면 ThemeData가 어느 위젯에 어느 부분에 적용되는지, 어느 부분에는 적용이 되지 않는지 너무나 모호해지고 <code>Theme.of(context)</code> 으로 적용한 부분들은 tracking 하기가 쉽지 않죠.</p>
<p>그래서, 제 경험을 토대로 한 방법 한가지를 이야기 해보려 합니다.</p>
<h3 id="🎨-flutter-custom-theme">🎨 Flutter custom theme</h3>
<hr>
<p><img src="https://images.velog.io/images/jason_hwang/post/9766352b-e3da-4f7b-a6c5-1a59f8e2813e/painting-remember.gif" alt=""><a href="https://pub.dev/packages/flutter_custom_theme">Flutter custom theme</a> 이라는 라이브러리를 사용했어요. flutter 의 themeData 와는 조금 다르게 내가 원하는 이름으로 theme 을 정의하고 원하는 곳에 직접 지정을 해줘야 해요.</p>
<h4 id="custom-theme-class-만들기">Custom theme class 만들기<img src="https://images.velog.io/images/jason_hwang/post/631d6f30-e88d-4404-a64d-1ee8e01442bb/image.png" alt=""></h4>
<p>CustomThemeData를 extends 한 클래스를 만들고 내가 원하는 색과, 텍스트 스타일 같은 모든 themeData를 정의해 사용할 수 있어요.</p>
<blockquote>
<p>Container <strong>color</strong>와 <strong>textStyle</strong>, <strong>align</strong> 을 CustomTheme 으로 적용
<img src="https://images.velog.io/images/jason_hwang/post/d4fcb094-8e48-449b-8a10-44ca8224412b/image.png" alt=""></p>
</blockquote>
<h3 id="🤟-장점-1-언어별-다른-텍스트-스타일-쓰기">🤟 장점 1. 언어별 다른 텍스트 스타일 쓰기</h3>
<hr>
<p>그래서, 저거 말고 뭐가 좋은데? 라고 할 수 있는데. 개인적으로 느꼈던 장점 몇가지만 이야기 해볼게요. 첫 번째로 언어별로 모두 baseline 이 다릅니다. 그래서 이 텍스트들이 모두 같은 위치에 있을거라고 보장하기가 조금 힘들어요. 제 개인적인 경험에서는요. 그래서 저희 팀에서는 언어별로 다른 텍스트 스타일을 사용하기로 했고, 이런식으로 해결했어요.<img src="https://images.velog.io/images/jason_hwang/post/0d78fe32-ff20-4ea1-be65-e8db54322d3b/image.png" alt=""> context로 languageCode를 가져와서 해당하는 스타일을 주는거죠. 덕분에 디자이너님이 만족할 만한 결과가 나왔었어요.</p>
<h3 id="🤟-장점-2-no-more-brightness-check">🤟 장점 2. no more brightness check</h3>
<hr>
<p>다크모드를 지원하려고 하면서 dark 컬러와 light 컬러를 따로 지정해놓고 사용하곤 했는데, 이 두 녀석들을 사용할때 
<code>bool isDark = Theme.of(context).birghtness == Brightness.dark;</code> 
이런 flag를 하나 두고 사용하곤 했어요. 덕분에 파편화가 심해졌고, 관리가 힘들어졌습니다. 코드 더 쳐야하는 단점도 있었죠. CustomTheme을 쓰고나서는 아래에서 살펴볼 수 있듯이 <img src="https://images.velog.io/images/jason_hwang/post/66222204-ed3f-42a3-af8f-8078c79ee2ed/image.png" alt=""> darkMode일때는 알아서 dark theme을 가져다 쓰기 때문에 불필요한 코드를 줄일 수 있었어요.</p>
<h3 id="👨🎨-마치며">👨‍🎨 마치며</h3>
<p><img src="https://c.tenor.com/LIzk3MiGIq8AAAAM/im-out-goodbye.gif" alt="">
flutter theme 때문에 두통과 함께 겪었던 것들을 공유해 봤어요. 부족했던 점이나 의견이 있으시다면 댓글로 공유해주세요! 제 이야기가 여러분의 개발에 도움이 되었으면 좋겠어요 (:</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Flutter 에서 i18n 적용하기]]></title>
            <link>https://velog.io/@jason_hwang/Flutter-%EC%97%90%EC%84%9C-i18n-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@jason_hwang/Flutter-%EC%97%90%EC%84%9C-i18n-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 31 May 2020 09:09:57 GMT</pubDate>
            <description><![CDATA[<p>프로젝트에서 사용하던 flutter i18n plugin이 더이상 유지보수를 중단한다고 선언했다.. </p>
<p><img src="https://images.velog.io/images/jason_hwang/post/a210aa68-ca3d-461b-9962-41791afc79d1/image.png" alt="">
갑작스런 청천벽력같은 소식에 서둘러서 다른 패키지들을 찾아봤는데 <a href="https://pub.dev/packages/intl">intl</a> 패키지라던가.. <a href="https://pub.dev/packages/flutter_i18n">flutter_i18n</a> 라던가... 다양한 패키지들을 고려해보았지만 대부분 dart code를 arb로 generate 하고 변환한 arb 파일을 사용하는 형태였는데 본인이 속한 회사에서는 이미 모든 텍스트 리소스가 key:value 형태로 있었기 때문에 이 형태를 벗어나지 않고 진행하고 싶었다.</p>
<p>그래서 결정한 패키지가 <a href="https://pub.dev/packages/easy_localization">easy_localization</a> 이다.</p>
<p>한차례 테스트 후에 잘 동작하는 것 같아서 사용하기로 결정했다.</p>
<h2 id="패키지-설치-및-셋업">패키지 설치 및 셋업</h2>
<p><em>여느 Dart 패키지처럼 pubsepc.yaml에 추가</em></p>
<pre><code class="language-yaml">easy_localization: ^2.3.2</code></pre>
<h4 id="그리고-assets에-사용할-asset-파일을-명시해줘야-한다">그리고 assets에 사용할 asset 파일을 명시해줘야 한다</h4>
<pre><code class="language-yaml">flutter:
  assets:
    - assets/translations/</code></pre>
<h3 id="⚠️-ios-에서는-반드시-infoplist-를-수정해야함">⚠️ iOS 에서는 반드시 info.plist 를 수정해야함</h3>
<p>xcode에서 <code>Runner.xcworkspace</code>를 열고 info.plist의 <code>Localizations</code> 프로퍼티를 수정해야 한다.
<img src="https://images.velog.io/images/jason_hwang/post/b6d58a6b-e8e6-4dd3-b62a-9812780bd7a2/image.png" alt=""></p>
<pre><code>만약 Localizations 프로퍼티가 없으면 +를 눌러서 Localizations 프로퍼티를 추가해주면 된다</code></pre><p><code>Localizations</code> 에 지원할 언어의 item을 추가해주면 된다</p>
<h4 id="사용하기">사용하기</h4>
<pre><code class="language-dart">import &#39;package:flutter/material.dart&#39;;
import &#39;package:flutter_localizations/flutter_localizations.dart&#39;;
import &#39;package:easy_localization/easy_localization.dart&#39;;

void main() {
  runApp(
    EasyLocalization(
      supportedLocales: [Locale(&#39;en&#39;, &#39;US&#39;), Locale(&#39;de&#39;, &#39;DE&#39;)],
      path: &#39;assets/translations&#39;, // &lt;-- change patch to your
      fallbackLocale: Locale(&#39;en&#39;, &#39;US&#39;),
      child: MyApp()
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: context.localizationDelegates,
      supportedLocales: context.supportedLocales,
      locale: context.locale,
      home: MyHomePage()
    );
  }
}</code></pre>
<ul>
<li>main에서 위 예제처럼 MyApp을 wrapping 하고 지원되는 언어들을 <code>supportedLocales</code> 에 명시한다</li>
<li>path는 localization resource 파일들의 위치</li>
<li>기기의 locale이 지원하지 않는 언어면 사용할 언어는 <code>fallbackLocale</code> 에 지정해주면 된다.</li>
</ul>
<h3 id="locale-이-항상-en_us로-잡히는-문제">Locale 이 항상 en_US로 잡히는 문제</h3>
<p><code>context.locale</code> 로 MaterialApp의 locale을 지정해주니까 항상 en_US로 locale이 잡히는 문제가 있었다.</p>
<p>나는 아래와 같이 <code>dart:ui</code>를 이용해서 시스템 locale 값을 통해 context.locale을 잡아주도록 해서 해결했다.</p>
<pre><code class="language-dart">void setLocale(BuildContext context) {
    switch (ui.window.locale.languageCode) {
      case &#39;ko&#39;:
        context.locale = Locale(&#39;ko&#39;, &#39;KR&#39;);
        break;
      case &#39;es&#39;:
        context.locale = Locale(&#39;es&#39;, &#39;ES&#39;);
        break;
      case &#39;fr&#39;:
        context.locale = Locale(&#39;fr&#39;, &#39;FR&#39;);
        break;
      case &#39;it&#39;:
        context.locale = Locale(&#39;it&#39;, &#39;IT&#39;);
        break;
      case &#39;ja&#39;:
        context.locale = Locale(&#39;ja&#39;, &#39;JP&#39;);
        break;
      case &#39;nl&#39;:
        context.locale = Locale(&#39;nl&#39;, &#39;NL&#39;);
        break;
      case &#39;zh&#39;:
        if (ui.window.locale.scriptCode == &#39;Hant&#39;) {
          context.locale = Locale(&#39;zh&#39;, &#39;TW&#39;);
        }
        if (ui.window.locale.countryCode == &#39;HK&#39; ||
            ui.window.locale.countryCode == &#39;TW&#39; ||
            ui.window.locale.countryCode == &#39;CN&#39;) {
          context.locale = Locale(&#39;zh&#39;, ui.window.locale.countryCode);
        } else
          context.locale = Locale(&#39;zh&#39;, &#39;CN&#39;);
        break;
      default:
        break;
    }
  }

  class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    setLocale(context);
    return MaterialApp(
      localizationsDelegates: context.localizationDelegates,
      supportedLocales: context.supportedLocales,
      locale: context.locale,
      home: MyHomePage()
    );
  }
}</code></pre>
<h2 id="사용">사용</h2>
<p>이제 키값을 통해서 아래처럼 간결하게 다국어 지원이 가능하다</p>
<pre><code class="language-dart">Text(&#39;CommonProfile&#39;.tr())</code></pre>
]]></description>
        </item>
    </channel>
</rss>