Bottom Navigation Activity を自動生成すると、こんな感じのソースが生成される。
Kotlin 初学者のため勘所を外していたら申し訳ないのだけれど、僕個人の趣味にあわせて書き換えてみたい。
class HomeActivity : AppCompatActivity() {
private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.navigation_home -> {
message.setText(R.string.title_home)
return@OnNavigationItemSelectedListener true
}
R.id.navigation_dashboard -> {
message.setText(R.string.title_dashboard)
return@OnNavigationItemSelectedListener true
}
R.id.navigation_notifications -> {
message.setText(R.string.title_notifications)
return@OnNavigationItemSelectedListener true
}
}
false
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
}
}
イベントリスナーの持ち上げ
OnNavigationItemSelectedListener
が private val
として、初期化と同時に構築され変更不能なフィールドとして確保されていることは好感が持てる。
ところでアクティビティを想定すると、ナビゲーションは一つ。(二つ以上のナビゲーションが画面内に存在するのは、 UI として下品だろう)
つまりリスナーを独立させる必要はなく、このアクティビティが唯一持つナビゲーションのリスナーであればよい。
class HomeActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
navigation.setOnNavigationItemSelectedListener(this)
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.navigation_home -> {
message.setText(R.string.title_home)
return true
}
R.id.navigation_dashboard -> {
message.setText(R.string.title_dashboard)
return true
}
R.id.navigation_notifications -> {
message.setText(R.string.title_notifications)
return true
}
}
return false
}
}
テキスト設定のくくりだし
さて。 onNavigationItemSelected
は内側の when
の各 case
がほとんど同じ構造であることに気づく。
こういう場合はくくりだしだ。
override fun onNavigationItemSelected(item: MenuItem): Boolean {
var resId: Int?
when (item.itemId) {
R.id.navigation_home -> resId = R.string.title_home
R.id.navigation_dashboard -> resId = R.string.title_dashboard
R.id.navigation_notifications -> resId = R.string.title_notifications
else -> resId = null
}
resId?.let {
message.setText(resId)
return true
}
return false
}
そして when
を関数としてくくり出すことで、さらに整理できる。
override fun onNavigationItemSelected(item: MenuItem): Boolean {
return stringIdFrom(item.itemId)?.let {
message.setText(it)
true
} ?: false
}
private fun stringIdFrom(itemId: Int): Int? {
return when (itemId) {
R.id.navigation_home -> R.string.title_home
R.id.navigation_dashboard -> R.string.title_dashboard
R.id.navigation_notifications -> R.string.title_notifications
else -> null
}
}
整理し終えたコード
掲げるまでもないけれど、全体はこう変わる。
class HomeActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
navigation.setOnNavigationItemSelectedListener(this)
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
return stringIdFrom(item.itemId)?.let {
message.setText(it)
true
} ?: false
}
private fun stringIdFrom(itemId: Int): Int? {
return when (itemId) {
R.id.navigation_home -> R.string.title_home
R.id.navigation_dashboard -> R.string.title_dashboard
R.id.navigation_notifications -> R.string.title_notifications
else -> null
}
}
}
ネストの深さから見ても、スッキリしたのではないだろうか?
アプリケーションで繰り返し利用されるようならば stringIdFrom
を共通で使う「関数オブジェクト」として切り出してもいいだろう。