モバイルアプリのUIを作成する方法を勉強してみます。
大昔のシステム開発ではUIもその裏の処理もプログラムを組んでいましたが、いつの頃からかUIはデザインツールを使ってXMLでレイアウトを作るようになりました。
ですが、最近はUIもプログラムでまた作るようになってきました。元に戻ったのですね。それとも流行の繰り返しでしょうか。
早速、主要なモバイルアプリ開発環境でのUIの作り方を見てみましょう。
SwiftでiOSアプリを開発する時は、
Xcodeに含まれるInterface Builderを使用してXMLのレイアウトファイルを作成していました。これからはSwiftUIでプログラムと同じようにレイアウトを作ります。
// SwiftUIでレイアウトを書くとこんな感じになります。 struct ContentView: View { var body: some View { Text("Hello, World!") .font(.largeTitle) .padding() } }
KotlinでAndroidアプリを開発する時は、
AndroidStudioに含まれるLayout Editorを使用してXMLのレイアウトファイルを作成していました。これからはComposeでプログラムと同じようにレイアウトを作ります。
// Composeでレイアウトを書くとこんな感じになります。 fun AppContent() { Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Text(text = "Hello, World!", style = MaterialTheme.typography.h4) } }
FlutterでiOS, Androidアプリを開発する時は、
プログラムと同じようにDartでレイアウトを作ります。Flutterは最初からレイアウトをプログラムとして記述する方法でした。
SwiftUIやComposeがFlutterのUI作成方法に寄ってきた感じがします。
// Flutterでレイアウトを書くとこんな感じになります。 Widget build(BuildContext context) { return MaterialApp( title: 'Hello World App', home: Scaffold( appBar: AppBar( title: Text('Hello World'), ), body: Center( child: Text('Hello, World!'), ), ), ); }
では、実際に「Hello World」を画面に表示してみます。
SwiftUIでHello World
// // LayoutSample01App.swift // LayoutSample01 // // アプリメイン // Created by mymyser.com on 2023/08/29. // import SwiftUI @main struct LayoutSample01App: App { var body: some Scene { WindowGroup { ContentView() } } }
// // ContentView.swift // LayoutSample01 // // 画面レイアウト // Created by mymyser.com on 2023/08/29. // import SwiftUI struct ContentView: View { var body: some View { Text("Hello World") } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
たった2つのクラスで画面表示だけのアプリができます。XibとObjective-CやStoryBoardとSwiftでアプリを作っていた頃と比べると隔世之感がありますね。
ComposeでHello World
AndroidStudioでプロジェクトを新規作成するときCompose用のテンプレートは出てきません。
公式には出てくるようなことが書いてありますが、新規作成の時にEmpty Activityを選ぶとCompose用のプロジェクトが書き出されます。
package com.mymyser.skf.layout.layoutsample01 import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import com.mymyser.skf.layout.layoutsample01.ui.theme.LayoutSample01Theme // アプリメイン class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { LayoutSample01Theme { Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { Greeting() } } } } } // 画面レイアウト @Composable fun Greeting(modifier: Modifier = Modifier) { Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Text( text = "Hello World", modifier = modifier ) } } @Preview(showBackground = true) @Composable fun GreetingPreview() { LayoutSample01Theme { Greeting() } }
AndroidではXMLのレイアウトを読み込み画面に表示する仕組みでしたが、たった1つのクラスでアプリのメインと画面レイアウトを作ることができます。
LayoutEditorを使って制約やらプロパティやらを設定したり、知らない間にGitでレイアウトファイルの差分が出てしまったり苦労が絶えませんでした。
これからはソースと一体化して扱えるのでComposeへの期待が大きいです。
FlutterでHello World
import 'package:flutter/material.dart'; // アプリメイン void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @override State<MyHomePage> createState() => _MyHomePageState(); } // 画面レイアウト class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return const Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text('Hello World',), ], ), ); } }
Flutterは良いですね。最初からプログラムもレイアウトも同じようにDartで書けます。
操作を覚えるのが大変なレイアウトツールを使わなくても良いです。
別に作ったレイアウトファイルを読み込んだり定義したりもありません。処理とレイアウトをソースコードとして扱えます。
Gitでの差分の管理が楽ですね。
モバイルアプリ開発のUI作成は暫くこれらのように
画面のソースコード + 処理のソースコード
の組み合わせが続くと思います。
Swift, Kotlin, Flutterそれぞれ開発言語・環境は異なりますがその向かっている方向は同じような気がします。