Save 37% off PRO during our Black Friday Sale! »

Material Design と Product UI Design

Material Design と Product UI Design

73e023e76c881293c494a350b1b7baa2?s=128

Katsumi Onishi

March 18, 2021
Tweet

Transcript

  1. Material Design 
 と 
 Product UI Design


  2. 大西克己 
 @katsummy
 Android Engineer since Donut
 Flutter Engineer Now


    I ♥Mt.
  3. Introduce


  4. Introduce


  5. Introduce
 Android Kotlin


  6. Introduce
 タクシーフードデリバリー サービス
 - ローンチに向けて Flutterで開発中

  7. Agenda
 1. デザインシステム / マテリアルデザインおさらい
 2. マテリアルデザインの要素
 3. アプリテーマのカスタマイズ
 4.

    プロダクトへマテリアルデザインの適用

  8. デザインシステム
 デザインの原則、概念、ガイド、コンポーネントなど、デザインに関するルールを定め たもの
 - Color 
 - Typography
 - Interaction

    (Animation)
 - Icon
 - Component
 - Button / List / ListItem / Divider / Card / Shadow (Elevation) / 
 - etc.
 一貫したデザインで、UIと操作/体験をユーザに伝える。

  9. デザインシステム
 - フラットデザイン - Apple?
 - マテリアルデザイン - Google
 -

    メトロUI - Microsoft?
 - Polaris - Shopify
 - etc.

  10. Material is the metaphor
 - 光があたると影が現れるなど、物理的な世界を、二次 元に取り入れている
 - 素材の表面は紙とインクで表現
 -

    フィードバック/モーション
 Material Design / Material System

  11. Material Design / Material System
 Component / Typography / Color

    / Elevation / States
  12. Material Design / Material System
 Components

  13. Material Design / Material System Components

  14. Product UI Design
 フォントとサイズは拘りたい
 カラーは仮の当てなので、ブランディング/トンマナ調整後は修正したい。
 ボタンなどコンポーネントデザインはプロダクトの雰囲気に合わせたい。
 - コンポーネントの角丸を大きく
 - Elevationはデフォルトとは変えたい


    - ボタン - Enable/Stable時の表示
 - Radio / Check のカスタム
 - カスタムコンポーネント
 

  15. Product UI Design への対応
 Product の Design System を作成する?
 デフォルトは

    Material Design を使用する!
 カスタムして Product UI Design へ適用!
 - Typography
 - Component
 - Color
 - Elevation
 - States
 マテリアルコンポーネントのテーマをカスタム!
 カスタムコンポーネント!

  16. アプリテーマのカスタマイズ
 Flutter アプリテーマのカスタマイズ - Qiita https://qiita.com/granoeste/items/352d19157c21cd35e21f


  17. アプリテーマのカスタマイズ


  18. アプリテーマのカスタマイズ


  19. アプリテーマのカスタマイズ


  20. Typographyのカスタマイズ


  21. Typography.material2018() black, white, englishLike, dense, tall プラットフォーム


  22. Typography factory Typography._withPlatform( TargetPlatform? platform, TextTheme? black, TextTheme? white, TextTheme

    englishLike, TextTheme dense, TextTheme tall, ) { switch (platform) { case TargetPlatform.iOS: black ??= blackCupertino; white ??= whiteCupertino; break; case TargetPlatform.android: case TargetPlatform.fuchsia: black ??= blackMountainView; white ??= whiteMountainView; break; case TargetPlatform.windows: black ??= blackRedmond; white ??= whiteRedmond; break; case TargetPlatform.macOS: black ??= blackRedwoodCity; white ??= whiteRedwoodCity; break; case TargetPlatform.linux: black ??= blackHelsinki; white ??= whiteHelsinki; break; case null: break; } return Typography._(black!, white!, englishLike, dense, tall); } プラットフォーム毎に Facetype が定義されている
 fontFamily: '.SF UI Display/Text' fontFamily: 'Roboto' fontFamily: 'Segoe UI' fontFamily: '.AppleSystemUIFont' fontFamily: 'Roboto', fontFamilyFallback: _helsinkiFontFallbacks, _helsinkiFontFallbacks = ['Ubuntu', 'Cantarell', 'DejaVu Sans', 'Liberation Sans', 'Arial']
  23. defaultTargetPlatform
 /// The dart:io implementation of [platform.defaultTargetPlatform]. platform.TargetPlatform get defaultTargetPlatform

    { platform.TargetPlatform? result; if (Platform.isAndroid) { result = platform.TargetPlatform.android; } else if (Platform.isIOS) { result = platform.TargetPlatform.iOS; } else if (Platform.isFuchsia) { result = platform.TargetPlatform.fuchsia; } else if (Platform.isLinux) { result = platform.TargetPlatform.linux; } else if (Platform.isMacOS) { result = platform.TargetPlatform.macOS; } else if (Platform.isWindows) { result = platform.TargetPlatform.windows; } assert(() { if (Platform.environment.containsKey('FLUTTER_TEST')) result = platform.TargetPlatform.android; return true; }()); if (platform.debugDefaultTargetPlatformOverride != null) result = platform.debugDefaultTargetPlatformOverride; if (result == null) { throw FlutterError( 'Unknown platform.\n' '${Platform.operatingSystem} was not recognized as a target platform. ' 'Consider updating the list of TargetPlatforms to include this platform.' ); } return result!; } final typography = Typography.material2018(platform: defaultTargetPlatform );
  24. Typography - englishLike2018
 /// Defines text geometry for [ScriptCategory.englishLike] scripts,

    such as /// English, French, Russian, etc. /// /// The font sizes, weights, and letter spacings in this version match the /// [latest Material Design specification](https://material.io/go/design-typography#typography-styles). static const TextTheme englishLike2018 = TextTheme( headline1 : TextStyle(debugLabel: 'englishLike headline1 2018', fontSize: 96.0, fontWeight: FontWeight.w300, textBaseline: TextBaseline.alphabetic, letterSpacing: -1.5), headline2 : TextStyle(debugLabel: 'englishLike headline2 2018', fontSize: 60.0, fontWeight: FontWeight.w300, textBaseline: TextBaseline.alphabetic, letterSpacing: -0.5), headline3 : TextStyle(debugLabel: 'englishLike headline3 2018', fontSize: 48.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.0), headline4 : TextStyle(debugLabel: 'englishLike headline4 2018', fontSize: 34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.25), headline5 : TextStyle(debugLabel: 'englishLike headline5 2018', fontSize: 24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.0), headline6 : TextStyle(debugLabel: 'englishLike headline6 2018', fontSize: 20.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.15), bodyText1 : TextStyle(debugLabel: 'englishLike bodyText1 2018', fontSize: 16.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.5), bodyText2 : TextStyle(debugLabel: 'englishLike bodyText2 2018', fontSize: 14.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.25), subtitle1 : TextStyle(debugLabel: 'englishLike subtitle1 2018', fontSize: 16.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.15), subtitle2 : TextStyle(debugLabel: 'englishLike subtitle2 2018', fontSize: 14.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.1), button : TextStyle(debugLabel: 'englishLike button 2018', fontSize: 14.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic, letterSpacing: 1.25), caption : TextStyle(debugLabel: 'englishLike caption 2018', fontSize: 12.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic, letterSpacing: 0.4), overline : TextStyle(debugLabel: 'englishLike overline 2018', fontSize: 10.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic, letterSpacing: 1.5), );
  25. Typography - dense2018
 /// Defines text geometry for dense scripts,

    such as Chinese, Japanese /// and Korean. /// /// The font sizes, weights, and letter spacings in this version match the /// latest [Material Design specification](https://material.io/go/design-typography#typography-styles). static const TextTheme dense2018 = TextTheme( headline1 : TextStyle(debugLabel: 'dense headline1 2018', fontSize: 96.0, fontWeight: FontWeight.w100, textBaseline: TextBaseline.ideographic), headline2 : TextStyle(debugLabel: 'dense headline2 2018', fontSize: 60.0, fontWeight: FontWeight.w100, textBaseline: TextBaseline.ideographic), headline3 : TextStyle(debugLabel: 'dense headline3 2018', fontSize: 48.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic), headline4 : TextStyle(debugLabel: 'dense headline4 2018', fontSize: 34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic), headline5 : TextStyle(debugLabel: 'dense headline5 2018', fontSize: 24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic), headline6 : TextStyle(debugLabel: 'dense headline6 2018', fontSize: 21.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic), bodyText1 : TextStyle(debugLabel: 'dense bodyText1 2018', fontSize: 17.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic), bodyText2 : TextStyle(debugLabel: 'dense bodyText2 2018', fontSize: 15.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic), subtitle1 : TextStyle(debugLabel: 'dense subtitle1 2018', fontSize: 17.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic), subtitle2 : TextStyle(debugLabel: 'dense subtitle2 2018', fontSize: 15.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic), button : TextStyle(debugLabel: 'dense button 2018', fontSize: 15.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic), caption : TextStyle(debugLabel: 'dense caption 2018', fontSize: 13.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic), overline : TextStyle(debugLabel: 'dense overline 2018', fontSize: 11.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic), );
  26. Typography - tall2018
 /// Defines text geometry for tall scripts,

    such as Farsi, Hindi, and Thai. /// /// The font sizes, weights, and letter spacings in this version match the /// latest [Material Design specification](https://material.io/go/design-typography#typography-styles). static const TextTheme tall2018 = TextTheme( headline1 : TextStyle(debugLabel: 'tall headline1 2018', fontSize: 96.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic), headline2 : TextStyle(debugLabel: 'tall headline2 2018', fontSize: 60.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic), headline3 : TextStyle(debugLabel: 'tall headline3 2018', fontSize: 48.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic), headline4 : TextStyle(debugLabel: 'tall headline4 2018', fontSize: 34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic), headline5 : TextStyle(debugLabel: 'tall headline5 2018', fontSize: 24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic), headline6 : TextStyle(debugLabel: 'tall headline6 2018', fontSize: 21.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic), bodyText1 : TextStyle(debugLabel: 'tall bodyText1 2018', fontSize: 17.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic), bodyText2 : TextStyle(debugLabel: 'tall bodyText2 2018', fontSize: 15.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic), subtitle1 : TextStyle(debugLabel: 'tall subtitle1 2018', fontSize: 17.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic), subtitle2 : TextStyle(debugLabel: 'tall subtitle2 2018', fontSize: 15.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic), button : TextStyle(debugLabel: 'tall button 2018', fontSize: 15.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic), caption : TextStyle(debugLabel: 'tall caption 2018', fontSize: 13.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic), overline : TextStyle(debugLabel: 'tall overline 2018', fontSize: 11.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic), );
  27. Typography - どこで使われてるのか?
 About applicationName, DatePicker
 AppBar
 TextFormField's hintStyle, DropdownButton,

    ListTile's title
 ListTile on Drawer, NavigationRail, TabBar
 Text, ListTile's subtitle
 Button
 TextFormField's errorStyle, helperStyle

  28. Typography - カスタマイズ AppのTextStyle
 black と dense をマージ
 個々にマージ
 textTheme

    に設定

  29. Typography - Tree


  30. Color
 深淵


  31. Color 個々に定義
 AppのColorStyle
 colorScheme に
 primary / secondary を定義
 深淵


  32. Component
 プロダクトで使用するコンポーネントをピックアップ - AppBar - Buttons - Bottom Navigation -

    Cards - Chips - TextField - etc... カスタムコンポーネント
 - Material Design に無いコンポーネント作成 - テーマのカスタムでは実現できないコンポーネント... - Radio/Check Material Design の テーマをカスタム

  33. Component
 プロダクトで使用するコンポーネントをピックアップ - AppBar - Buttons - Bottom Navigation -

    Cards - Chips - TextField - etc... カスタムコンポーネント
 - Material Design に無いコンポーネント作成 - テーマのカスタムでは実現できないコンポーネント - Radio/Check Material Design の テーマをカスタム

  34. Component - AppBar
 AppBar は、primaryColor が適用されるので、 appBarTheme で再定義します。 AppBar の背景は

    white、テキストとアイコンは black を適用したい

  35. Component - Button
 Flutter 1.22 ~ 


  36. Component - Button
 ElevatedButton( style: ButtonStyle( backgroundColor: MaterialStateProperty.resolveWith<Color>( (Set<MaterialState> states)

    { if (states.contains(MaterialState.pressed)) return Theme.of(context).colorScheme.primary.withOpacity(0.5); return null; // default to the component's default }, ), ), ) states で値を変更

  37. Component - Button - ElevatedButton 角をもっと丸く、ボタンのDisable時のテキストはデフォルトではグレーになるので、プライマリーカラーに透過したものを適用したい!!


  38. Component - Button - OutlinedButton 角をもっと丸く、アウトラインはもう少し細く、プライマリーカラーとフィルカラーを適用したい!!


  39. Component - Button - TextButton 
 テキストボタンのカラーは Black を適用したい!!


  40. Component - TextField 
 テキスト入力は背景カラーとアンダーラインを適用したい!!
 フォーカス
 フォーカス


  41. Component - TextField 
 アンダーライン
 背景


  42. Component - TextField - Typography

  43. Component - Radio/Checkbox Radio / Checkbox は、円形でデフォルトより大きく、チェックマークをカスタムしたい!!
 デフォルト
 こうしたい


  44. Component - Radio/Checkbox Radio / Checkbox は、円形でデフォルトより大きく、チェックマークをカスタムしたい!!
 デフォルト
 こうしたい
 テーマ/スタイルの定義ではカスタムできません!!


    画像で実装できるけど... インタラクション(アニメーション)が消えてる...

  45. Component - Radio/Checkbox SDK ソースコードをコピーしてカスタム...
 大きく
 丸く
 チェックマークのパスのポ ジションを調整
 プライベート定数

    
 const 定数

  46. Component - Radio/Checkbox
 SDK ソースコードをコピーしてカスタム...
 大きく
 プライベート定数 


  47. Elevation
 テーマ設定できるものは、Elevationを使用する。 
 カスタムコンポーネントはboxShadowを使用する 


  48. Elevation


  49. Elevation
 const Map<int, List<BoxShadow>> kElevationToShadow = _elevationToShadow; // to hide

    the literal from the docs const Color _kKeyUmbraOpacity = Color(0x33000000); // alpha = 0.2 const Color _kKeyPenumbraOpacity = Color(0x24000000); // alpha = 0.14 const Color _kAmbientShadowOpacity = Color(0x1F000000); // alpha = 0.12 const Map<int, List<BoxShadow>> _elevationToShadow = <int, List<BoxShadow>>{ // The empty list depicts no elevation. 0: <BoxShadow>[], 1: <BoxShadow>[ BoxShadow(offset: Offset(0.0, 2.0), blurRadius: 1.0, spreadRadius: -1.0, color: _kKeyUmbraOpacity), BoxShadow(offset: Offset(0.0, 1.0), blurRadius: 1.0, spreadRadius: 0.0, color: _kKeyPenumbraOpacity), BoxShadow(offset: Offset(0.0, 1.0), blurRadius: 3.0, spreadRadius: 0.0, color: _kAmbientShadowOpacity), ], 2: <BoxShadow>[ BoxShadow(offset: Offset(0.0, 3.0), blurRadius: 1.0, spreadRadius: -2.0, color: _kKeyUmbraOpacity), BoxShadow(offset: Offset(0.0, 2.0), blurRadius: 2.0, spreadRadius: 0.0, color: _kKeyPenumbraOpacity), BoxShadow(offset: Offset(0.0, 1.0), blurRadius: 5.0, spreadRadius: 0.0, color: _kAmbientShadowOpacity), ],
  50. Elevation
 カスタムコンポーネントはboxShadowに kElevationToShadow[?] を指定する


  51. まとめ 個別にスタイルを定義はしない。


  52. まとめ アプリ開発初めには、
 - カラー/トンマナは決まってない。
 - ブランディング/マーケティングでかわってくる。
 - アプリ名/アプリアイコンも。
 
 作成途中の機能とデザインを元に実装を進めなければならないことがある。


    
 - コンポーネント志向!! デザイナとエンジニアで共有する
 - スタイルはテーマ化を意識して実装する
 - 足りないUIパーツは、カスタムコンポーネント化していく
 
 デモソースコード granoeste/flutter_custom_theme https://github.com/granoeste/flutter_custom_theme
  53. None
  54. 採用情報| 株式会社Mobility Technologies https://mo-t.com/recruit/