5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Jetpack Compose基礎

Last updated at Posted at 2019-12-14

FUN Advent Calendar 2019 Part1,14日目の記事です.

昨日はふぁるくんの世界料理学会 in Hakodateに参戦してきた話でした.

今年はじめてAdvent Calendarというものに参加してみました.
テーマが自由だったので,好きなことを書きます.
色々迷いましたが,某LT会での記事の続き的なことを書こうと思いました.
某LT会から結構時間が経ったのですが,最近触れていなかったのでJetpack Composet周りを軽くまとめてみようかなと思いました

概要

以前記事を書いた時には,AOSP(Android Open Source Project)からダウンロードして利用するしか方法がありませんでした.
しかし,まだプレアルファ版ですが,Android Studio 4.0からライブラリとしてJetpack Composeが使用できるようになりました(プレアルファ版なので,製品版には使用しないでくださいという注意書きがあります).
そこで,Android Studio 4.0 Canary4を利用してJetpack Composeを使用していこうと思います.
ちゃんと書こうとするとModelやStateとかも出てきてしまうのですが,今回はシンプルなUI作成の紹介をしていきます.

余談

Android Studio4.0 Canary4のタイトル部分(?)がかっこよくなってますね.
Android Studio3.5から背景に模様が入っていましたがここまで変えてくるとは...

導入

今回は,自分で新たにプロジェクト作成して行いました.
jetpack composeを自分のプロジェクトで利用する方法はこちらの手順で行いました.
現状では,プロジェクト作成時にjetpack composeを使うか否か選べないようです.
まだプレアルファ版なので無いだけで,そのうち追加されそうですね

自分がプロジェクト作成する際に見落としているだけでした.
画像のような「Empty Compose Activity」を選んでプロジェクトを作成すればできるっぽいです.

スクリーンショット 2019-12-13 13.39.25.png

Let's try Jetpack Compose

基礎的なUIの表示方法を軽くまとめていきます.

前提

説明に入る前に...
下記のようにsetContentの中にUI部分を書いていきます.
今回のコードは全て,setContentの中に入れる関数として作成していきます.
※小見出しに従来のCompoment名で書いているのでご注意ください.

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            createGreetingUI()
        }
}

TextView

やっぱり初めはJetpack Composeにご挨拶しなきゃですよね(笑)
てことで,文字列の表示から行っていきます.
TextというCompomentに,text = {表示させたい文字列}としてあげれば文字列が表示されます.

@Composable
fun createGreetingUI() {
    greetingView("JetpackCompose")
}

@Composable
fun greetingView(name: String) {
    MaterialTheme {
        Center {
            Text(text = "Hello $name!")
        }
    }
}

このようにHello JetpackCompose!と表示されます.

この例では,text以外の設定をデフォルトから変更していません.
もちろんフォントやフォントサイズの変更もできます.
下のように,TextStyleを設定することでTextを好きなようにカスタマイズできます.

fun originalTextViewStyle() = TextStyle(color = Color.Red, fontSize = 30.sp, fontFamily = FontFamily.Cursive)
Text(text = "Hello $name!", style = originalTextViewStyle())

この例では.フォント,フォントサイズ,フォントカラーを変更しています.
今回はFontFamilyにもともと入っているフォントを使用していますが,各自で追加したものでもできます.

ImageView

次は,画像の表示を行っていきます.
画像には,DraweImageを使用し,image = {画像}で表示させます.

@Composable
fun createImageUI() {
    MaterialTheme {
        Center {
            Container(height = 300.dp, width = 300.dp) {
                DrawImage(image = +imageResource(R.drawable.droidkun))
            }
        }
    }
}

実際に表示させるとこのような感じになります.
DrawImageのみだと画像のサイズ通りに表示されてしまうため,Containerで表示させる範囲を指定しています.

EditText

従来とは,だいぶCompoment名が変わりましたが,TextFieldを使用します.

value部分は表示される文字列,onValueChangeは入力された文字列となる.
そのため,onValueChange+state関数に入力された文字列に更新し,value+state関数を代入することで入力された文字列が更新されます.

@Composable
fun createEditTextUI() {
    val state = +state { "" }
    TextField(
        value = state.value,
        onValueChange = { state.value = it },
        editorStyle = EditorStyle(
            textStyle = TextStyle(
                fontSize = (20.sp)
            )
        )
    )
}

このようになりました.
現状では従来のHintはなく,下線が表示されていません.
Hintに関しては調べてみると無理やり実装している例も見つけましたが,そのうち追加されそうなので省きます.

従来通りキーボードの設定もできるので,今回はNumberPasswordを試してみました.

keyboardType = KeyboardType.NumberPassword

あれっ!?
キーボードの設定をPasswordにしたら,表示される文字は*になるべきではないのかと思いました.
このままでは各自で実装する際に,変換する必要がありそうですが,きっと修正されますよね?

AppBar

次に,AppBarを表示させていきます.
まず,既存の方法でデフォルトのActionBarを非表示にします.
下記のようにparentをTheme.AppCompat.Light.NoActionBarに変更します.

stymes.xml
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

これで,ActionBarを非表示にできたので,AppBarを追加していきます.
AppBarには,TopAppBarを使用し,icon = {アイコン}title = {タイトル}で表示できます.

@Composable
fun createAppBarUI() {
    MaterialTheme {
        Column(mainAxisAlignment = MainAxisAlignment.Start) {
            TopAppBar(
                title = { Text(text = "cuntomAppBar", style = originalAppBarTextStyle()) },
                color =  Color(0xFF339933),
                navigationIcon = {
                    VectorImageButton(R.drawable.ic_home) {
                        /**
                         * iconタップ処理
                         */ 
                    }
                }
            )
        }
    }
}

fun originalAppBarTextStyle() = TextStyle(color = Color.White)

@Composable
fun VectorImageButton(@DrawableRes id: Int, onClick: () -> Unit) {
    Ripple(bounded = false) {
        Clickable(onClick = onClick) {
            VectorImage(id)
        }
    }
}

@Composable
fun VectorImage(@DrawableRes id: Int, tint: Color = Color.Transparent) {
    val vector = +vectorResource(id)
    WithDensity {
        Container(
            width = vector.defaultWidth.toDp(),
            height = vector.defaultHeight.toDp()
        ) {
            DrawVector(vector, tint)
        }
    }
}

上記のコードではこのような表示になります.

上記コードのiconを表示させる部分では,VectorImageButtonでRippleとClickを付与し,VectorImageでVectorの範囲指定と表示を行っています.

使ってみた感じいくつか注意すべき点があるように感じました.

  • MaterialThemeで囲まないと**No colors found!**と怒られます.
    これは,内部的には指定しているため,color指定するしないに関わらず怒られます.
  • Columnなどで場所を指定したあげないとフルスクリーンで表示されます.
  • ステータス部分の背景色は,(この場合)AppThemecolorPrimaryDarkが自動で設定されます.
    しかし,AppBarの背景色はcolorPrimaryが設定されずデフォルトの0xFF6200EEが設定されます.
    指定しない場合,colorPrimaryがAppBarの背景色に設定されればスッキリするように感じました.

ListView

何か配列のものをリスト状に表示させることはよくあることです.
しかし,現状ではCompomentとして用意されていないようです.
そのため,ListVIew的なもののを作成してみます.

フルーツの配列を作ってリスト状に表示させていきます.
ただColumに追加していってもスクロールできず,下の方が見えなくなるためVerticalScrollerの中に作っていきます.
さらに,Listの要素分だけListItemを追加することで,リスト状に表示できます.
区切り線が必要な場合には,Dividerで表示させてください.

@Composable
fun createListUI(context: Context) {

    val fruitList = arrayOf("りんご", "いちご", "みかん", "なし", "パイナップル", "スイカ", "メロン", "さくらんぼ", "バナナ", "キウイ", "ぶどう", "レモン", "グレープフルーツ", "モモ", "ゆず")

    MaterialTheme {
        FlexColumn {
            flexible(flex = 1f) {
                VerticalScroller {
                    Column {
                        for (fruit in fruitList) {
                            ListItem(
                                text = fruit,
                                onClick = {
                                    Toast.makeText(context, fruit, Toast.LENGTH_SHORT).show()
                                }
                            )
                            /**
                             * 区切り線の表示
                             */
                            Divider(color = Color(0x44666666))
                        }
                    }
                }
            }
        }
    }
}

今回は,文字列のみのリストですがListItemでは,iconなども設定できるっぽいのでもう少しちゃんとしたものも作れそうです.

まとめ

この場で全てを紹介するなんてのは無理なので開発の中でよく使いそうなものの一部を紹介しました.
まだ,未完成の状態なので今後の追加次第で今回紹介したものもより応用を効かすことができそうです.

Jetpack Compose自体はReact, Flutterなどを触ったことがある人ならある程度理解しやすいのかなと思います.
自分はあまり触ったことがないので慣れるまでは苦労しそうだなと思いました.
もう少し色々試してみようと思ってはいたのですが,時間がなくあまり試せませんでした.
やることが落ち着いたらPart2でも書こうかなと思います.

Jetpack Compose用に作成した個人のリポジトリ

下記のリンクに今回紹介したコードを含めたアプリのレポジトリを載せました.
よかったら参考程度にでも.....
https://github.com/mattukouta/JetpackCompose

参考サイト

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?