If we want to create the layout as below, we need to create the Drawer and Expandable List View.
For fulfill our purpose, we need to create some files.
First, your main_activity layout must add drawer and content expendable list.
activity_main.xml
<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/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.NavigationView
android:id="@+id/naviView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/drawer_header">
<ExpandableListView
android:id="@+id/navigationmenu"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginTop="151dp"
android:background="@android:color/white">
</ExpandableListView>
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
Add
listheader.xml for each title in drawer.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="20dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/iconimage"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"/>
<TextView
android:id="@+id/submenu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:textColor="@color/grayColor_55"
android:textSize="16sp"/>
<!-- Indicator right-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="140dp"
android:layout_gravity="end">
<ImageView
android:id="@+id/indicatorImage"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="10dp"/>
</LinearLayout>
</LinearLayout>
</android.support.constraint.ConstraintLayout>
Add
list_submenu.xml for Child list.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--Expandable View, Children List-->
<TextView
android:id="@+id/submenu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="50dp"
android:padding="10dp"
android:textColor="@color/grayColor_55"
android:textSize="16sp"/>
</LinearLayout>
Now we've already had the xml files that we need.
Prepare Kotlin files
1. We need a model for set icon and text title.
ExpandedMenuModel.kt
class ExpandedMenuModel {
var iconName = "" var iconImg = -1 // menu icon resource id}
2. We need a Adapter
ExpandableListAdapter.kt
class ExpandableListAdapter(private val mContext: Context, private val mListDataHeader: ArrayList<ExpandedMenuModel> // header titles , // child data in format of header title, child title private val mListDataChild: HashMap<ExpandedMenuModel, ArrayList<String>>, internal var expandList: ExpandableListView) : BaseExpandableListAdapter() {
override fun getGroupCount(): Int {
val i = mListDataHeader.size
Log.d("GROUPCOUNT", i.toString())
return this.mListDataHeader.size }
override fun getChildrenCount(groupPosition: Int): Int {
var childCount = 0
if (groupPosition == 2 || groupPosition == 3) {
childCount = this.mListDataChild[this.mListDataHeader[groupPosition]]!!.size
}
return childCount
}
override fun getGroup(groupPosition: Int): Any {
return this.mListDataHeader[groupPosition]
}
override fun getChild(groupPosition: Int, childPosition: Int): Any {
Log.d("CHILD", mListDataChild[this.mListDataHeader[groupPosition]]!!.get(childPosition))
return mListDataChild[this.mListDataHeader[groupPosition]]!!.get(childPosition)
}
override fun getGroupId(groupPosition: Int): Long {
return groupPosition.toLong()
}
override fun getChildId(groupPosition: Int, childPosition: Int): Long {
return childPosition.toLong()
}
override fun hasStableIds(): Boolean {
return false }
override fun getGroupView(groupPosition: Int, isExpanded: Boolean, convertView: View?, parent: ViewGroup): View {
var convertView = convertView
val headerTitle = getGroup(groupPosition) as ExpandedMenuModel
if (convertView == null) {
val infalInflater = mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
convertView = infalInflater.inflate(R.layout.listheader, null)
}
val lblListHeader = convertView!!.findViewById(R.id.submenu) as TextView
val headerIcon = convertView!!.findViewById(R.id.iconimage) as ImageView
// Expandable View, Indicator right
val headerIndicator = convertView.findViewById(R.id.indicatorImage) as ImageView
lblListHeader.setTypeface(null, Typeface.NORMAL)
lblListHeader.text = headerTitle.iconName
headerIcon.setImageResource(headerTitle.iconImg)
// Expandable View, Indicator status
if (getChildrenCount( groupPosition ) == 0) {
headerIndicator.visibility = View.GONE
} else {
headerIndicator.visibility = View.VISIBLE
if (isExpanded) {
headerIndicator.setBackgroundResource((R.drawable.ic_keyboard_arrow_up_black_18dp))
} else {
headerIndicator.setBackgroundResource((R.drawable.ic_keyboard_arrow_right_black_18dp))
}
}
return convertView
}
override fun getChildView(groupPosition: Int, childPosition: Int, isLastChild: Boolean, convertView: View?, parent: ViewGroup): View {
var convertView = convertView
val childText = getChild(groupPosition, childPosition) as String
if (convertView == null) {
val infalInflater = this.mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
convertView = infalInflater.inflate(R.layout.list_submenu, null)
}
val txtListChild = convertView!!
.findViewById(R.id.submenu) as TextView
txtListChild.text = childText
return convertView
}
override fun isChildSelectable(groupPosition: Int, childPosition: Int): Boolean {
return true
}
}
3. In MainActivity.kt , call your layout, add title and add onClickListener
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// ExpandableListView
setNavigationView = findViewById<View>(R.id.naviView) as NavigationView
setupDrawerContent(setNavigationView)
// Add content in drawer
prepareListData()
mMenuAdapter = ExpandableListAdapter(this, listDataHeader, listDataChild, navigationmenu!!)
navigationmenu!!.setAdapter(mMenuAdapter)
// Expandable View, hide original indicator
navigationmenu.setGroupIndicator(null)
//*******************************************************************//
// Set Listener, do anything you wanted
// Group = Big Title, Child = SubTitle
navigationmenu.setOnGroupClickListener({ parent, _, groupPosition, _ ->
when (groupPosition) {
// Position, first title = 0, second title = 1, .......
0 -> {
// Do anything you wanted
}
1 -> {
// Do anything you wanted
}
2 -> { //Example - How to expand the drawer list
if (parent.isGroupExpanded(groupPosition)) {
parent.collapseGroup(groupPosition)
} else {
parent.expandGroup(groupPosition)
parent.setOnChildClickListener({ parent, _, groupPosition, childPosition, _ -> when (childPosition) {
0 -> {
// Do anything you wanted
}
1 -> {
// Do anything you wanted
}
}
// Collapse the expanded list
parent.collapseGroup(groupPosition)
})
}
}
3 -> {
if (parent.isGroupExpanded(groupPosition)) {
parent.collapseGroup(groupPosition)
} else {
parent.expandGroup(groupPosition)
parent.setOnChildClickListener({ parent, _, groupPosition, childPosition, _ -> when (childPosition) {
0 -> {
// Do anything you wanted
}
1 -> {
// Do anything you wanted
}
2 -> {
// Do anything you wanted
}
}
parent.collapseGroup(groupPosition)
})
}
}
4 -> {
// Do anything you wanted
}
5 -> {
// Do anything you wanted
}
}
true })
}
private fun setupDrawerContent(navigationView: NavigationView?) {
navigationView?.setNavigationItemSelectedListener { menuItem ->
selectDrawerItem(menuItem)
true
}
}
// ExpandableListView, Drawer content
// Add Anything you wanted
private fun prepareListData() {
val drawerAddADDWII01 = ExpandedMenuModel()
// First Part, group(Big Title)
drawerAddADDWII01.iconName = getString(R.string.text_navi_add_device)
drawerAddADDWII01.iconImg = R.drawable.ic_bluetooth_searching_black_24dp
// Adding data header
listDataHeader.add(drawerAddADDWII01)
val drawerAccount02 = ExpandedMenuModel()
drawerAccount02.iconName = getString(R.string.text_navi_accountManagement)
drawerAccount02.iconImg = R.drawable.ic_account_box_black_24dp listDataHeader.add(drawerAccount02)
val drawerMap03 = ExpandedMenuModel()
drawerMap03.iconName = getString(R.string.text_navi_title_map)
drawerMap03.iconImg = R.drawable.ic_place_black_24dp listDataHeader.add(drawerMap03)
val drawerHelp04 = ExpandedMenuModel()
drawerHelp04.iconName = getString(R.string.text_navi_title_help)
drawerHelp04.iconImg = R.drawable.ic_help_black_24dp listDataHeader.add(drawerHelp04)
val drawerSetting05 = ExpandedMenuModel()
drawerSetting05.iconName = getString(R.string.text_navi_setting)
drawerSetting05.iconImg = R.drawable.ic_settings_black_24dp listDataHeader.add(drawerSetting05)
val drawerAbout06 = ExpandedMenuModel()
drawerAbout06.iconName = getString(R.string.text_navi_about)
drawerAbout06.iconImg = R.drawable.ic_phone_android_black_24dp listDataHeader.add(drawerAbout06)
// Second, Adding child data (Subtitle)
val childMap03 = ArrayList<String>()
childMap03.add(getString(R.string.text_navi_personal))
childMap03.add(getString(R.string.text_navi_air_map))
val childHelp04 = ArrayList<String>()
childHelp04.add(getString(R.string.text_navi_knowledge))
childHelp04.add(getString(R.string.text_navi_q_and_a))
childHelp04.add(getString(R.string.text_navi_tour))
// This case, only 2 of Big title have sub title
listDataChild[listDataHeader[2]] = childMap03
listDataChild[listDataHeader[3]] = childHelp04
}
Thanks