Android navigation drawer using RecyclerView
Dependencies in the app gradle.
implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.android.support:design:26.1.0' implementation 'com.android.support:recyclerview-v7:26.0.+'
DrawerFragment.kt, the drawer implementation in a fragment with all the ui listeners for clicking and touching events from the RecyclerView. Those events are passed back to the activity through FragmentDrawerListener, and the activity will decide what to do with these events.
import android.content.Context import android.os.Bundle import android.support.v4.app.Fragment import android.support.v4.widget.DrawerLayout import android.support.v7.app.ActionBarDrawerToggle import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.RecyclerView import android.support.v7.widget.Toolbar import android.view.GestureDetector import android.view.LayoutInflater import android.view.MotionEvent import android.view.View import android.view.ViewGroup import com.example.androidnavigationdrawerrecyclerview.adapter.DrawerAdapter import com.example.androidnavigationdrawerrecyclerview.data.DrawerItem import kotlinx.android.synthetic.main.fragment_drawer.* import java.util.ArrayList class DrawerFragment : Fragment() { private lateinit var adapter: DrawerAdapter private var drawerListener: FragmentDrawerListener? = null private var mDrawerLayout: DrawerLayout? = null private var containerView: View? = null override fun onAttach(context: Context?) { super.onAttach(context) try { drawerListener = context as FragmentDrawerListener } catch (e : RuntimeException) { e.printStackTrace() } } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.fragment_drawer, container, false) } override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) var titles = activity.resources.getStringArray(R.array.nav_drawer_labels) val data = ArrayList() for (i in titles.indices) { val navItem = DrawerItem(title = titles[i]) data.add(navItem) } adapter = DrawerAdapter(data) rv_drawer_list.adapter = adapter rv_drawer_list.layoutManager = LinearLayoutManager(activity) rv_drawer_list.addOnItemTouchListener(RecyclerTouchListener(activity, rv_drawer_list, object : ClickListener { override fun onClick(view: View, position: Int) { drawerListener?.onDrawerItemSelected(view, position) mDrawerLayout?.closeDrawer(containerView) } override fun onLongClick(view: View?, position: Int) { } })) } fun init(fragmentId: Int, drawerLayout: DrawerLayout, toolbar: Toolbar) { containerView = activity.findViewById(fragmentId) mDrawerLayout = drawerLayout val drawerToggle = object : ActionBarDrawerToggle(activity, drawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close) { override fun onDrawerOpened(drawerView: View?) { super.onDrawerOpened(drawerView) activity.invalidateOptionsMenu() } override fun onDrawerClosed(drawerView: View?) { super.onDrawerClosed(drawerView) activity.invalidateOptionsMenu() } override fun onDrawerSlide(drawerView: View?, slideOffset: Float) { super.onDrawerSlide(drawerView, slideOffset) toolbar.alpha = 1 - slideOffset / 2 } } mDrawerLayout?.addDrawerListener(drawerToggle) mDrawerLayout?.post { drawerToggle.syncState() } } interface ClickListener { fun onClick(view: View, position: Int) fun onLongClick(view: View?, position: Int) } internal class RecyclerTouchListener(context: Context, recyclerView: RecyclerView, private val clickListener: ClickListener?) : RecyclerView.OnItemTouchListener { private val gestureDetector: GestureDetector init { gestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() { override fun onSingleTapUp(e: MotionEvent): Boolean { return true } override fun onLongPress(e: MotionEvent) { val child = recyclerView.findChildViewUnder(e.x, e.y) if (child != null && clickListener != null) { clickListener.onLongClick(child, recyclerView.getChildAdapterPosition(child)) } } }) } override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean { val child = rv.findChildViewUnder(e.x, e.y) if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) { clickListener.onClick(child, rv.getChildAdapterPosition(child)) } return false } override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {} override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) { } } interface FragmentDrawerListener { fun onDrawerItemSelected(view: View, position: Int) } }
MainAcitvity.kt, the activity implements the FragmentDrawerListener and receives the ui events happening from the drawer in the fragment. It process the event in the function displayView.
import android.os.Bundle import android.support.v4.app.Fragment 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.* class MainActivity : AppCompatActivity(), DrawerFragment.FragmentDrawerListener { private lateinit var drawerFragment: DrawerFragment override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) setSupportActionBar(toolbar) drawerFragment = supportFragmentManager.findFragmentById(R.id.fragment_navigation_drawer) as DrawerFragment drawerFragment.init(R.id.fragment_navigation_drawer, drawer_layout, toolbar) displayView(0) } override fun onCreateOptionsMenu(menu: Menu): Boolean { // Inflate the menu; this adds items to the action bar if it is present. menuInflater.inflate(R.menu.menu_main, menu) return true } override fun onOptionsItemSelected(item: MenuItem): Boolean { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. return when (item.itemId) { R.id.action_settings -> true else -> super.onOptionsItemSelected(item) } } override fun onBackPressed() { if (drawer_layout.isDrawerOpen(GravityCompat.START)) { drawer_layout.closeDrawer(GravityCompat.START) } else { super.onBackPressed() } } override fun onDrawerItemSelected(view: View, position: Int) { displayView(position) } private fun displayView(position: Int) { var fragment: Fragment? = null var title = getString(R.string.app_name) when (position) { 0 -> { fragment = AFragment() title = getString(R.string.nav_item_one) } 1 -> { fragment = BFragment() title = getString(R.string.nav_item_two) } 2 -> { fragment = CFragment() title = getString(R.string.nav_item_three) } else -> { } } if (fragment != null) { val fragmentManager = supportFragmentManager val fragmentTransaction = fragmentManager.beginTransaction() fragmentTransaction.replace(R.id.main_content, fragment) fragmentTransaction.commit() supportActionBar?.title = title } } }
AFragment.kt, one of the fragments that is being displayed by the activity.
import android.os.Bundle import android.support.v4.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import kotlinx.android.synthetic.main.fragment_layout.* class AFragment : Fragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.fragment_layout, container, false) } override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) tv_label.text = "One" } }
activity_main.xml, the layout for the main activity. A drawerlayout with a custom implementation of the navigation draw in a fragment instead of the NavigationView provided by the design support library.
Custom navigation drawer with recyclerview only, no fragment
Search within Codexpedia
Search the entire web