2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

UI Pocketで、FlutterとFigmaとデザイン、まとめて学習しちゃおう

Last updated at Posted at 2025-01-20

概要

UI Pocketというサービスを活用した学習方法について話をさせていただきます。
デサインに興味がある方には、ぜひ知ってほしいサービスです!
タイトルに記載の通りですが、
UI Pocketを通じて、以下に対する理解を深められると感じている最中です。

  • Flutter
  • Figma
  • デザイン
Flutterの経験について

業務経験はないですが、モバイル開発に興味があり、1年弱さわっています。

UI Pocketとは

一言でいえば、UIカタログ、でしょうか。
様々なアプリのスクリーンショットを無料で閲覧できるサービスです。(無料で利用可能なコンテンツあり)

トップ画面です。(PC表示)
image.png

モバイルの場合は、画面下の方にタブバーで表示

image.png

以下3つの機能は、無料プランでは制限があり、全画像の閲覧はできません。制限解除には、Proプランに加入が必要です。
といっても、月額480円です。本格的に利用される方にとっては、安いものかと思いました!
これらの機能も利用することで、作成したいUI構築に役立てることが可能になります。

  • UIコンポーネント
  • UIパターン
  • フロー

各機能の紹介(ざっくり)

アプリ

ここは冒頭で記載した通り、閲覧可能なアプリ一覧が並んでいます。
ここは無料ユーザでも一通り閲覧可能です。
image.png

UIコンポーネント

テキストフィールドやボタンなど、特定の要素ごとのデザインをサービスを跨いで確認できます。
image.png

UIパターン

様々なサービスを跨いで、特定の機能に関する情報を一度に閲覧できます。
image.png

フロー

特定サービスの特定機能にフィルタリングした状態で、一連の流れを確認できます。
image.png

本題へ

以下3つの方法を用いて、学習を進めています。
(FlutterやFigmaの基本的な話は特に記載していません。)

  1. UI Pocketの画像を見て、Figma上でUIを作成して、プラグインでコード出力
  2. UI Pocketの画像をClaudeにアップロードして、コード提供してもらう
  3. UI Pocketの画像を見て、実際にコード実装しながら、適宜ネットやClaudeを利用

基本的には、UIPocketで提供されているタブとフォームがある画面(「口座情報」でログイン)を参照して進めました。

1. UI Pocketの画像を見て、Figma上でUIを作成して、プラグインでコード出力

Figmaの理解と利用しやすいコードを出力するための作り方を理解
Figmaの操作方法を知るためにも使っています。
私はプラン加入していないので、開発モードは使えません。UI Pocketの特定画像を見ながら、Figma上で作成を行います。作成完了後に、プラグインでコード生成を行います。

利用者数が多い順に2つのプラグインで確認しました。

Figma to Code (HTML, Tailwind, Flutter, SwiftUI)

Figma上で作成して、コードを出力しました。
しかしそのコードには、TabBarコンポーネントFormコンポーネントが存在しませんでした。
その後、エディター上のエラー解消後に実端末で確認しましたが、OVERFLOWEDが発生しました。

実端末確認時のスクリーンショット

image.png

FigmaToFlutter

1つ目のプラグインと同じ成果物を利用しましたが、
プラグインが立ち上がりませんでした。
Material 3 Design Kitで提供されたExampleでは、以下ウインドウが表示されました。私の成果物がプラグインに適応した形で作成できていないと思われます。

image.png

Material 3 Design KitのExampleを使って、コードを出力しました。
エディター上のエラー解消後に実端末で確認しましたが、こちらもOVERFLOWEDが発生しました。

実端末確認時のスクリーンショット

image.png

Figmaの利用経験が少ないので、今後改善可能な部分はありますが、UI全体を頼るのではなく、必要な部分を適宜ピックアップして利用する、といった形で適切な気がしました!

UI Pocketの画像をClaudeにアップロードして、コード提供してもらう

特定のUIや機能の実装方法を把握して選択肢を広げる
chatgptではなくClaudeです。両方を試してみて、アップロード画像に対するFlutterのコード生成は、Claudeの方がより実物に近いUIかつ、動くものに近いコードが生成される印象を受けました。

プロンプト入力

画面を添付して、添付した画像について、Flutterでコードを作成してほしいです。と伝えました。
image.png

コード生成

image.png

動作確認

生成されたコードで特にエラー発生していませんので、修正箇所はありませんでした。
実機を用いた確認に進みました。こちらは、OVERFLOWEDがありませんでした!

実端末で確認

image.png
画像1枚からここまでの精度でコード出力してくれることに感謝です。
UIがそれっぽいだけではありません。FormウィジェットとTextFormFieldウィジェットで構成されていました。

キーボードが数字入力になっている

image.png

ラジオボタンがONになる

image.png

コード確認

テキスト入力欄やボタンの配置、各入力値を保持する、タブ部分をタブとして機能させる、など修正が必要な箇所はありますが、ここまでやってくれると助かります。

生成されたコード エラーは特に発生しなかったので、修正箇所はありません。
import 'package:flutter/material.dart';

class SMBCLoginScreen extends StatefulWidget {
  @override
  _SMBCLoginScreenState createState() => _SMBCLoginScreenState();
}

class _SMBCLoginScreenState extends State<SMBCLoginScreen> {
  bool _saveCredentials = false;
  final _formKey = GlobalKey<FormState>();
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: Icon(Icons.arrow_back),
          onPressed: () => Navigator.pop(context),
        ),
        title: Text('ログイン'),
        actions: [
          IconButton(
            icon: Icon(Icons.help_outline),
            onPressed: () {
              // ヘルプ機能の実装
            },
          ),
        ],
      ),
      body: SingleChildScrollView(
        child: Padding(
          padding: EdgeInsets.all(16.0),
          child: Form(
            key: _formKey,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                // SMBC ID と口座情報のタブ
                Row(
                  children: [
                    Expanded(
                      child: Container(
                        padding: EdgeInsets.all(8),
                        decoration: BoxDecoration(
                          border: Border(
                            bottom: BorderSide(
                              color: Colors.green[700]!,
                              width: 2,
                            ),
                          ),
                        ),
                        child: Text(
                          'SMBC ID',
                          style: TextStyle(
                            color: Colors.green[700],
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                      ),
                    ),
                    Expanded(
                      child: Container(
                        padding: EdgeInsets.all(8),
                        child: Text('口座情報'),
                      ),
                    ),
                  ],
                ),
                SizedBox(height: 24),
                Text(
                  '契約者番号でログイン',
                  style: TextStyle(
                    color: Colors.green[700],
                    fontSize: 16,
                  ),
                ),
                SizedBox(height: 16),
                // 店番号入力フィールド
                TextFormField(
                  decoration: InputDecoration(
                    labelText: '店番号',
                    border: OutlineInputBorder(),
                  ),
                  keyboardType: TextInputType.number,
                ),
                SizedBox(height: 16),
                // 口座番号入力フィールド
                TextFormField(
                  decoration: InputDecoration(
                    labelText: '口座番号',
                    border: OutlineInputBorder(),
                  ),
                  keyboardType: TextInputType.number,
                ),
                SizedBox(height: 16),
                // ログイン暗証入力フィールド
                TextFormField(
                  decoration: InputDecoration(
                    labelText: 'ログイン暗証',
                    border: OutlineInputBorder(),
                  ),
                  obscureText: true,
                ),
                SizedBox(height: 16),
                // 店・口座番号保存スイッチ
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text('店・口座番号保存'),
                    Switch(
                      value: _saveCredentials,
                      onChanged: (bool value) {
                        setState(() {
                          _saveCredentials = value;
                        });
                      },
                      activeColor: Colors.green[700],
                    ),
                  ],
                ),
                SizedBox(height: 24),
                // ログインボタン
                ElevatedButton(
                  onPressed: () {
                    if (_formKey.currentState!.validate()) {
                      // ログイン処理の実装
                    }
                  },
                  style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.grey[200],
                    padding: EdgeInsets.symmetric(vertical: 16),
                  ),
                  child: Text(
                    'ログイン',
                    style: TextStyle(
                      color: Colors.grey[600],
                      fontSize: 16,
                    ),
                  ),
                ),
                SizedBox(height: 24),
                // 暗証忘れの場合のリンク
                TextButton(
                  onPressed: () {
                    // 暗証忘れ処理の実装
                  },
                  child: Text(
                    'ログイン暗証をお忘れの場合',
                    style: TextStyle(
                      color: Colors.green[700],
                    ),
                  ),
                ),
                // 下部のナビゲーションバー
                Padding(
                  padding: EdgeInsets.only(top: 100),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceAround,
                    children: [
                      _buildBottomNavItem(Icons.lock, 'ワンタイム\nパスワード'),
                      _buildBottomNavItem(Icons.credit_card, 'My通帳'),
                      _buildBottomNavItem(Icons.account_balance, 'サービス一覧'),
                      _buildBottomNavItem(Icons.settings, '設定'),
                    ],
                  ),
                ),
                SizedBox(height: 16),
                // システムメンテナンス通知
                Container(
                  padding: EdgeInsets.all(8),
                  color: Colors.yellow[100],
                  child: Text(
                    '1月12日(日)21時〜1月13日(月・祝)12時\n新システムへ移行のため、サービスを休止いたします。',
                    style: TextStyle(fontSize: 12),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildBottomNavItem(IconData icon, String label) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Icon(icon, color: Colors.green[700]),
        Text(
          label,
          textAlign: TextAlign.center,
          style: TextStyle(
            fontSize: 12,
            color: Colors.green[700],
          ),
        ),
      ],
    );
  }
}

UI Pocketの画像を見て、実際にコード実装しながら、適宜ネットやClaudeを利用

Flutter(Dart)の各APIの機能を理解しつつ、開発する能力向上
まだこの方法一番早く進められる状況です。Flutterを少しだけ理解している段階にあるから、かもしれません。
Claudeで出力されたものを実物に近づける作業の方が、苦労するレベルかと思います。

画像を見て、基本的には私自身でコードを書き進めます。
この部分のUIはどう実装するんだろう?となった場合に、ネットで情報収集をしたり、Claudeを利用したりします。(比較的原始的な方法?)

成果物(画面)

実際にコードを書いて作成したものです。
左:表示時
右:情報入力後
アイコン部分などは、これから実装、といった段階です。
改めて、時間は要しても、この方法が一番収穫の多いやり方、と感じられますね。
image.png

成果物(コード)

これから改善する箇所もありますが、こちらのページからコードは確認いただけます。
ちなみに、custom_color.dartで実装した各要素の色は、以下の手順で設定しています。

1.Microsoft PowerToysColor Pickerを用いて、知りたい箇所の色のHEXを取得

2.Flutter Color from hex generatorに1で取得した色を貼り付け、変換後の値を設定

コード作成後

3つ目の方法の最後に記載しましたが、以下では困っちゃいます。

  • UIがかっこよく見えても、スクロールしたらガタガタ
  • 別の端末にしたら、OVERFLOWなどのエラーになる

Flutter and Dart DevToolsも使って、パフォーマンスを改善、レスポンシブデザイン対応、など行います。(まだまだ勉強中です!!)
初歩的な内容かとなりますが、ご容赦ください!

パフォーマンス改善

  • 各Widgetのrebuildを防ぐためにconstを設定
  • constを設定可能な構造への変更、Widgetを採用(ContainerからSizedBoxへの切り替え、など)

Responsive, Adaptiveデザインの適用

まとめ

今回、UI Pocketというサービスを起点にFlutter学習を進めている話をさせていただきました。
冒頭にも記載しましたが、
UI Pocketを通じて、以下の理解を深められると感じている最中です。

  • Flutter
  • Figma
  • デザイン

今後も活用して、スキルアップできればと思います。

ありがとうございました。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?