ViewModel+LiveData+Databindingを使ってみる
キーボードが表示されているときだけViewを非表示にするというサンプルです。
ソースコード
設定
build.gradle
//略
dataBinding {
enabled = true
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$rootProject.kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0-alpha03'
implementation 'androidx.core:core-ktx:1.1.0-alpha05'
//lifecycle
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0-alpha02'
}
//略
dataBinding {
enabled = true
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$rootProject.kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0-alpha03'
implementation 'androidx.core:core-ktx:1.1.0-alpha05'
//lifecycle
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0-alpha02'
}
dataBindingを有効にして
androidx.lifecycle:lifecycle-extensionsをインポートしています。
androidxを使わない場合は
android.arch.lifecycle:extensionsをインポートします。
<activity
android:name="com.ringored.view.StartActivity"
android:windowSoftInputMode="adjustResize"
>
windowSoftInputMode="adjustResize"にすることでキーボードが表示される度にキーボードの領域を除いた画面サイズで再描画します。
ViewModel
class MainViewModel(application: Application) : AndroidViewModel(application) {
val isKeyboardShowing: MutableLiveData<Boolean> by lazy {
MutableLiveData<Boolean>()
}
}
AndroidViewModelを継承した自作のViewModelに
isKeyboardShowingというBooleanのMutableLiveDataを作成します。
あとでこのisKeyboardShowingをレイアウトからobserve(観察)します
View
class StartActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
showLogin()
}
}
fun showLogin(){
supportFragmentManager
.beginTransaction()
.replace(R.id.fragment_container, MainFragment(), TAG_OF_FRAGMENT)
.commit()
}
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</FrameLayout>
ActivityはFragmentをTransactionしているだけ
Activityに描画する場合は以下のFragmentをActivityに置き換えます。
const val TAG_OF_FRAGMENT = "MainFragment"
class MainFragment : Fragment() {
private lateinit var binding: FragmentMainBinding
private var parent: ViewGroup? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_main, container, false)
binding.lifecycleOwner = this
binding.viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
setKeyboardStatusObserver()
return binding.root
}
//keyboardの状態を監視してliveDataに通知
private fun setKeyboardStatusObserver() {
parent = activity!!.fragment_container as ViewGroup
parent?.viewTreeObserver?.addOnGlobalLayoutListener {
parent?.let {
//rootViewの高さを比較して200px以上あればimeが表示されているとみなす
binding.viewModel?.isKeyboardShowing?.postValue(it.rootView.height - it.height > 200)
}
}
}
}
bindingの型はxmlの名前をキャメルケースにして後ろにBindingをつけたものがビルド時に自動生成されます。
fragment_main-> FragmentMainBinding
うまくインポートできない場合はBuild->Rebuild Projectしてください。
binding.lifecycleOwner = this
lifecycleOwnerを自分のフラグメントに設定します。
これしないと動きません。
binding.viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
ViewModelProvidersからViewModelを取得してbindingにセットします。
parent?.viewTreeObserver?.addOnGlobalLayoutListener {
parent?.let {
//rootViewの高さを比較して200px以上あればimeが表示されているとみなす
binding.viewModel?.isKeyboardShowing?.postValue(it.rootView.height - it.height > 200)
}
}
viewが再描画される度にviewModelのisKeyboardShowingを更新します。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="android.view.View"/>
<variable name="viewModel"
type="jp.co.synchrolife.vm.start.login.LoginViewModel" />
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{viewModel.isKeyboardShowing ? View.GONE: View.VISIBLE}"
app:srcCompat="@drawable/fruit_apple"/>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
android:hint="パスワード"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<com.google.android.material.textfield.TextInputEditText
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</layout>
全体をlayoutタグで囲み
View.GONE,VISIBLEを使用するためにandroid.view.Viewをインポートします
MainViewModelをobserveするためvariableにパッケージを追加します。
android:visibility="@{viewModel.isKeyboardShowing ? View.GONE: View.VISIBLE}"
これでLiveData(isKeyboardShowing)が更新される度、GONE VISIBLEを切り替えてくるようになりました。
Author And Source
この問題について(ViewModel+LiveData+Databindingを使ってみる), 我々は、より多くの情報をここで見つけました https://qiita.com/toroncho-good/items/fa76b95bf3e9a45dd790著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .