Android Kotlin スライドメニュー(NavigationDrawer+ListView)を実装
今回やりたかったことは以下
・画面左上のメニューアイコンタップでスライドメニュー表示
・各メニューのレイアウトは自由にカスタムしたい
Androidプロジェクト作成時に「Navigation Drawer Activity」を選択すればある程度期待する画面なのだが、以下のやり方がわからなかったので実装したときのメモ
・右上のメニューは不要
・レイアウトをカスタマイズ
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:openDrawer="start"> <!-- スライドメニュー以外(アクションバー+メイン画面の部分) --> <include layout="@layout/app_bar_main" android:layout_width="match_parent" android:layout_height="match_parent"/> <!-- スライドメニュー部分 --> <!-- app:headerLayoutでヘッダーに使用するレイアウトを指定 --> <android.support.design.widget.NavigationView android:id="@+id/nav_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="true" app:headerLayout="@layout/nav_header_main"> <!-- スライドメニューの中身はListViewとする --> <ListView android:id="@+id/nav_menu_items" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="8dp" android:layout_marginTop="100dp" /> </android.support.design.widget.NavigationView> </android.support.v4.widget.DrawerLayout>
app_bar_main.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <android.support.design.widget.AppBarLayout android:layout_height="wrap_content" android:layout_width="match_parent" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay"/> </android.support.design.widget.AppBarLayout> <!-- メインコンテンツ部分 --> <include layout="@layout/content_main"/> </android.support.design.widget.CoordinatorLayout>
menu_item.xml
<?xml version="1.0" encoding="utf-8"?> <!-- ListViewの各行 --> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="3sp"> <TextView android:id="@+id/name" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#000" android:textStyle="bold" android:textSize="16sp" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:layout_marginLeft="5sp"/> </RelativeLayout>
nav_header_main.xml(Android Studioが作ってくれたやつほぼそのまま)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="100dp" android:background="@drawable/side_nav_bar" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:theme="@style/ThemeOverlay.AppCompat.Dark" android:orientation="vertical" android:gravity="bottom"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:paddingTop="@dimen/nav_header_vertical_spacing" android:text="@string/nav_header_title" android:textAppearance="@style/TextAppearance.AppCompat.Body1"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/nav_header_subtitle" android:id="@+id/textView"/> </LinearLayout>
MainActivity.kt
package xxx.yyy.zzz import android.os.Bundle import android.support.design.widget.Snackbar import android.support.design.widget.NavigationView import android.support.v4.view.GravityCompat import android.support.v7.app.ActionBar import android.support.v7.app.ActionBarDrawerToggle import android.support.v7.app.AppCompatActivity import android.view.Menu import android.view.MenuItem import android.view.View import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.app_bar_main.* class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // アクションバー+スライドメニュー設定 setSupportActionBar(toolbar) val toggle = ActionBarDrawerToggle(this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) drawer_layout.addDrawerListener(toggle) toggle.syncState() // スライドメニューの各行をListViewで設定 val menuItems = mutableListOf<MenuItem>() menuItems.add(MenuItem("メニュー1")) menuItems.add(MenuItem("メニュー2")) menuItems.add(MenuItem("メニュー3")) menuItems.add(MenuItem("メニュー4")) menuItems.add(MenuItem("メニュー5")) nav_menu_items.adapter = MenuItemAdapter(this, menuItems) } // バックボタンでメニューを閉じる override fun onBackPressed() { if (drawer_layout.isDrawerOpen(GravityCompat.START)) { drawer_layout.closeDrawer(GravityCompat.START) } else { super.onBackPressed() } } }
MenuItem.kt
package xxx.yyy.zzz class MenuItem( val title: String )
MenuItemAdapter.kt
package xxx.yyy.zzz import android.content.Context import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.BaseAdapter import kotlinx.android.synthetic.main.menu_item.view.* class MenuItemAdapter(val context: Context, val items: List<MenuItem>): BaseAdapter() { val layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater override fun getCount(): Int { return items.count() } override fun getItem(position: Int): MenuItem { return items[position] } override fun getItemId(position: Int): Long { return position.toLong() } override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View { val view = layoutInflater.inflate(R.layout.menu_item, parent, false) view.name.text = items[position].title return view } }
MenuItemとMenuItemAdapterはスライドメニューというよりListViewの実装のコード。以上