1. 始める前に
この Codelab では、Image
コンポーザブルを使用してアプリに画像を追加する方法を学びます。
前提条件
- Android Studio でアプリを作成して実行する方法についての基本的な知識
- テキスト コンポーザブルなどの UI 要素を追加する方法についての基本的な知識
学習内容
- Android アプリに画像や写真を追加する方法
Image
コンポーザブルを使用してアプリに画像を表示する方法String
リソースを使用する際のおすすめの方法
作成するアプリの概要
- Happy Birthday アプリを拡張して、画像を追加します。
必要なもの
- Android Studio がインストールされているパソコン
- テキスト コンポーザブルを使用してシンプルなアプリを作成する Codelab で作成したアプリ
2. アプリを設定する
Android Studio で、前の Codelab で作成した Happy Birthday プロジェクトを開きます。
アプリを実行すると、次のスクリーンショットのようになります。
プロジェクトに画像を追加する
このタスクでは、インターネットから画像をダウンロードし、Happy Birthday アプリに追加します。
- こちらのリンクから誕生日カードアプリの画像を開きます。
- [ダウンロード] をクリックします。
- 画像を右クリックし、パソコンに
androidparty.png
というファイル名で保存します。 - 画像の保存先をメモしておきます。
以下の例では、[ダウンロード] フォルダに保存したものとして説明します。
- Android Studio のメニューで、[View] > [Tool Windows] > [Resource Manager] をクリックするか、[Project] ウィンドウの横にある [Resource Manager] タブをクリックします。
- [+](モジュールにリソースを追加)> [Import Drawables] をクリックします。
- ファイル ブラウザで、ダウンロードした画像ファイルを選択して [Open] をクリックします。
この操作により、[Import drawables] ダイアログが開きます。
- Android Studio に画像のプレビューが表示されます。[QUALIFIER TYPE] プルダウン リストから [Density] を選択します。この操作を行う理由については、後のセクションで説明します。
- [VALUE] リストから [No Density] を選択します。
Android デバイスは、画面サイズ(スマートフォン、タブレット、TV など)だけでなく、画面のピクセルサイズもさまざまです。1 平方インチあたり 160 ピクセルのデバイスもあれば、480 ピクセルのデバイスもあります。ピクセル密度の違いを考慮しないと、画像が拡大されてぼやける、メモリを大量に消費する大きな画像になる、あるいは不適切にサイズ変更された画像になることがあります。
Android システムが処理できるよりも大きな画像のサイズを変更しようとすると、メモリ不足エラーがスローされます。写真であったり、現在の画像 androidparty.png
のような背景画像であったりする場合は、drawable-nodpi
フォルダに置く必要があります。ここに置くとサイズ変更が行われなくなります。
ピクセル密度について詳しくは、各種のピクセル密度をサポートするをご覧ください。
- [Next] をクリックします。
- Android Studio に、画像が配置されるフォルダ構造が表示されます。先ほど説明した
drawable-nodpi
フォルダがあるはずです。 - [Import(C)] をクリックします。
Android Studio によって drawable-nodpi
フォルダが作成され、そこに画像が配置されます。Android Studio のプロジェクト ビューに、androidparty.png (nodpi)
というリソース名で表示されます。Android Studio によって、パソコンのファイル システムに drawable-nodpi
というフォルダが作成されます。
画像が正常に読み込まれると、Android Studio によって画像が [Drawable] タブのリストに追加されます。このリストには、アプリのすべての画像とアイコンが入っています。これで、この画像をアプリで使用できるようになりました。
- [View] > [Tool Windows] > [Project] をクリックするか、左端の [Project] タブをクリックして、プロジェクト ビューに戻ります。
- [app] > [res] > [drawable] をクリックして、画像が
drawable
フォルダにあることを確認します。
3. Image コンポーザブルを追加する
アプリに画像を表示するには、画像を表示する場所が必要です。Text
コンポーザブルを使用してテキストを表示する場合と同じようにして、Image
コンポーザブルを使用して画像を表示できます。
このタスクでは、Image
コンポーザブルをアプリに追加し、ダウンロードした画像をアプリの画像に設定して、その画像のサイズと位置を画面内に収まるように調整します。
画像を追加するためにコンポーズ可能な関数を追加する
MainActivity.kt
ファイルで、GreetingText()
関数の後にコンポーズ可能な関数GreetingImage()
を追加します。GreetingImage()
関数に 2 つのString
パラメータを渡します。一つは誕生日祝いのメッセージのmessage
、もう一つは署名のfrom
です。
@Composable
fun GreetingImage(message: String, from: String) {
}
- すべてのコンポーズ可能な関数は、オプションの
Modifier
パラメータを受け入れる必要があります。修飾子は、UI 要素に対して親レイアウト内での配置、表示、動作を指示します。GreetingImage()
コンポーザブルで別のパラメータを追加します。
@Composable
fun GreetingImage(message: String, from: String, modifier: Modifier = Modifier) {
}
Jetpack Compose のリソース
リソースとは、コードが使用する追加のファイルと静的コンテンツであり、ビットマップ、ユーザー インターフェース文字列、アニメーション命令などがあります。Android のリソースについて詳しくは、アプリリソースの概要をご覧ください。
画像や文字列などのアプリリソースは必ずコードとは別にする必要があります。それにより、コードとは独立して管理できるようになります。実行時に、Android は現在の設定に基づいて適切なリソースを使用します。たとえば、画面サイズごとに異なる UI レイアウトや言語設定ごとに異なる文字列を指定できます。
リソースのグループ化
リソースは種類ごとにプロジェクトの res/
ディレクトリの対応するサブディレクトリに保存する必要があります。たとえば、単純なプロジェクトのファイル階層の例を次に示します。
MyProject/
src/
MyActivity.kt
res/
drawable/
graphic.png
mipmap/
icon.png
values/
strings.xml
この例では、res/
ディレクトリのサブディレクトリにすべてのリソースが保存されていて、画像リソースは drawable/
ディレクトリ、ランチャー アイコンは mipmap/
ディレクトリ、文字列リソースは values/
ディレクトリに入ります。アプリリソースの使用方法、形式、構文の詳細については、リソースタイプの概要をご覧ください。
リソースへのアクセス
Jetpack Compose は、Android プロジェクトで定義されたリソースにアクセスできます。リソースにアクセスするには、プロジェクトの R
クラスで生成されたリソース ID を使用します。
R
クラスは、Android によって自動生成されたクラスであり、プロジェクト内のすべてのリソースの ID を含むクラスです。ほとんどの場合、リソース ID はファイル名と同じになります。たとえば、前のファイル階層の画像にアクセスするには、次のコードを使用します。
R.drawable.graphic
次のタスクでは、前のタスクに追加した画像ファイル androidparty.png
を使用します。
GreetingImage()
関数の中で、image
という名前のval
プロパティを宣言します。androidparty
リソースを渡してpainterResource()
関数を呼び出します。その戻り値をimage
変数に代入します。
val image = painterResource(R.drawable.androidparty)
アプリをコンパイルするには関数をインポートする必要があるため、Android Studio は painterResource
コードをハイライト表示します。
- Android Studio でハイライト表示されている
.painterResource
をクリックします。 - ポップアップで [Import] をクリックし、
androidx.compose.ui.res.painterResource
のインポートを追加します。
painterResource()
関数は、ドローアブル画像リソースを読み込みます。引数としてリソース ID(この場合は R.drawable.androidparty
)を取ります。
painterResource()
関数の呼び出しの後に、Image
コンポーザブルを追加し、painter
という名前付きの引数としてimage
を渡します。
Image(
painter = image
)
アプリをコンパイルするには関数をインポートする必要があるため、Android Studio は Image
コードをハイライト表示します。
この警告を解決するには、MainActivity.kt
ファイルの先頭に次のインポートを追加します。
import androidx.compose.foundation.Image
最初の警告は解決されましたが、Android Studio で単語 Image
にカーソルを合わせると、[None of the following functions can be called with the arguments supplied] という新しい警告が表示されます。これは、提供された引数が Image
関数シグネチャのいずれとも一致しないためです。
この警告は次のセクションで解決します。
アプリのユーザー補助対応を確認する
ユーザー補助を意識したコーディング習慣に従うことで、障がいを持つユーザーを含めた、すべてのユーザーがアプリ内の移動やアプリの操作を簡単に行えるようになります。
Android Studio により、アプリのユーザー補助機能を強化するためのヒントと警告が提供されます。コンテンツの説明を使って UI 要素の目的を定義することで、TalkBack でアプリを利用しやすくなります。
しかし、このアプリの画像は装飾目的のみで使用されています。この場合は、画像にコンテンツの説明を追加すると TalkBack で利用しにくくなります。読み上げられるコンテンツの説明を設定するのではなく、画像の contentDescription
引数を null
に設定すれば、TalkBack が Image
コンポーザブルをスキップするようにできます。
Image
コンポーザブルに、contentDescription
という名前付き引数を追加し、その値はnull
に設定します。
Image(
painter = image,
contentDescription = null
)
Image
コンポーザブルをプレビューする
このタスクでは、画像コンポーザブルをプレビューし、アプリをエミュレータまたはデバイスで実行します。
BirthdayCardPreview()
関数内のGreetingText()
関数の呼び出しをGreetingImage()
関数の呼び出しに置き換えます。
関数は次のコード スニペットのようになります。
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
HappyBirthdayTheme {
GreetingImage(
message = "Happy Birthday Sam!",
from = "From Emma"
)
}
}
- [Design] ペインは自動更新されます。更新されない場合は、[] をクリックしてビルドします。
すると、テキストが表示されなくなります。これは、新しい関数には Image
コンポーザブルがあるだけで、Text
コンポーザブルがなくなっているためです。
4. Box レイアウトを追加する
Compose には、基本的な標準レイアウト要素として、Column
、Row
、Box
の 3 つのコンポーザブルがあります。Column
コンポーザブルと Row
コンポーザブルについては前の Codelab で学習したので、ここでは Box
コンポーザブルについて詳しく学びます。
Box
レイアウトは、Compose の標準レイアウト要素の一つです。Box
レイアウトは、要素を別の要素の上に重ねるときに使用します。また、Box
レイアウトを使用すると、それに含まれる要素の配置も設定することもできます。
- 次のように、
GreetingImage()
関数内のImage
コンポーザブルをBox
コンポーザブルで囲みます。
@Composable
fun GreetingImage(message: String, from: String, modifier: Modifier = Modifier) {
val image = painterResource(R.drawable.androidparty)
Box {
Image(
painter = image,
contentDescription = null
)
}
}
- Android Studio にプロンプトが表示されたら、
androidx.compose.foundation.layout.Box
関数をインポートします。 modifier
パラメータをBox
コンポーザブルに渡すコードを追加します。
@Composable
fun GreetingImage(message: String, from: String, modifier: Modifier = Modifier) {
val image = painterResource(R.drawable.androidparty)
Box(modifier) {
Image(
painter = image,
contentDescription = null
)
}
}
- 次のように、
Box
コンポーザブルの最後でGreetingText()
関数を呼び出し、誕生日メッセージと署名および修飾子を渡します。
@Composable
fun GreetingImage(message: String, from: String, modifier: Modifier = Modifier) {
val image = painterResource(R.drawable.androidparty)
Box(modifier) {
Image(
painter = image,
contentDescription = null
)
GreetingText(
message = message,
from = from,
modifier = Modifier
.fillMaxSize()
.padding(8.dp)
)
}
}
- [Design] ペインでプレビューが更新されます。
すると、テキストと画像が表示されます。
- この変更をエミュレータまたはデバイスに反映させるために、
onCreate()
関数内のGreetingText()
関数の呼び出しをGreetingImage()
関数の呼び出しに置き換えます。
その結果、setContent
ブロックは次のコード スニペットのようになります。
setContent {
HappyBirthdayTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
GreetingImage(
message = "Happy Birthday Sam!",
from = "From Emma"
)
}
}
}
画像は、画面と同じ幅になっていますが、画面の上側に寄せられています。画面の下側に空白があるので、あまり見栄えが良くありません。次のタスクでは、画面の上下左右に空白を作らないように、画像のサイズを画面全体のサイズに合わせます。
5. 不透明度を変更し、画像を拡大縮小する
このタスクでは、アプリの見栄えを良くするために画像が全画面に表示されるようにします。そのために、ContentScale
パラメータを使用します。
コンテンツのサイズを調整する
アプリに画像を追加して、画像の位置設定を行いました。次は、画像のスケーリングの種類(画像のサイズの調整方法)を設定して、画像が全画面に表示されるようにします。
ContentScale
には多数の種類が用意されています。ここでは ContentScale.Crop
パラメータを使用し、画像の幅と高さが、それぞれ画面の幅と高さと等しいかそれ以上になるように、アスペクト比を維持しながら均等に画像を拡大します。
- Image に
ContentScale
の名前付き引数を追加します。
Image(
painter = image,
contentDescription = null,
contentScale = ContentScale.Crop
)
- Android Studio にプロンプトが表示されたら、
androidx.compose.ui.layout.ContentScale
インターフェースをインポートします。 - [Design] ペインを確認します。
すると、次のスクリーンショットのように、画像がプレビュー画面全体に表示されます。
不透明度の変更
アプリのコントラストを向上させるには、背景画像の不透明度を変更します。
alpha
パラメータを Image
コンポーザブルに追加し、0.5F
に設定します。
Image(
painter = image,
contentDescription = null,
contentScale = ContentScale.Crop,
alpha = 0.5F
)
画像の不透明度が変更されます。
大量のコードになりましたが、その結果をプレビューしましょう。
アプリを実行する
デバイスまたはエミュレータでアプリを実行します。
全画面の画像とテキスト メッセージが表示されるようにできました。また、画像の不透明度も変更しました。
レイアウト修飾子
修飾子は、Jetpack Compose UI 要素の装飾や、その動作の追加に使用されます。たとえば、行やテキスト、ボタンに、背景やパディング、動作を追加できます。このような設定をするには、コンポーザブルまたはレイアウトが修飾子をパラメータとして受け取る必要があります。
前回の Codelab で修飾子について説明した際には、パディング修飾子(Modifier.padding
)を使用して、Text
コンポーザブルの周囲に空白を追加しました。修飾子には多くの機能がありますが、それらは今回と以降で説明します。
たとえば、次の Text
コンポーザブルには背景を緑色にする Modifier
引数があります。
// Example
Text(
text = "Hello, World!",
// Solid element background color
modifier = Modifier.background(color = Color.Green)
)
上記の例と同様に、引数と引数修飾子をレイアウトに追加することで、Arrangement プロパティと Alignment プロパティを使用して子要素を配置できます。
Row
内の子の位置を設定するには、horizontalArrangement
引数と verticalAlignment
引数を設定します。Column
の場合は、verticalArrangement
引数と horizontalAlignment
引数を設定します。
Arrangement プロパティは、レイアウトのサイズが子の合計よりも大きい場合に、子要素を配置するために使用されます。
たとえば、Column
のサイズが子のサイズの合計よりも大きい場合、verticalArrangement
を指定して Column
内の子の位置を定義できます。以下に、さまざまな垂直配置の図を示します。
同様に、Row
のサイズが子のサイズの合計よりも大きい場合は、horizontalArrangement
を指定して Row
内の子の位置を定義できます。以下に、さまざまな水平配置の図を示します。
Alignment プロパティは、子要素をレイアウトの先頭、中央、末端に配置するために使用されます。
6. テキストの配置を調整する
このタスクでは、前の Codelab でアプリにテキストを配置するために追加したコードを確認します。
MainActivity.kt
ファイルで、GreetingText()
関数までスクロールします。この列のverticalArrangement
プロパティはArrangement.Center
に設定されています。テキスト コンテンツは画面の中央に配置されます。
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
Column(
verticalArrangement = Arrangement.Center,
modifier = modifier
) {
Text(
text = message,
fontSize = 100.sp,
lineHeight = 116.sp,
textAlign = TextAlign.Center
)
Text(
text = from,
fontSize = 36.sp,
modifier = Modifier
.padding(16.dp)
.align(alignment = Alignment.End)
)
}
}
パディング
UI 要素はコンテンツを囲んでいます。余白が狭すぎないようにするために、上下左右のパディングの量を指定できます。
パディングは修飾子として使用されるので、任意のコンポーザブルに適用できます。padding
修飾子は、コンポーザブルの上下左右のそれぞれに対してパディングの量を定義するオプションの引数を取ります。
// This is an example.
Modifier.padding(
start = 16.dp,
top = 16.dp,
end = 16.dp,
bottom = 16.dp
)
- 実践しましょう。
MainActivity.kt
ファイルで、GreetingText()
関数が呼び出されるところまでスクロールし、パディング属性を確認します。
modifier = Modifier
.fillMaxSize()
.padding(8.dp)
- 同様に、
GreetingText()
関数の内側で、署名のText
コンポーザブルのパディングも確認します。
modifier = Modifier
.padding(16.dp)
.align(alignment = Alignment.End)
7. 適切なコード プラクティスを採用する
翻訳
アプリを作成する際には、どこかの時点で別の言語に翻訳される可能性があることを知っておいてください。前の Codelab で学んだように、String
というデータ型は "Happy Birthday Sam!"
のような文字の並びです。
「ハードコード」された文字列とは、アプリのコードに直接書き込まれた文字列です。ハードコードされた文字列を使用すると、アプリを他の言語に翻訳するのが難しくなり、アプリの文字列を別の場所で再利用するのが難しくなります。この問題は、文字列をリソース ファイルに抽出することで解決できます。具体的には、文字列をコード内にハードコードする代わりに別のファイルに格納して、文字列リソースに名前を付けます。文字列を使用するときには、この名前を使用するようにします。文字列を変更したり、他の言語に翻訳したりしても、名前は変わりません。
MainActivity.kt
ファイルで、onCreate()
関数までスクロールします。誕生日祝いのメッセージ(Happy Birthday Sam!
文字列、引用符なし)を選択します。- 画面左側の電球アイコンをクリックします。
- [Extract string resource] を選択します。
Android Studio で [Extract Resource] ダイアログが開きます。このダイアログでは、文字列リソースの名前と保存方法の詳細をカスタマイズできます。[Resource name] フィールドには、文字列の名前を入力します。[Resource value] には、実際の文字列を入力します。
- [Extract Resource] ダイアログで、[Resource name] を
happy_birthday_text
に変更します。
文字列リソースの名前には小文字を使用し、複数の単語はアンダースコアで区切るようにします。他の設定はデフォルトのままにします。
- [OK] をクリックします。
- コードの変更点を確認しましょう。
ハードコードされた文字列が getString()
関数の呼び出しに置き換えられています。
GreetingImage(
message = getString(R.string.happy_birthday_text),
from = "From Emma",
modifier = Modifier.padding(8.dp)
)
- [Project] ペインでパス
app > res > values > strings.xml
の strings.xml ファイルを開くと、happy_birthday_text
という文字列リソースが Android Studio により作成されたのがわかります。
<resources>
<string name="app_name">Happy Birthday</string>
<string name="happy_birthday_text">Happy Birthday Sam!</string>
</resources>
strings.xml
ファイルには、アプリによってユーザーに表示される文字列のリストが入っています。アプリの名前も文字列リソースです。文字列をすべて 1 か所にまとめることで、アプリ内のテキストの翻訳が簡単になり、アプリの別の場所で文字列を再利用するのも簡単になります。
- 同じ手順で署名である
Text
コンポーザブルのテキストを抽出しますが、今度は [Resource name] フィールドにsignature_text
を入力します。
完成したファイルは以下のようになります。
<resources>
<string name="app_name">Happy Birthday</string>
<string name="happy_birthday_text">Happy Birthday Sam!</string>
<string name="signature_text">From Emma</string>
</resources>
stringResource()
と抽出された文字列を使用するようにBirthdayCardPreview()
を更新します。
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
HappyBirthdayTheme {
GreetingImage(
message = stringResource(R.string.happy_birthday_text),
from = stringResource(R.string.signature_text)
)
}
}
- アプリをもう一度実行し、変わらず動作していることを確認します。
8. 課題に挑戦しましょう
アプリに画像を追加できたところで、次の課題に挑戦しましょう。
- 署名テキスト コンポーザブルを画面の中央に揃えて配置します。
アプリでの表示は次のようになります。
参考までに、GreetingText()
関数の解答コードは次のようになります。
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
Column(
verticalArrangement = Arrangement.Center,
modifier = modifier
) {
Text(
text = message,
fontSize = 100.sp,
lineHeight = 116.sp,
textAlign = TextAlign.Center
)
Text(
text = from,
fontSize = 36.sp,
modifier = Modifier
.padding(16.dp)
.align(alignment = Alignment.CenterHorizontally)
)
}
}
9. 解答コードを取得する
Happy Birthday アプリの解答コードは GitHub に掲載されています。
GitHub は、デベロッパーがソフトウェア プロジェクトのコードを管理できるようにするサービスです。Git という、コードの各バージョンで行われた変更を追跡するバージョン管理システムが使用されています。Google ドキュメントの変更履歴を見ると、いつ、どのような編集が行われたかを確認できます。同じように、プロジェクト内のコードのバージョン履歴を追跡できます。この機能は、プロジェクトに個人として取り組んでいる場合にも、チームとして取り組んでいる場合にも便利です。
GitHub には、プロジェクトの表示や管理ができるウェブサイトもあります。次の GitHub のリンクを使用すると、Happy Birdthday プロジェクトのファイルをオンラインで閲覧したり、パソコンにダウンロードしたりできます。
この Codelab の完成したコードをダウンロードするには、次の git コマンドを使用します。
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-birthday-card-app.git
または、リポジトリを ZIP ファイルとしてダウンロードし、Android Studio で開くこともできます。
解答コードを確認する場合は、GitHub で表示します。
GitHub におけるブランチ
ブランチとは何かを理解する前に、リポジトリ(リポ)とは何かを理解しておきましょう。リポジトリとは、プロジェクト全体(ディレクトリとファイル)であり、そのクローン(コピー)をパソコンに作成します。ブランチとは、リポジトリのあるバージョン、つまり独立した開発の系統のことです。たとえば、このコースの starter ブランチは、Codelab の間のコード作成に使用したバージョンかもしれません。main ブランチまたは solution ブランチは、Codelab の最後となるバージョンであり、完全な解答コードが入っているものです。
リポジトリには複数のブランチを作ることができます。つまり、リポジトリには複数バージョンのコードがあります。
10. まとめ
Happy Birthday アプリに画像を追加し、テキストを修飾子で整列して、ユーザー補助のガイドラインを遵守するようにし、他の言語に翻訳しやすくしました。そして、さらに重要なこととして、ご自分の Happy Birthday アプリを完成させました。作品をソーシャル メディアで共有し、ハッシュタグ #AndroidBasics を使って皆にわかるようしましょう。
概要
- Android Studio の [Resource Manager] タブを使用すると、画像やその他のリソースを追加して配置することができます。
Image
コンポーザブルは、アプリに画像を表示する UI 要素です。- アプリのユーザー補助機能を改善するために、
Image
コンポーザブルにコンテンツの説明を付ける必要があります。 - 誕生日祝いのメッセージなどのユーザーに表示するテキストは、文字列リソースに抽出して、アプリを他の言語に翻訳しやすくする必要があります。