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
You save my life ahahah.. I was looking for this implementation and I didn't find something updated in these days.. your solution gives me a better understanding of how to implement items Expandables
回覆刪除Thanks alot!!