📜  如何使用Kotlin在Android中为RecyclerView创建选项菜单?

📅  最后修改于: 2021-05-10 16:54:10             🧑  作者: Mango

RecyclerView是作为GridView和ListView的后继者添加到android studio的ViewGroup。这是对两者的改进,可以在最新的v-7支持包中找到。创建它的目的是使具有XML布局的任何列表的构造成为可能,并且可以在极大地自定义项目的同时提高ListViews和GridViews的效率。通过回收用户看不见的视图来实现此改进。例如,如果用户向下滚动到可以看到项目4和5的位置,则向下滚动;第1、2和3项将从内存中清除,以减少内存消耗。在本文中,我们将说明如何在RecyclerView的每个项目中使用“选项”菜单。以下是示例视频,展示了我们将要构建的内容。请注意,我们将使用Kotlin语言实施此项目。

分步实施

步骤1:创建一个新项目

要在Android Studio中创建新项目,请参阅如何在Android Studio中创建/启动新项目。请注意,选择Kotlin作为编程语言。

步骤2:添加视图绑定依赖项

转到android标签内的build.gradle(app)和以下依赖项,然后单击立即同步

步骤3:使用activity_main.xml文件

转到activity_main.xml文件,并参考以下代码。以下是activity_main.xml文件的代码。它只有一个Recycler视图,我们将用它来显示数据。

XML


      
    
    
  


XML


  
    
        
        
        
        
        
        
        
        
        
        
        
        
          
    
  


Kotlin
// this is the Language model class
class Language(
    val name : String ="",
    val exp : String = ""
)


Kotlin
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.geeksforgeeks.rvadapterviewbinding.databinding.SingleItemBinding
  
class RvAdapter(
    private var languageList: List,
    private var optionsMenuClickListener: OptionsMenuClickListener
) : RecyclerView.Adapter() {
  
    // create an interface for onClickListener
    // so that we can handle data most effectively in MainActivity.kt
    interface OptionsMenuClickListener {
        fun onOptionsMenuClicked(position: Int)
    }
  
    // create an inner class with name ViewHolder
    // It takes a view argument, in which pass the generated class of single_item.xml
    // ie SingleItemBinding and in the RecyclerView.ViewHolder(binding.root) pass it like this
    inner class ViewHolder(val binding: SingleItemBinding) : RecyclerView.ViewHolder(binding.root)
  
    // inside the onCreateViewHolder inflate the view of SingleItemBinding
    // and return new ViewHolder object containing this layout
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = SingleItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return ViewHolder(binding)
    }
  
    // bind the items with each item of the list languageList which than will be
    // shown in recycler view
    // to keep it simple we are not setting any image data to view
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        with(holder){
            with(languageList[position]){
                // set text to language name
                binding.tvLangName.text = this.name
                // set exp
                binding.tvExp.text = this.exp
                // implement on clickListener and pass position of the item
                // rest we will handle in MainActivity.kt
                binding.textViewOptions.setOnClickListener {
                    optionsMenuClickListener.onOptionsMenuClicked(position)
                }
            }
        }
    }
  
    // return the size of languageList
    override fun getItemCount(): Int {
        return languageList.size
    }
}


Kotlin
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.MenuItem
import android.widget.PopupMenu
import android.widget.Toast
import androidx.core.view.get
import androidx.recyclerview.widget.LinearLayoutManager
import com.geeksforgeeks.rvadapterviewbinding.databinding.ActivityMainBinding
  
class MainActivity : AppCompatActivity() {
  
    // view binding for the activity
    private var _binding: ActivityMainBinding? = null
    private val binding get() = _binding!!
  
    // get reference to the adapter class
    private var languageList = ArrayList()
    private lateinit var rvAdapter: RvAdapter
  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        _binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
  
        // define layout manager for the Recycler view
        binding.rvList.layoutManager = LinearLayoutManager(this)
        // attach adapter to the recycler view and also handle item click
        rvAdapter = RvAdapter(languageList , object : RvAdapter.OptionsMenuClickListener{
            // implement the required method
            override fun onOptionsMenuClicked(position: Int) {
                // this method will handle the onclick options click
                // it is defined below
                performOptionsMenuClick(position)
            }
        })
        // add adapter to the recycler view
        binding.rvList.adapter = rvAdapter
  
        // create objects of Language
        // create some row data
        val language1 = Language("Java" , "3 Year exp" )
        val language2 = Language("Kotlin" , "2 Year exp" )
        val language3 = Language("Python" , "1 Year exp" )
        val language4 = Language("CPP" , "5 Year exp" )
        val language5 = Language("PHP" , "No exp" )
  
        // pass raw data t rhe list
        languageList.add(language1)
        languageList.add(language2)
        languageList.add(language3)
        languageList.add(language4)
        languageList.add(language5)
  
        rvAdapter.notifyDataSetChanged()
    }
  
    // this method will handle the onclick options click
    private fun performOptionsMenuClick(position: Int) {
        // create object of PopupMenu and pass context and view where we want
        // to show the popup menu
        val popupMenu = PopupMenu(this , binding.rvList[position].findViewById(R.id.textViewOptions))
        // add the menu
        popupMenu.inflate(R.menu.options_menu)
        // implement on menu item click Listener
        popupMenu.setOnMenuItemClickListener(object : PopupMenu.OnMenuItemClickListener{
            override fun onMenuItemClick(item: MenuItem?): Boolean {
                when(item?.itemId){
                    R.id.delete -> {
                        // here are the logic to delete an item from the list
                        val tempLang = languageList[position]
                        languageList.remove(tempLang)
                        rvAdapter.notifyDataSetChanged()
                        return true
                    }
                    // in the same way you can implement others
                    R.id.item2 -> {
                        // define
                        Toast.makeText(this@MainActivity , "Item 2 clicked" , Toast.LENGTH_SHORT).show()
                        return true
                    }
                    R.id.item3 -> {
                        // define
                        Toast.makeText(this@MainActivity , "Item 3 clicked" , Toast.LENGTH_SHORT).show()
                        return true
                    }
                }
                return false
            }
        })
        popupMenu.show()
    }
  
    // on destroy of view make the binding reference to null
    override fun onDestroy() {
        super.onDestroy()
        _binding = null
    }
}


步骤4:创建一个新的布局文件并将其命名为single_item.xml文件

转到single_item.xml文件,并参考以下代码。以下是single_item.xml文件的代码。这是我们将在RecyclerView中使用的单个项目布局。

XML格式



  
    
        
        
        
        
        
        
        
        
        
        
        
        
          
    
  

步骤5:创建一个新的模型类

创建一个新的Language.kt类,我们将使用自定义通用“ Language ”的数据来传递将在回收者视图中显示的列表。

科特林

// this is the Language model class
class Language(
    val name : String ="",
    val exp : String = ""
)

步骤6:使用适配器类

创建一个新的类RvAdapter.kt,它将充当回收者视图的Adapter类。为了更好的理解,在代码之前添加了注释。

科特林

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.geeksforgeeks.rvadapterviewbinding.databinding.SingleItemBinding
  
class RvAdapter(
    private var languageList: List,
    private var optionsMenuClickListener: OptionsMenuClickListener
) : RecyclerView.Adapter() {
  
    // create an interface for onClickListener
    // so that we can handle data most effectively in MainActivity.kt
    interface OptionsMenuClickListener {
        fun onOptionsMenuClicked(position: Int)
    }
  
    // create an inner class with name ViewHolder
    // It takes a view argument, in which pass the generated class of single_item.xml
    // ie SingleItemBinding and in the RecyclerView.ViewHolder(binding.root) pass it like this
    inner class ViewHolder(val binding: SingleItemBinding) : RecyclerView.ViewHolder(binding.root)
  
    // inside the onCreateViewHolder inflate the view of SingleItemBinding
    // and return new ViewHolder object containing this layout
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = SingleItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return ViewHolder(binding)
    }
  
    // bind the items with each item of the list languageList which than will be
    // shown in recycler view
    // to keep it simple we are not setting any image data to view
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        with(holder){
            with(languageList[position]){
                // set text to language name
                binding.tvLangName.text = this.name
                // set exp
                binding.tvExp.text = this.exp
                // implement on clickListener and pass position of the item
                // rest we will handle in MainActivity.kt
                binding.textViewOptions.setOnClickListener {
                    optionsMenuClickListener.onOptionsMenuClicked(position)
                }
            }
        }
    }
  
    // return the size of languageList
    override fun getItemCount(): Int {
        return languageList.size
    }
}

步骤7:使用MainActivity.kt

转到MainActivity.kt文件,并参考以下代码。下面是MainActivity.kt文件的代码。在代码内部添加了注释,以更详细地了解代码。

科特林

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.MenuItem
import android.widget.PopupMenu
import android.widget.Toast
import androidx.core.view.get
import androidx.recyclerview.widget.LinearLayoutManager
import com.geeksforgeeks.rvadapterviewbinding.databinding.ActivityMainBinding
  
class MainActivity : AppCompatActivity() {
  
    // view binding for the activity
    private var _binding: ActivityMainBinding? = null
    private val binding get() = _binding!!
  
    // get reference to the adapter class
    private var languageList = ArrayList()
    private lateinit var rvAdapter: RvAdapter
  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        _binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
  
        // define layout manager for the Recycler view
        binding.rvList.layoutManager = LinearLayoutManager(this)
        // attach adapter to the recycler view and also handle item click
        rvAdapter = RvAdapter(languageList , object : RvAdapter.OptionsMenuClickListener{
            // implement the required method
            override fun onOptionsMenuClicked(position: Int) {
                // this method will handle the onclick options click
                // it is defined below
                performOptionsMenuClick(position)
            }
        })
        // add adapter to the recycler view
        binding.rvList.adapter = rvAdapter
  
        // create objects of Language
        // create some row data
        val language1 = Language("Java" , "3 Year exp" )
        val language2 = Language("Kotlin" , "2 Year exp" )
        val language3 = Language("Python" , "1 Year exp" )
        val language4 = Language("CPP" , "5 Year exp" )
        val language5 = Language("PHP" , "No exp" )
  
        // pass raw data t rhe list
        languageList.add(language1)
        languageList.add(language2)
        languageList.add(language3)
        languageList.add(language4)
        languageList.add(language5)
  
        rvAdapter.notifyDataSetChanged()
    }
  
    // this method will handle the onclick options click
    private fun performOptionsMenuClick(position: Int) {
        // create object of PopupMenu and pass context and view where we want
        // to show the popup menu
        val popupMenu = PopupMenu(this , binding.rvList[position].findViewById(R.id.textViewOptions))
        // add the menu
        popupMenu.inflate(R.menu.options_menu)
        // implement on menu item click Listener
        popupMenu.setOnMenuItemClickListener(object : PopupMenu.OnMenuItemClickListener{
            override fun onMenuItemClick(item: MenuItem?): Boolean {
                when(item?.itemId){
                    R.id.delete -> {
                        // here are the logic to delete an item from the list
                        val tempLang = languageList[position]
                        languageList.remove(tempLang)
                        rvAdapter.notifyDataSetChanged()
                        return true
                    }
                    // in the same way you can implement others
                    R.id.item2 -> {
                        // define
                        Toast.makeText(this@MainActivity , "Item 2 clicked" , Toast.LENGTH_SHORT).show()
                        return true
                    }
                    R.id.item3 -> {
                        // define
                        Toast.makeText(this@MainActivity , "Item 3 clicked" , Toast.LENGTH_SHORT).show()
                        return true
                    }
                }
                return false
            }
        })
        popupMenu.show()
    }
  
    // on destroy of view make the binding reference to null
    override fun onDestroy() {
        super.onDestroy()
        _binding = null
    }
}

输出:

Github仓库在这里。

想要一个节奏更快,更具竞争性的环境来学习Android的基础知识吗?
单击此处前往由我们的专家精心策划的指南,以使您立即做好行业准备!