🙌
JetpackComposeでカスタムビューを作ってみた
最近話題のJetpackComposeですが、1画面まるっと対応は少し不安があるのでカスタムビューから対応してみたいと思ってやってみた記録です。
とりあえず動いたレベルなので、誤りや非推奨のコードもあるかもしれません
Build.gradle
buildscript {
ext {
compose_version = '1.0.0-alpha03'
}
ext.kotlin_version = "1.4.10"
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.2.0-alpha12'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
こちらはコードラボの物をそのまま使ってます。
kotlinのバージョンが1.4以上であれば大丈夫なはずです。
plugins {
id 'com.android.application'
id 'kotlin-android'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.0"
defaultConfig {
applicationId "com.example.statecodelab"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
kotlinOptions {
jvmTarget = '1.8'
useIR = true
allWarningsAsErrors = false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildFeatures {
compose true
viewBinding true
}
composeOptions {
kotlinCompilerExtensionVersion "$compose_version"
kotlinCompilerVersion "$kotlin_version"
}
}
dependencies {
〜略〜
implementation "androidx.compose.animation:animation:$compose_version"
implementation "androidx.compose.foundation:foundation:$compose_version"
implementation "androidx.compose.foundation:foundation-layout:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.material:material-icons-extended:$compose_version"
implementation "androidx.compose.runtime:runtime-livedata:$compose_version"
implementation "androidx.compose.runtime:runtime:$compose_version"
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.ui:ui-tooling:$compose_version"
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
kotlinOptions {
jvmTarget = "1.8"
freeCompilerArgs += [
"-Xopt-in=kotlin.RequiresOptIn"
]
}
}
こちらもほぼコードラボと同じですが、使用している別のライブラリの影響でallWarningsAsErrors
をtrueにしておくとビルドが通らなかったのでfalseに変更しています。
カスタムビュー
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.compose.foundation.Text
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Recomposer
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.setContent
import sobaya.example.allflow.R
class ComposeSample @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0
) : FrameLayout(context, attrs, defStyleAttr, defStyleRes) {
init {
val view = LayoutInflater.from(context).inflate(R.layout.compose, this, true)
(view as ViewGroup).setContent(Recomposer.current(), null) {
MaterialTheme {
customView()
}
}
}
@Composable
fun customView() {
Text(text = "TEST", color = Color.Black)
}
}
LayoutInflaterでFramelayoutを宣言してるだけのLayout.xmlを読み込ませて、
そこにcustomView()
メソッドで作成したレイアウトを差し込んでいます。
ここはxmlの読み込みが無駄に思えるのですが、他に方法が見つからなかったのでこうしています。
FragmentのonCreateViewのようにViewを返却すれば描画してくれる場合にはComposeView
と言うクラスが用意されているので
ComposeView(requireContext()).apply {
setContent {
Text(text = "TEST", color = Color.Black)
}
こんな感じに記載することができます。
※ComposeViewをViewとして渡してあげれば描画してくれる
Layout.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" />
本当に何も記載していません
画面
表示はこのようになりました
気になったのでレイアウトの構成を眺めてみたら、この程度の内容なのにかなり深くなっておられる。。。
Discussion