HeaderView + DataBinding でハマった話
HeaderView に DataBinding でアニメーション実装しようとしたら意外とハマったのでメモ。
- アーキテクチャ : MVVM
- 言語 : Kotlin
ハマりポイント
- HeaderView は動的に生成しないとバインドされない
- NavigationDrawer の
app:headerLayout
は使わない
正直これ↓見ていただければいいだけの話ではある( ˘ω˘)
ハマった実装
xml で静的に HeaderView をセットしていました。
まずは HeaderView のレイアウト。
<layout xmlns:bind="http://schemas.android.com/apk/res-auto"> <data> <variable name="viewmodel" type="MainViewModel"/> </data> <android.support.constraint.ConstraintLayout android:id="@+id/navigation_header_frame" bind:animate_background_color="@{viewmodel.headerColorTo}"> <ImageView android:id="@+id/header_image" .../> </android.support.constraint.ConstraintLayout> </layout>
次にMainActivity のレイアウト。
<layout xmlns:bind="http://schemas.android.com/apk/res-auto"> <data> <variable name="viewmodel" type="MainViewModel"/> </data> <DrawerLayout ...> <ConstraintLayout ...> </ConstraintLayout> <!--Navigation Drawer--> <NavigationView android:id="@+id/nav_view" app:headerLayout="@layout/navigation_header" /> </DrawerLayout> </layout>
app:headerLayout
で HeaderView をセットしていましたが、これでは単に HeaderView が表示されるだけでデータバインドはされません。
一応 MainActivity#onCreate
の実装。
class MainActivity : AppCompatActivity() { lateinit var binding: MainActBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) /* MainActivity の View を生成 */ binding = DataBindingUtil.setContentView<MainActBinding>(this, R.layout.main_act).also { it.viewmodel = obtainViewModel() it.setLifecycleOwner(this) } } }
setContentView
で子のバインドも出来てると思い込んでしまった……。
解決した実装
app:headerLayout
を消した上で、MainActivity#onCreate
に次のように実装します。
class MainActivity : AppCompatActivity() { lateinit var binding: MainActBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) /* MainActivity の View を生成 */ binding = DataBindingUtil.setContentView<MainActBinding>(this, R.layout.main_act).also { it.viewmodel = obtainViewModel() it.setLifecycleOwner(this) } /* HeaderView inflate */ val _bind = NavigationHeaderBinding.inflate(layoutInflater, binding.navView, false).also { it.viewmodel = obtainViewModel() it.setLifecycleOwner(this) } /* HeaderView を NavigationDrawer にセット */ binding.navView.addHeaderView(_bind.root) } }
binding.navView
は MainActivity のレイアウトに置いてある NavigationDrawer です。念のため。
次は HeaderView にアニメーションを DataBinding 機構を介して実装した話書きます。