サイトロゴ

Enjoy Creating
Web & Mobile Apps

MENU BOX
WEB
MOBILE
OPEN

ホーム

 > 

 > 

【Jetpack Compose】プロフィールカードで学ぶレイアウトの基本+α

【Jetpack Compose】プロフィールカードで学ぶレイアウトの基本+α

この記事にはプロモーションが含まれています。

Jetpack Composeでは、UIパーツのレイアウトにXMLファイルは使いません。全てコンポーザブル(関数)で調整できるようになっています。

要素を縦に並べたければ Column()、横に並べたければ Row() …というふうに、その仕組みはとてもシンプルで、簡単に扱えるのが大きな特徴です。

とは言え、やや細かいレイアウトの調整を行うとなると、基礎中の基礎の知識だけではさすがに行き詰まってしまいます。

ということで、今回はプロフィールカードを作成しながら、Jetpack Composeにおけるレイアウトの基本+αをご紹介していこうと思います😀

この記事を読むことで分かること
  • ・Jetpack Composeにおける基本的なレイアウト方法
  • ・プロフィールカードふうのレイアウトを行うテクニック

– 目次 –

完成形のイメージを確認

個人開発者の中には、『コーディングしながらデザインを調整していく』という人もいるかと思いますが、一般的には、デザインデータを元に仕様通りにコーディングを行っていきます。

今回はプロフィールカードを作成(レイアウト)していくので、まずはそのデザインデータ(完成形のイメージ)が必要ということになりますね。

ということで、デザインデータを用意しました。できる限りこの完成形と同じになるように、レイアウトを行っていきます。

プロフィールカードのデザインイメージ図

なお、今回はあくまでレイアウト(要素の配置)がテーマであるため、カラーやフォントなど、その他のデザインの要素に関しては特にこだわらなくて良いこととします。

また、Androidアプリ開発においてよく出てくる 【dp(Density-independent Pixels)】 という単位ですが、これはデバイスの画面密度に関係なく、一貫したサイズを表すための単位です。

たとえば、100個のドットで文字や画像を表現できるデバイスと、200個のドットで表現できるデバイスがあり、それぞれ画面の大きさは同じだとしましょう。

このとき、『ドット50個分の大きさ』という方法でサイズを指定すると、100個のドットでは画面の半分の大きさになる一方、200個のドットの画面の方ではそれよりも小さい(画面の1/4サイズ)で表示されることになってしまいます。

これでは画面密度によって大きさが変わってしまうため、dpという画面密度に依存しない単位を用いるのがセオリーとなっています。

何はともあれ完成形のデザインが確認できたので、次のステップでは、さっそくJetpack Composeを使ってレイアウトしていきましょう!

    POINT!
  1. ・基本的には、完成系のデザインデータを元にレイアウトを行っていく!
  2. ・今回はレイアウトに的を絞っているので、その他の要素(カラーなど)に関してはテキトーでOK!
  3. ・dp(Density-independent Pixels)は、画面密度に依存しない大きさを表す単位!

Boxで重ねる

デザインをよく見ると、横並びになっている部分(1)と、縦並びになっている部分(2)、そしてどちらにも該当しない部分(3)があります。

それぞれの並び方を枠線で囲った図

(1)は Row() 、(2)は Column()、そして(3)は Box() コンポザーブルを使ってレイアウトすることができます。

まず、Card コンポーザブルでカードの形をした背景を用意し、その次に(3)のアイコンをレイアウトするための Box() を配置します。

カードのサイズ指定は Card コンポーザブルで行い、Box は親となるCardコンポーザブルの幅いっぱいになるように、Modifier(修飾子)で fillMaxSize() を指定します。

なお、カード内のPadding(余白)は、Boxに指定しておきます。

さらに、後でBoxスコープ内に画像やテキストを配置するので、contentAlignment = Alignment.CenterStart と指定することで、要素が上下の中央かつ左揃えに配置されるようにしておきます。

LayoutSample.kt

@Composable
fun LayoutSample(modifier: Modifier = Modifier) {
   Card(
       modifier = Modifier
           .padding(16.dp)
           .size(width = 300.dp, height = 150.dp)
   ) {
       Box(
           contentAlignment = Alignment.CenterStart,
           modifier = Modifier
               .fillMaxSize()
               .padding(16.dp)
       ) {
          
       }
   }
}

この時点で、表示結果は次のようになります。

上記のコードのプレビュー

Boxは、要素を親要素内に自由な位置に重ねて配置したいときに使うレイアウト用のコンポザーブルです。

今回は、アイコンをCardの右上に配置したいので、Boxスコープ内にIconを配置して、Iconの位置をModifireで .align(Alignment.TopEnd) と指定します。

LayoutSample.kt

@Composable
fun LayoutSample(modifier: Modifier = Modifier) {
   Card(
       modifier = Modifier
           .padding(16.dp)
           .size(width = 300.dp, height = 150.dp)
   ) {
       Box(
           contentAlignment = Alignment.CenterStart,
           modifier = Modifier
               .fillMaxSize()
               .padding(16.dp)
       ) {
           Icon(
               imageVector = Icons.Default.Favorite,
               contentDescription = null,
               tint = MaterialTheme.colorScheme.primary,
               modifier = Modifier
                   .align(Alignment.TopEnd)
           )
       }
   }
}

すると、アイコンがCardの右上に配置されます。

上記のコードのプレビュー(カードの右上にお気に入りアイコンが表示されている)

なお、より実際のアプリに近づけるのであれば、ここはただのIconではなく、IconButton にしてクリック動作を行えるようにすべきところですが、今回は単にアイコンを配置するだけに留めておきます。

次のステップで、残りの要素を一気にレイアウトして完成させていきます!

    POINT!
  1. ・Cardコンポーザブルで、カード風の背景を簡単に作ることができる!
  2. ・Box()は、要素を重ね合わせることができる!
  3. ・Boxスコープ内の要素のModifierに .align(Alignment.TopEnd) を指定すると、Boxの右上に配置される!

RowとColumnで横並びと縦並び

レイアウトの大枠ができたので、次に画像とテキストを配置していきたいと思います。
まず、Row() で画像とテキストを横並びに並べます。

画像のサイズは縦横 100.dp に指定した上で、画像が丸く切り取られるように、clip(CircleShape) を指定します。

なお、画像とテキストの間隔は 8.dp なので、Rowコンポザーブルの horizontalArrangement パラメータに、Arrangement.spaceBy(8.dp) を指定しておきます。

テキスト部分は縦並びなので、Column() を使ってテキストをレイアウトします。

テキスト同士の間隔は 8.dp なので、Columnコンポザーブルの verticalArrangement パラメータに、Arrangement.spaceBy(8.dp) を指定します。

テキストの大きさやフォントに関しては、今回特に指定がないものとして扱いますので、違和感が出ない程度にお好きなように設定してください。

コードと表示結果は次のようになります。

LayoutSample.kt

@Composable
fun LayoutSample(modifier: Modifier = Modifier) {
   Card(
       modifier = Modifier
           .padding(16.dp)
           .size(width = 300.dp, height = 150.dp)
   ) {
       Box(
           contentAlignment = Alignment.CenterStart,
           modifier = Modifier
               .fillMaxSize()
               .padding(16.dp)
       ) {
           Icon(
               imageVector = Icons.Default.Favorite,
               contentDescription = null,
               tint = MaterialTheme.colorScheme.primary,
               modifier = Modifier
                   .align(Alignment.TopEnd)
           )
           Row(
               horizontalArrangement = Arrangement.spacedBy(8.dp),
               modifier = modifier
           ) {
               Image(
                   painter = painterResource(R.drawable.me),
                   contentDescription = "Profile",
                   contentScale = ContentScale.Crop,
                   modifier = Modifier
                       .size(100.dp)
                       .clip(CircleShape)
               )
               Column(
                   verticalArrangement = Arrangement.spacedBy(8.dp)
               ) {
                   Text(
                       text = "Michihiro",
                       style = MaterialTheme.typography.titleLarge
                   )
                   Text(
                       text = "Hi! My name is Michihiro. I'm a developer of Android apps!"
                   )
               }
           }
       }
   }
}
上記のコードのプレビュー(カードレイアウトが完成している)

ということで、無事に完成形のデザインデータと同じようにレイアウトすることができました!

今回、要素の間隔を空けるのに Arrangement.spacedBy() を主に使ってますが、要素が複数あってその間隔が一定ではない場合は、要素に padding() を指定して余白を調整する必要があります。

余白の調整をはじめ、レイアウトを調整する方法は一つだけでなく色んなやり方があるので、状況に応じて効率よく調整できる方法を選択すると良いでしょう。

    POINT!
  1. ・Row() で要素を横並びにレイアウトできる!
  2. ・Column() で要素を縦並びにレイアウトできる!
  3. ・余白の開け方など、調整方法は色々あるので状況に応じて使い分けよう!

« »

カテゴリーリンク

著者について- author profile -

ROYDOプロフィール写真
Michihiro

モバイルアプリ(iOS・Android)ディベロッパー&デザイナー

これまでに、可読性の高いカラーパターンを自動で生成するアプリや、『第3火曜日』といった形式で通知をスケジュールできるアプリなどを制作。

サブでWebデザイン・フロントエンドエンジニアとしても活動しています。

📝ツール・言語:JavaScript/React Native/Kotlin/Android Studio/Swift/SwiftUI

🎓資格:基本情報技術者/ウェブデザイン技能検定3級

Twitterアイコン Instagramアイコン