【Jetpack Compose】android初学者がModifierでできることをまとめました

# 初めに
Jetpack Composeを用いたandroid開発について学ぶ中でUIの微調整のためにModifierを使うことが多かったため、主な使われ方(主観)について調べ、まとめました。
なお、当方、この記事が初投稿となります。拙い点もあるかと思いますが、どうか温かい目で見ていただければ幸いです。
## 目次
1. Modifierについて
2. Modifierの活用法(コードと実際の画面)
   1. サイズ・レイアウト
   2. 背景・ボーダー
   3. オブジェクトの配置
   4. スタイル調整
   5. 視覚への効果
3. まとめ
### 対象読者
- android開発初学者の方
## Modifierとは何か
まず、Modifierとは、UIコンポーネント(UIのレンダリングを行う関数)に対して、**外観、レイアウト、動作**などを定義し、文字通り**UIコンポーネントに対しての修飾子**としての役割を果たしています。このModifierを有効に活用することで、UI要素のレイアウトや装飾、動作を柔軟に決定することができるため、複雑なUIを構成するためにはModifierについての理解が非常に重要になります。
## Modifierの活用法

### 1:サイズ・レイアウト
#### - `fillMaxSize`
```Kotlin
@Composable
fun Myfunc(
    text: String = "This is a sample text!",
    modifier: Modifier = Modifier
) {
    Box(
        modifier = modifier
            .fillMaxSize()
            .background(Color.Cyan),
        contentAlignment = Alignment.Center
    ) {
        Text(
            text = "This is a sample text!",
            fontSize = 32.sp,
            fontWeight = FontWeight.Bold,
        )
    }
}
```
fillMaxSize()関数では、**幅と高さの両方を親要素のサイズいっぱいに広げます**。このため、画面上でも水色の背景がデバイス全体に広がっています。
![fillMaxSize.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796037/9c4ea3ea-0cd0-e985-2d34-99972ba82996.png)


#### - `fillMaxWidth`
```Kotlin
@Composable
fun Myfunc(
    text: String = "This is a sample text!",
    modifier: Modifier = Modifier
) {
    Column(
        verticalArrangement = Arrangement.Center,
    ) {
        Box(
            modifier = modifier
                .fillMaxWidth(),
            contentAlignment = Alignment.Center
        ) {
            Text(
                text = "This is a sample text!",
                fontSize = 32.sp,
                fontWeight = FontWeight.Bold,
            )
        }
    }
}
```
fillMaxWidth()関数は**横幅だけを親の幅一杯に広げます**。
![fillmaxwidth.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796037/25d6bc94-e442-8919-5762-790dc3c06517.png)


#### - `fillMaxHeight`
```Kotlin
@Composable
fun Myfunc(
    text: String = "This is a sample text!",
    modifier: Modifier = Modifier
) {
    Column(
        modifier = Modifier.fillMaxHeight()
    ) {
        Box(
            modifier = modifier
                .fillMaxHeight()
                .background(Color.DarkGray)
                .weight(1f)
                .width(200.dp),
            contentAlignment = Alignment.Center
        ) {
            Text(
                text = "first text",
                fontSize = 32.sp,
                fontWeight = FontWeight.Bold,
                color = Color.White
            )
        }
        Box(
            modifier = modifier
                .fillMaxHeight()
                .background(Color.Magenta)
                .weight(1f)
                .width(200.dp),
            contentAlignment = Alignment.Center
        ) {
            Text(
                text = "second text",
                fontSize = 32.sp,
                fontWeight = FontWeight.Bold,
                color = Color.White
            )
        }
    }
}
```
fillMaxHeight()関数は**縦幅だけを親の高さいっぱいに広げます**。画面では、後述するweight()関数を利用して縦方向に2つのBoxを配置しています。
![fillMaxHeight.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796037/7de00732-bff8-7018-a4f5-efc45b0d1c62.png)


### 2:背景・ボーダー
#### - `background`
```Kotlin
@Composable
fun Myfunc(
    text: String ="This is a sample text!",
    modifier: Modifier = Modifier
) {
    Box(
        modifier = modifier
            .fillMaxSize()
    ) {
        Text(
            text = text,
            modifier = modifier
                .align(Alignment.Center)
                .background(Color.Cyan),
            fontSize = 32.sp,
            fontWeight = FontWeight.Bold
        )
    }
}
```
background()関数では**任意の背景色を付けることが出来ます**。画面では、Text内のmodifierでこの関数を使用することでテキストの背景をシアンカラーにしています。
![background.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796037/4fc07618-0841-5315-665c-bf2e62129eca.png)



#### - `border`
```Kotlin
@Composable
fun Myfunc(
    text: String ="This is a sample text!",
    modifier: Modifier = Modifier
) {
    Box(
        modifier = modifier
            .fillMaxSize()
    ) {
        Text(
            text = text,
            modifier = modifier
                .align(Alignment.Center)
                .background(Color.Cyan)
                .border(4.dp,Color.Black),
            fontSize = 32.sp,
            fontWeight = FontWeight.Bold
        )
    }
}
```
border()関数では**UI部品の周囲を枠線で囲うことができる関数**です。
![border.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796037/674f5c9d-fc75-1838-2fd5-54f5f1860e1c.png)


### 3:オブジェクトの配置
#### - `align`
```Kotlin
@Composable
fun Myfunc(
    text: String ="This is a sample text!",
    modifier: Modifier = Modifier
) {
    Box(
    ) {
        Text(
            text = text,
            modifier = modifier.align(Alignment.Center),
            fontSize = 32.sp,
            fontWeight = FontWeight.Bold
        )
    }
}
```
align()関数は**親要素の中での子要素の配置(右揃え、左揃え、中央揃え)を決定する関数**です。コードでは、`align(Alignment.Center)`とすることでBox内のテキストを中央揃えしています。
![alignmaxsize.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796037/aebfdd98-d192-4275-ceff-2c49ceba6838.png)


#### - `offset`
```Kotlin
@Composable
fun Myfunc(
    text: String ="This is a sample text!",
    modifier: Modifier = Modifier
) {
    Box(
        modifier = modifier
            .fillMaxSize()
    ) {
        Text(
            text = text,
            modifier = modifier
                .align(Alignment.Center)
                .offset(y = 70.dp,x=20.dp),
            fontSize = 32.sp,
            fontWeight = FontWeight.Bold
        )
    }
}
```
offset関数は**UI要素の位置を相対的に移動させるための関数**です。移動幅はx軸とy軸に分けて設定することが出来ます。コードでは`offset(y = 70.dp,x=20.dp)`としているため、align()関数で中央揃えした時よりもテキストが右下に寄っていることが分かります。
![offset.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796037/68bd9339-00d7-935d-8cc1-e31d818794f8.png)


### 4:スタイル調整
#### - `padding`
```Kotlin
@Composable
fun Myfunc(
    text: String ="This is a sample text!",
    modifier: Modifier = Modifier
) {
    Box(
        modifier = modifier
            .fillMaxSize()
    ) {
        Text(
            text = text,
            modifier = modifier
                .align(Alignment.Center)
                .background(Color.Cyan)
                .border(4.dp,Color.Black)
                .padding(24.dp),
            fontSize = 32.sp,
            fontWeight = FontWeight.Bold
        )
    }
}
```
padding()関数は**そのUI部品の周囲の余白を指定する関数**です。border()関数を用いた際の画面と比べるとテキストの周りに余白が出来ていることが分かります。
![padding.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796037/2ce67bd8-0d03-1d48-55b6-105a43626481.png)


#### - `size`
```Kotlin
@Composable
fun Myfunc(
    text: String ="This is a sample text!",
    modifier: Modifier = Modifier
) {
    Box(
        modifier = modifier
            .fillMaxSize()
    ) {
        Text(
            text = text,
            modifier = modifier
                .align(Alignment.Center)
                .background(Color.Cyan)
                .border(4.dp,Color.Black)
                .padding(24.dp)
                .size(240.dp,120.dp),
            fontSize = 32.sp,
            fontWeight = FontWeight.Bold
        )
    }
}
```
size()関数は**UI要素のスケールを調整するための関数**です。
コードの中では`size(240.dp,120.dp)`という形で記述することで元々よりすケースが大きくなっています。
![size.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796037/7cfad267-0096-a717-64f5-6b8a5c34e98a.png)


#### - `weight`
```Kotlin
@Composable
fun Myfunc(
    text: String = "This is a sample text!",
    modifier: Modifier = Modifier
) {
    Column(
        modifier = modifier
            .fillMaxSize()
            .background(Color.LightGray),
    ) {
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .background(Color.Red)
                .weight(0.3f)
        ) {
            Text(
                text = "sample test",
                color = Color.White,
                fontSize = 24.sp,
                fontWeight = FontWeight.Bold,
            )
        }
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .background(Color.Blue)
                .weight(0.2f)
        ) {
            Text(
                text = "sample test",
                color = Color.White,
                fontSize = 24.sp,
                fontWeight = FontWeight.Bold,
            )
        }
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .background(Color.DarkGray)
                .weight(0.5f)
        ) {
            Text(
                text = "sample test",
                color = Color.White,
                fontSize = 24.sp,
                fontWeight = FontWeight.Bold,
            )
        }
    }
}
```
weight()関数は`Row`や`Column`などの中で**UI要素に割り当てる比率を調整するための関数**です。
画面では3つのBoxが縦に並んでいますが、それぞれのweight()関数の引数を`0,2f,0.5f,0.3f`(全体の大きさは`1f`)としているので画面でもその通りの大きさの比率となっています。
![weight.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796037/bb712434-ddce-26a3-0976-b601c2778320.png)


### 5:視覚への効果
#### - `alpha`
```Kotlin
@Composable
fun Myfunc(
    text: String ="This is a sample text!",
    modifier: Modifier = Modifier
) {
    Box(
        modifier = modifier
            .fillMaxSize()
    ) {
        Text(
            text = text,
            modifier = modifier
                .align(Alignment.Center)
                .clip(RoundedCornerShape(20.dp))
                .alpha(0.5f)
                .background(Color.Green)
                .padding(24.dp),
            fontSize = 32.sp,
            fontWeight = FontWeight.Bold
        )
    }
}
```
alpha()関数は**UI部品の透明度を調節する関数**です。コードでは`alpha(0.5f)`としていますが、これにより画面においてボタンとその中のテキストの色が通常よりも薄くなっているのが分かります。
![alpha.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796037/bc2fe4e7-4d33-21a4-cbbc-0e14c3d96476.png)


#### - `clip`
```Kotlin
@Composable
fun Myfunc(
    text: String ="This is a sample text!",
    modifier: Modifier = Modifier
) {
    Box(
        modifier = modifier
            .fillMaxSize()
    ) {
        Text(
            text = text,
            modifier = modifier
                .align(Alignment.Center)
                .clip(RoundedCornerShape(20.dp))
                .background(Color.Green)
                .padding(24.dp),
            fontSize = 32.sp,
            fontWeight = FontWeight.Bold
        )
    }
  }
```
clip()関数は**コンポーネントを丸く切り抜くための関数**です。画面を見ると、ボタンの角が少し丸みがかっているのが分かります。なお、引数のshapeにはRoundedCornerShapeなどが必要になります。
![clip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796037/1996f28f-1fa4-1e40-baba-4bd72431ac4f.png)


#### - `scale`
```Kotlin
@Composable
fun Myfunc(
    text: String ="This is a sample text!",
    modifier: Modifier = Modifier
) {
    Column(
        modifier = modifier
            .fillMaxSize()
            .padding(16.dp)
            .background(Color.LightGray),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally,
    ) {
        Text(
            text = "Small Text",
            color = Color.Red,
            fontSize = 24.sp,
            modifier = Modifier.scale(0.7f, 0.7f)
        )
        Spacer(modifier =Modifier.height(16.dp))
        Text(
            text = "Middle test",
            color = Color.Blue,
            fontSize = 24.sp,
            modifier= Modifier.scale(1.0f, 1.0f)
        )
        Spacer(modifier =Modifier.height(16.dp))
        Text(
            text = "Large Text",
            color = Color.Black,
            fontSize = 24.sp,
            modifier= Modifier.scale(1.8f, 1.8f)
        )
        Spacer(modifier =Modifier.height(32.dp))
        Button(
            onClick = { /*TODO*/ },
            modifier=Modifier.scale(0.8f,0.8f)) {
            Text("小さいボタン")
        }
        Spacer(modifier =Modifier.height(32.dp))
        Button(
            onClick = { /*TODO*/ },
            modifier=Modifier.scale(1.5f,1.5f)) {
            Text("大きいボタン")
        }
    }
}
```
scale()関数は**UI要素のスケールを調整するための関数**です。このscale()関数の引数では`1f`は元のサイズを表し、それより大きい引数とすれば通常よりサイズの大きいUI部品が、小さい値の引数とすれば通常より小さいUI部品が描画されます。
![scale.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796037/ac031654-4e49-4588-8394-eb497b054d08.png)


## まとめ
Modifierを適切に使用することで、コードの再利用性や可読性が向上されられるため、効率的なアプリケーション開発に不可欠だと言えます。
なお、本記事で紹介したのは一例にすぎません。興味を持った方はぜひ公式ドキュメントを参照してください。