4
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

.NET MAUIAdvent Calendar 2022

Day 14

Figmaで作る.NET MAUI UIコンポーネント

Last updated at Posted at 2022-12-13

はじめに

先週YouTuberの記事を書きましたが、その中で紹介したJavier Suárezさんが作ったFigmaのデザインをそのまま.NET MAUIに持ってくるツールを使ってみたので、その紹介をします。

他の記事で導入方法については書いていますので、ここではインストール後からお話できればと思います。

Figma Design to .NET MAUI

さて、ここからが本題になります。
まず、インストールしたFigma.Maui.Graphics.Sampleを開きます。
sample.png

ここに赤の線のところにコピーしたFigmaのアクセストークンを貼り付けます。

そして黄色いところにはデザインを持っていきたいFigmaFileのURLのFileID部分をコピペします。
YourFi.png

「Generate」を押すとC#のコードが作成されるので「Export」して保存してください。

.NET MAUIで実装

新規作成をして生成したコードを表示するGraphicsViewを作成します。

MAUIのテンプレートを新規作成して「MainPage.xaml」を以下のように書き換えます。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="FigmaApps.MainPage">
    <ScrollView>
            <GraphicsView //GraphicsViewの追加  
                x:Name="figmaSample"/>
    </ScrollView>
</ContentPage>

そして「MainPage.xaml.cs」は以下のように書き換えます。

namespace FigmaApps;

public partial class MainPage : ContentPage
{
	public MainPage()
	{
		InitializeComponent();

        figmaSample.Drawable = new Drawable();//x:Nameと名前をあわせること
	}

	class Drawable:IDrawable //IDrawblewを継承したDrawbleクラスを実装
	{
		public void Draw(ICanvas canvas, RectF dirtyRect)
        {
            //ここに生成したコードをコピペする  ここに書いてあるコードをどう編集していいかはさすがにわかってると思うので割愛
            /////////////////////////////////////////////////////////////////////////////////
            // View:     rectangleView
            // NodeName: Rectangle 1
            // NodeType: RECTANGLE
            // NodeId:   1:4
            canvas.SaveState();
            canvas.SetFillPaint(new LinearGradientPaint { GradientStops = new PaintGradientStop[] { new PaintGradientStop(0, new Color(234, 234, 234, 255)), new PaintGradientStop(1, new Color(234, 234, 234, 130)), } }, new RectF(0f, 0f, 350f, 500f));
            canvas.FillRoundedRectangle(0f, 0f, 350f, 500f, 10f);
            canvas.StrokeColor = Color.FromRgb(0, 0, 0);
            canvas.Alpha = 1;
            canvas.StrokeSize = 1;
            canvas.DrawRoundedRectangle(0f, 0f, 350f, 500f, 10f);
            canvas.RestoreState();

            // View:     rectangleView1
            // NodeName: Rectangle 2
            // NodeType: RECTANGLE
            // NodeId:   1:5
            canvas.SaveState();
            canvas.SetFillPaint(new LinearGradientPaint { GradientStops = new PaintGradientStop[] { new PaintGradientStop(0, new Color(81, 43, 212, 255)), new PaintGradientStop(1, new Color(43, 151, 212, 41)), } }, new RectF(0f, 430f, 350f, 5f));
            canvas.FillRoundedRectangle(0f, 430f, 350f, 5f, 0f);
            canvas.RestoreState();

            // View:     rectangleView2
            // NodeName: Rectangle 3
            // NodeType: RECTANGLE
            // NodeId:   1:7
            canvas.SaveState();
            canvas.SetFillPaint(new LinearGradientPaint { GradientStops = new PaintGradientStop[] { new PaintGradientStop(0, new Color(81, 43, 212, 255)), new PaintGradientStop(1, new Color(81, 43, 212, 89)), } }, new RectF(14f, 446f, 325f, 41f));
            canvas.FillRoundedRectangle(14f, 446f, 325f, 41f, 20f);
            canvas.RestoreState();

            // View:     elipseView
            // NodeName: Ellipse 1
            // NodeType: ELLIPSE
            // NodeId:   1:8
            canvas.SaveState();
            canvas.SetFillPaint(new LinearGradientPaint { GradientStops = new PaintGradientStop[] { new PaintGradientStop(0, new Color(81, 43, 212, 255)), new PaintGradientStop(1, new Color(43, 151, 212, 41)), } }, new RectF(19f, 28f, 116f, 116f));
            canvas.StrokeSize = 5;
            canvas.DrawEllipse(19f, 28f, 116f, 116f);
            canvas.RestoreState();

            // View:     textView
            // NodeName: Name
            // NodeType: TEXT
            // NodeId:   1:9
            canvas.SaveState();
            canvas.FontColor = Color.FromRgb(0, 0, 0);
            canvas.Alpha = 1;
            canvas.Font = new Microsoft.Maui.Graphics.Font("Shrikhand-Regular", 400, FontStyleType.Normal);
            canvas.FontSize = 16f;
            canvas.DrawString(@"Name", 175f, 28f, 63f, 23f, HorizontalAlignment.Left, VerticalAlignment.Top);
            canvas.RestoreState();

            // View:     rectangleView3
            // NodeName: Rectangle 4
            // NodeType: RECTANGLE
            // NodeId:   1:10
            canvas.SaveState();
            canvas.SetFillPaint(new RadialGradientPaint { GradientStops = new PaintGradientStop[] { new PaintGradientStop(0, new Color(81, 43, 212, 255)), new PaintGradientStop(1, new Color(139, 117, 214, 255)), new PaintGradientStop(1, new Color(217, 217, 217, 255)), } }, new RectF(30f, 200f, 50f, 50f));
            canvas.FillRoundedRectangle(30f, 200f, 50f, 50f, 10f);
            canvas.RestoreState();

            // View:     rectangleView4
            // NodeName: Rectangle 5
            // NodeType: RECTANGLE
            // NodeId:   1:11
            canvas.SaveState();
            canvas.SetFillPaint(new RadialGradientPaint { GradientStops = new PaintGradientStop[] { new PaintGradientStop(0, new Color(43, 151, 212, 255)), new PaintGradientStop(1, new Color(43, 151, 212, 0)), } }, new RectF(30f, 270f, 50f, 50f));
            canvas.FillRoundedRectangle(30f, 270f, 50f, 50f, 10f);
            canvas.RestoreState();

            // View:     rectangleView5
            // NodeName: Rectangle 6
            // NodeType: RECTANGLE
            // NodeId:   1:12
            canvas.SaveState();
            canvas.FillColor = Color.FromRgb(163, 242, 143);
            canvas.Alpha = 1;
            canvas.FillRoundedRectangle(30f, 340f, 50f, 50f, 10f);
            canvas.RestoreState();

            // View:     imageView
            // NodeName: Vector 1
            // NodeType: VECTOR
            // NodeId:   1:16

            // View:     textView1
            // NodeName: MAUI
            // NodeType: TEXT
            // NodeId:   1:17
            canvas.SaveState();
            canvas.FontColor = Color.FromRgb(0, 0, 0);
            canvas.Alpha = 1;
            canvas.Font = new Microsoft.Maui.Graphics.Font("Shrikhand-Regular", 400, FontStyleType.Normal);
            canvas.FontSize = 16f;
            canvas.DrawString(@"MAUI", 88f, 184f, 47f, 23f, HorizontalAlignment.Left, VerticalAlignment.Top);
            canvas.RestoreState();

            // View:     textView2
            // NodeName: .Net MAUI High School
            // NodeType: TEXT
            // NodeId:   1:22
            canvas.SaveState();
            canvas.FontColor = Color.FromRgb(0, 0, 0);
            canvas.Alpha = 1;
            canvas.Font = new Microsoft.Maui.Graphics.Font("Rakkas-Regular", 400, FontStyleType.Normal);
            canvas.FontSize = 16f;
            canvas.DrawString(@".Net MAUI High School", 96f, 213f, 153f, 24f, HorizontalAlignment.Left, VerticalAlignment.Top);
            canvas.RestoreState();

            // View:     textView3
            // NodeName: TwitterAccount
            // NodeType: TEXT
            // NodeId:   1:24
            canvas.SaveState();
            canvas.FontColor = Color.FromRgb(0, 0, 0);
            canvas.Alpha = 1;
            canvas.Font = new Microsoft.Maui.Graphics.Font("Rakkas-Regular", 400, FontStyleType.Normal);
            canvas.FontSize = 16f;
            canvas.DrawString(@"TwitterAccount", 96f, 289f, 103f, 24f, HorizontalAlignment.Left, VerticalAlignment.Top);
            canvas.RestoreState();

            // View:     textView4
            // NodeName: QiitaAccount
            // NodeType: TEXT
            // NodeId:   1:25
            canvas.SaveState();
            canvas.FontColor = Color.FromRgb(0, 0, 0);
            canvas.Alpha = 1;
            canvas.Font = new Microsoft.Maui.Graphics.Font("Rakkas-Regular", 400, FontStyleType.Normal);
            canvas.FontSize = 16f;
            canvas.DrawString(@"QiitaAccount", 96f, 358f, 87f, 24f, HorizontalAlignment.Left, VerticalAlignment.Top);
            canvas.RestoreState();

            // View:     textView5
            // NodeName: Twitter
            // NodeType: TEXT
            // NodeId:   1:18
            canvas.SaveState();
            canvas.FontColor = Color.FromRgb(0, 0, 0);
            canvas.Alpha = 1;
            canvas.Font = new Microsoft.Maui.Graphics.Font("Shrikhand-Regular", 400, FontStyleType.Normal);
            canvas.FontSize = 16f;
            canvas.DrawString(@"Twitter", 88f, 254f, 64f, 23f, HorizontalAlignment.Left, VerticalAlignment.Top);
            canvas.RestoreState();

            // View:     textView6
            // NodeName: Qiita
            // NodeType: TEXT
            // NodeId:   1:20
            canvas.SaveState();
            canvas.FontColor = Color.FromRgb(0, 0, 0);
            canvas.Alpha = 1;
            canvas.Font = new Microsoft.Maui.Graphics.Font("Shrikhand-Regular", 400, FontStyleType.Normal);
            canvas.FontSize = 16f;
            canvas.DrawString(@"Qiita", 88f, 324f, 41f, 23f, HorizontalAlignment.Left, VerticalAlignment.Top);
            canvas.RestoreState();
        }
    }
}

Figmaで作成.png

これで完了になります。

Visual StudioはIDEでありTeacherです。

image.png
影がないなと思ったらつければいいのです。
shadowをつけようと思ったら勝手にSetShadowが出てきてその引数が何のかさえ教えてくれます。
こんな感じでVisual Studioをうまく使っていきましょう。先生最高!!

不具合など

見たらわかると思いますが、変換がうまくいってない箇所が多少見受けられます。
それらの理由や対処法などご紹介できればと思います。

・Elipeseのグラデーションができない。→ソフト的には未対応。しかしコードを書き替えることによって対応は可能
・ドロップシャドウがついてない→ソフト的には未対応。しかしコードを付け足すことによって対応は可能(canvas.SetShadow())
・パスが描かれない→ソフト的に未対応詳細はこちら(https://github.com/jsuarezruiz/figma-to-maui-graphics#known-limitations-or-issues)
・不具合ではないですがコンポーネントのX,Yの値を0にそろえていないとうまく変換されないようです。↑参照
・フォントが変わっていない→.NET MAUIプロジェクトに対応するフォントを入れ込めば反映可能
・3つボタンの上2つがうまく変換できていない→下の図のように決められたサイズの枠からはみ出してコンポーネントを作ったための不具合。きちんとルールにのっとれば可能
gurade-syonn.png

さいごに

以上がFigmaのデザインを.NET MAUIへ持ってくる方法の紹介となりました。

多少の不具合はありますがこんなに簡単にFigmaで作ったデザインをモバイルアプリのUIを構築できる方法は今のところないと思います。
(あっても多少のお金がかかったり、操作が大変であったり)

今回私が自作したデザインで試しましたが、ほかのFigmaユーザーが作成したデザインであってもコピーを取得し、URLさえ入手できればどのものでも生成が可能です。

UIコンポーネントくらいならかなり良い感じで爆速で生成ができますね。

4
7
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
4
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?