目次

03.共通UIコンポーネントの作成

今後の保守性や開発の進め方を考え、画面(機能)ごとにモジュールを作成することにします。

今回は、下記のモジュール構成で進めていきます。

uiモジュールの作成

トップディレクトリで:core:uiモジュールを作成します。

android:studio:application:app:android-app0201.png

モジュールの作成

プロジェクト直下で新規モジュールを作成します。

android:studio:application:app:android-app0202.png

uiモジュール情報の入力

画面(Activity)は不要なのでAndroid Libraryを選択します。

Module nameは『:core:ui』にしています。

Package nameは『jp.co.progress_llc.portal.core.ui』にします。

完了(F)』でモジュールがcore/uiに作成されます。

javaディレクトリ名の変更

:appモジュールと同様に/core/ui/src/main/java/… のディレクトリ名を /core/ui/src/main/kotlin/… に変更します。
※変更しなくても構いません。

/core/ui/src/androidTest/java、/core/ui/src/test/java も同様にkotlinに変更します。

サンプルテストクラスの削除

サンプルテストクラスは、残しておくと依存の関係でコンパイルエラーが出ることがありますので削除します。

下記のファイルを削除します。

Composite Buildへの対応

/build-logic/src/main/kotlin内にライブラリモジュールのbuild.gradle.ktsで使用するビルドプラグインを作成します。
ファイル名をLibraryConfigurePlugin.ktにしています。

package jp.co.progress_llc.buildlogic

import com.android.build.api.dsl.LibraryExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies

class LibraryConfigurePlugin: Plugin<Project> {
  override fun apply(project: Project) = with(project) {
    with(pluginManager) {
      apply("com.android.library")
      apply("org.jetbrains.kotlin.android")
      apply("com.google.devtools.ksp")
    }
    extensions.configure<LibraryExtension> {
      configureCommonExtension(this)
      defaultConfig.consumerProguardFiles("consumer-rules.pro")
      buildTypes {
        release {
          isMinifyEnabled = false
          proguardFiles(
            getDefaultProguardFile("proguard-android-optimize.txt"),
            "proguard-rules.pro"
          )
        }
      }
    }
    dependencies {
      add("implementation", project.libs().findLibrary("androidx-core-ktx").get())
      add("implementation", project.libs().findLibrary("androidx-appcompat").get())
      add("implementation", project.libs().findLibrary("material").get())
    }
  }
}

12行目~13行目
Libraryモジュールで使用するプラグインを定義しています。
/core/ui/build.gradle.kts内のpluginsブロックを参照して指定します。
14行目
KSPのプラグインを定義しています。
17行目
ConfigureExtension.ktで作成した全モジュールの共通定義を呼び出しています。
18行目
/core/ui/build.gradle.kts内のandroid/defaultConfigブロックを参照して指定します。
minSdkConfigureExtension.ktで定義済です。
testInstrumentationRunnerはビルドプラグインでは定義しません。
19行目~27行目
/core/ui/build.gradle.kts内のandroid/buildTypesブロックを参照して指定します。
30行目~32行目
dependenciesブロックの依存ライブラリを定義しています。
/core/ui/build.gradle.kts内のdependenciesブロックを参照して指定します。
テスト関連の依存ライブラリはビルドプラグインでは定義しません。
バージョンカタログを参照しています。

LibraryConfigurePluginの適用

作成したビルドプラグインをモジュールのbuild.gradle.ktsで使用できるようにbuild-logic直下のbuild.gradle.ktsに追記します。

   :
gradlePlugin {
   :
  plugins {
    register("LibraryConfigurePlugin") {
      id = "build.logic.library.configure"
      implementationClass = "jp.co.progress_llc.buildlogic.LibraryConfigurePlugin"
    }
  }
}

dependencies {
   :

5行目
任意の名前で名称を定義しています。
6行目
任意の名前でプラグインのidを定義しています。
7行目
プラグインを実装しているクラスを指定します。
/build-logic/src/main/kotlin内に作成したLibraryConfigurePlugin.ktで定義しているクラス名です。

追記後、『Sync Now』で内容をプロジェクトに反映させます。

:core:uiモジュールのbuild.gradle.ktsに作成したビルドプラグインを適用します。

plugins {
  alias(libs.plugins.android.library)
  alias(libs.plugins.kotlin.android)
  id("build.logic.library.configure")
  id("org.jetbrains.kotlin.plugin.compose")
}

android {
  namespace = "jp.co.progress_llc.portal.core.ui"
  compileSdk {
    version = release(36)
  }

  defaultConfig {
    minSdk = 28

    testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    consumerProguardFiles("consumer-rules.pro")
  }

  buildTypes {
    release {
      isMinifyEnabled = false
      proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
    }
  }
  compileOptions {
    sourceCompatibility = JavaVersion.VERSION_11
    targetCompatibility = JavaVersion.VERSION_11
  }
  kotlinOptions {
    jvmTarget = "11"
  }
  buildFeatures {
    compose = true
  }
}

dependencies {

  implementation(libs.androidx.core.ktx)
  implementation(libs.androidx.appcompat)
  implementation(libs.material)
  testImplementation(libs.junit)
  androidTestImplementation(libs.androidx.junit)
  androidTestImplementation(libs.androidx.espresso.core)
  implementation(platform(libs.compose.bom))
  implementation(libs.compose.ui)
  implementation(libs.compose.material)
}

2行目~3行目、10行目~16行目、18行目~33行目、41行目~43行目
ビルドプラグインで定義しているので削除します。
4行目
/build-logic/build.gradle.ktsで定義したビルドプラグインのidを指定します。
5行目
:core:uiモジュールの場合、Jetpack Composeのコンパイラープラグインのidを追加指定します。
17行目、44行目~46行目
:core:uiモジュールではテストを行わないため削除します。
34行目~36行目
Jetpack Composeを有効にします。
47行目~49行目
Jetpack Composeの依存関係を追加します。

適用後、『Sync Now』で内容をプロジェクトに反映させます。

ui定義の移動

:core:uiモジュールを作成しましたので、appモジュールのui定義を:core:uiモジュールに移動させます。

android:studio:application:app:android-app0311.png

リファクタリング

/app/scr/main/…/ui直下のthemeディレクトリを右クリック➡『リファクタリング(R)』➡『パッケージまたはディレクトリの移動…』でディレクトリの移動を行います。

android:studio:application:app:android-app0312.png

ディレクトリの移動

宛先ディレクトリ(D)』をクリックします。

android:studio:application:app:android-app0313.png

移動

宛先ディレクトリ』に:core:uiモジュールのsrc/main/…/core/uiを指定します。

リファクタリング(R)』でディレクトリを移動します。

移動後、/app/scr/main/…/uiディレクトリ内が空になっているので、uiディレクトリを削除します。

appモジュールに:core:uiモジュールへの参照を追加します。

   :
dependencies {
  implementation(project(":core:ui"))
   :

3行目
:core:uiへの依存関係を追加します。

追記後、『Sync Now』で内容をプロジェクトに反映させます。

:appモジュールのMainActivity.kt:appモジュールのuiを参照している定義がありますので:core:uiモジュールを参照するように変更します。

   :
import jp.co.progress_llc.portal.ui.theme.PortalTheme
import jp.co.progress_llc.portal.core.ui.theme.PortalTheme
   :

2行目~3行目
2行目のuicore.uiに変更します。

この時点で、一度エミュレーターで実行してみます。

Hello Android!』がエミュレーターの端末に表示されれば問題ありません。

カスタムテーマの適用

デフォルトのui/themeではなく、Google公式ツールのマテリアルテーマビルダーでカスタムテーマを作成して適用することもできます。

android:studio:application:app:android-app0321.png

ソースカラーの変更

マテリアルテーマビルダーの『Source Color』の色の箇所をクリックします。

※右側の『Random Color』のアイコンをクリックしてランダムに変わる配色を画面上で確認しながら選択することもできます。

android:studio:application:app:android-app0322.png

Color Picker

Hex Color』等で色を指定します。

例では、Light Cyan (0xE0FFFF)を指定しています。

Apply』等で色を適用します。

android:studio:application:app:android-app0323.png

ファイルの保存

マテリアルテーマビルダーの右上のアイコンをクリックします。

android:studio:application:app:android-app0324.png

ファイル名の指定

上部のペンアイコンで保存するファイル名を指定することができます。

Export』をクリックします。

android:studio:application:app:android-app0325.png

ファイル形式の指定

Jetpack Compose (Theme.kt)』を選択します。

指定したファイル名のzipファイルがダウンロードされます。

:core:uiモジュールのscr/main/…/ui/theme内のファイルをダウンロードされたzipファイルの\ui\theme内のファイルに置き換えます。

各ファイルのpackage行を:core:uiモジュールのthemeに変更します。
下記はColor.ktの例です。
同様にTheme.ktType.ktも変更します。

   :
package com.example.compose
package jp.co.progress_llc.portal.core.ui.theme
   :

2行目~3行目
packageを:core:uiモジュールのthemeに変更します。

:appモジュールのMainActivity.ktにあるPortalThemeのimport定義をAppThemeに変更します。

   :
import jp.co.progress_llc.portal.core.ui.theme.PortalTheme
import jp.co.progress_llc.portal.core.ui.theme.AppTheme
   :
    setContent {
      PortalTheme {
      AppTheme {
   :
fun GreetingPreview() {
  PortalTheme {
  AppTheme {
   :

2行目~3行目、6行目~7行目、10行目~11行目
上の行のPortalThemeを下の行のようにAppThemeに変更します。

カスタムテーマを適用させるため、dynamicColorを使用しないようにします。
dynamicColorはデバイス設定や壁紙の色に基づいてアプリの配色を動的に変化させる仕組みです。
デバイス設定や壁紙の色に基づいて配色を動的に変化させるため、カスタムテーマの設定は無視されます。

:core:uiモジュールのTheme.ktの定義を変更します。

   :
fun AppTheme(
   :
  dynamicColor: Boolean = true,
  dynamicColor: Boolean = false,
   :

4行目~5行目
fun AppTheme内のdynamicColorfalseに変更します。