在recyclerview适配器(Kotlin)中处理按钮单击?

马特·格里尔

我有一个适配器,其中每个项都有3个按钮,它们会生成一个对话框,然后执行一个动作。我感觉应该从适配器中删除它(我有可用的视图模型),但是它起作用了,我在想:我是否应该将逻辑移到片段,视图模型,是否需要全部移走(下面的代码是不好的做法,如果是,为什么呢?任何帮助/输入将不胜感激。

这是适配器代码:

class ViewRecipesAdapter(val context: Context, private val recipes: List<Recipe>, private val parentFragment: Fragment) :
        RecyclerView.Adapter<ViewRecipesAdapter.RecipeViewHolder>()
{

    private var listToUse: List<Recipe> = recipes
    private lateinit var recipesViewModel: RecipesViewModel
    private var isView = false


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecipeViewHolder
    {
        val layoutInflater = LayoutInflater.from(parent.context)
        val binding: ViewRecipesItemBinding =
                DataBindingUtil.inflate(layoutInflater, R.layout.view_recipes_item, parent, false)

        return RecipeViewHolder(binding, context)
    }

    override fun getItemCount() = listToUse.size

    override fun onBindViewHolder(holder: RecipeViewHolder, position: Int)
    {

        val recipe = listToUse[position]
        // to delete and edit items
        val dao = RecipesDatabase.getInstance(context).recipeDao()

        val repository = RecipeRepository(dao)
        recipesViewModel = RecipesViewModel(repository)
        //display data on list item
        holder.bind(recipe)
        Glide.with(context).load(recipe.imageOne)
                .into(holder.binding.imageViewItemImage)
        //tried to handle clicks here through the viewModel but I could not get it working from fragment
        //the function call after viewModel calls is what works and it seems to work well
        holder.binding.imageButtonItemdelete.setOnClickListener {
            recipesViewModel.setIsDelete(true)
            recipesViewModel.setPositionFromAdapter(position)
            startDeleteDialog(position)
        }
        holder.binding.imageButtonItemedit.setOnClickListener {
            recipesViewModel.setIsView(false)
            recipesViewModel.setPositionFromAdapter(position)
            isView = false
            startEditOrViewDialog(position)
        }
        holder.binding.imageButtonItemview.setOnClickListener {
            recipesViewModel.setIsView(true)
            recipesViewModel.setPositionFromAdapter(position)
            isView = true
            startEditOrViewDialog(position)
        }

    }

    fun setList(newList: List<Recipe>)
    {
        listToUse = newList
    }

    //dialog functions for the edit, delete, and view buttons on each item
    private fun startDeleteDialog(position: Int)
    {
        AlertDialog.Builder(context)
                .setTitle("Delete recipe?")
                .setPositiveButton("Yes") { _, _ ->
                    recipesViewModel.deleteRecipe(recipes[position])
                    notifyItemRemoved(position)
                }
                .setNegativeButton("No") { dialog, _ ->
                    dialog.dismiss()
                }.show()
    }

    private fun startEditOrViewDialog(position: Int)
    {
        when (isView)
        {
            true ->
            {
                AlertDialog.Builder(context).setTitle("View recipe?")
                        .setPositiveButton("Yes") { _, _ ->
                            //get relevant data from current recipe
                            val recipe = recipes[position]
                            //create a dialog that shows this data in an inflated layout
                            val viewDialog = AlertDialog.Builder(context)
                            val inflater = LayoutInflater.from(context)
                            val view = inflater.inflate(R.layout.fragment_edit_or_view, null)

                            view.editText_editrecipe_directions.setText(recipe.directions)
                            view.editText_editrecipe_ingredients.setText(recipe.ingredients)
                            view.editText_editrecipe_notes.setText(recipe.notes)
                            view.editText_editrecipe_title.setText(recipe.title)
                            view.textView_date_edit.text = recipe.date
                            view.editText_editrecipe_title.keyListener = null
                            view.editText_editrecipe_directions.keyListener = null
                            view.editText_editrecipe_ingredients.keyListener = null
                            view.editText_editrecipe_notes.keyListener = null
                            if (recipe.rating != null)
                            {
                                view.ratingBar_edit.rating = recipe.rating
                            }
                            Glide.with(context)
                                    .load(recipe.imageOne)
                                    .into(view.imageView_addphoto_edit)
                            viewDialog.setView(view).show()
                        }
                        .setNegativeButton("No") { dialog, _ ->
                            dialog.dismiss()
                        }.show()
            }
            false ->
            {
                AlertDialog.Builder(context).setTitle("Edit recipe?")
                        .setPositiveButton("Yes") { _, _ ->
                            //get relevant data from current recipe
                            val recipe = recipes[position]
                            val idString = recipe.id.toString()
                            recipesViewModel.setId(idString)
                            recipesViewModel.getRecipeById2(idString)
                            notifyDataSetChanged()

                            val controller = parentFragment.findNavController()
                            controller.navigate(
                                ViewRecipesFragmentDirections.actionNavViewrecipesToNavAddrecipe(
                                    recipe.id.toString()
                                )
                            )
                        }
                        .setNegativeButton("No") { dialog, _ ->
                            dialog.dismiss()
                        }.show()
            }
        }
    }

    override fun getItemId(position: Int): Long
    {
        return position.toLong()
    }

    override fun getItemViewType(position: Int): Int
    {
        return position
    }


    class RecipeViewHolder(val binding: ViewRecipesItemBinding, val context: Context) :
            RecyclerView.ViewHolder(binding.root)
    {

        fun bind(recipe: Recipe)
        {
            if (recipe.isLeftover == true)
            {
                binding.tvIsLeftovers.visibility = View.VISIBLE
            }
            binding.textViewItemTitle.text = recipe.title

            if (recipe.date != null)
            {
                binding.textViewItemDate.text = recipe.date
            }
            if (recipe.rating != null)
            {
                binding.ratingBar2.rating = recipe.rating
            }
            binding.root.animation = AlphaAnimation(0.0f, 1.0f).apply {
                duration = 1000
            }
        }
    }
}

这是视图模型,设置了实时数据变量,使我无法使用此RecyclerView所在的片段:

class RecipesViewModel(private val repository: RecipeRepository) : ViewModel()
{
    val recipesList = repository.getAllRecipes()

    private val _isView = MutableLiveData<Boolean>()
    val isView: MutableLiveData<Boolean> = _isView

    private val _isEdit = MutableLiveData<Boolean>()
    val isEdit: MutableLiveData<Boolean> = _isEdit

    private val _positionFromAdapter = MutableLiveData<Int>()
    val positionFromAdapter: MutableLiveData<Int> = _positionFromAdapter

    private val _isDelete = MutableLiveData<Boolean>()
    val isDelete: MutableLiveData<Boolean> = _isDelete

    private val _recipesListFromSearch = MutableLiveData<List<Recipe>>()
    val recipesListFromSearch: LiveData<List<Recipe>> = _recipesListFromSearch

    private val _recipe = MutableLiveData<Recipe>()

    val recipe: LiveData<Recipe> = _recipe

    lateinit var searchString: String

    val savedId = MutableLiveData<String>()

    fun setPositionFromAdapter(position: Int)
    {
        _positionFromAdapter.value = position
    }

    fun setIsView(isView: Boolean)
    {
        _isView.value = isView
    }

    fun setIsDelete(isDelete: Boolean)
    {
        _isView.value = isDelete
    }

    fun setIsEdit(isEdit: Boolean)
    {
        _isEdit.value = isEdit
    }

    fun setId(id: String)
    {
        savedId.value = id
    }

    fun insertRecipe(recipe: Recipe)
    {
        CoroutineScope(Dispatchers.IO).launch {
            repository.insertRecipe(recipe)
        }
    }

    fun getRecipesFromQuery(query: String)
    {
        CoroutineScope(Dispatchers.IO).launch {
            val list = repository.getRecipesSearch(query)
            MainScope().launch { _recipesListFromSearch.value = list }
        }
    }

    fun saveUserRecipeToDb(
        title: String?,
        ingredients: String?,
        directions: String?,
        notes: String?,
        uriToSave: String?,
        rating: Float?,
        date: String?,
        isLeftover: Boolean,
        loadedId: String
    ): Boolean
    {
        val recipeToSave = Recipe(
            title,
            ingredients,
            directions,
            notes,
            uriToSave,
            null,
            null,
            rating,
            date,
            isLeftover
        )
        if (loadedId != "666")
        {
            recipeToSave.id = loadedId.toInt()
        }
        insertRecipe(recipeToSave)
        return false
    }

    fun getRecipeById2(id: String) = repository.getRecipeByIdLive(id)

    fun deleteRecipe(recipe: Recipe)
    {
        CoroutineScope(Dispatchers.IO).launch {
            repository.deleteRecipe(recipe)
        }
    }
}
我知道

如何onClick在RecyclerView中实施假设在“回收站”中,每个视图都是某些视图的可视化,item并且当您单击该视图时,您想要对该项目执行某些操作:

  1. 创建课程ClickListener::
class ClickListener(
    val clickListener: (itemId: Int) -> Unit,
)
{
    fun onClick(item: ItemClass) = clickListener(item.id)
}
  1. 现在,在您的RecylerViewAdapter中,此侦听器作为参数传递:
class RecylerViewAdapter(
    private val clickListener: ClickListener
)
  1. onBindViewHolder通过这Listenner作为参数
override fun onBindViewHolder(holder: ViewHolder, position: Int)
{
    holder.bind(getItem(position)!!, clickListener)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder
{
    return ViewHolder.from(
        parent
    )
}
  1. 在您的ViewHolder类中:
class ViewHolder private constructor(private val binding: ItemRecyclerBinding) :
        RecyclerView.ViewHolder(binding.root)
{
    companion object
    {
        fun from(parent: ViewGroup): ViewHolder
        {
            val layoutInflater = LayoutInflater.from(parent.context)
            val binding = ItemRecyclerBinding.inflate(layoutInflater, parent, false)
            return ViewHolder(
                binding
            )
        }
    }


    fun bind(
        item : Item,
        clickListener: ClickListener
    )
    {
        binding.item = item
        binding.clickListener = clickListener
        binding.executePendingBindings()
    }
}
  1. 在您的项目布局(必须将其转换为数据绑定布局)中添加以下内容:
<data>
    <variable
        name="item"
        type="com.example.sth.database.Item" /> // path to `Item`
    <variable
        name="clickListener"
        type="com.example.sth.ui.adapter.ClickListener" /> // Path to `ClickListener`
</data>
  1. 现在您可以onClick向Button添加方法:
android:onClick="@{() -> clickListener.onClick(item)}"
  1. 在片段或活动中创建适配器时,必须将其clickListenner作为参数传递这样,您可以处理片段中的所有内容,而RecyclerView并不关心您在此功能中所做的事情。
val clickListenner = ClickListenner(
    { id -> viewModel.clickItemWithid(id) }, // click. This function from ViewModel will be executed when You click on item in recycler View
)

val adapter = RecylerViewAdapter (
    clickListenner
)

此方法基于Udacity上的Google开发人员代码实验室。
在这里您可以检查整个代码实验室。它是免费的
这只是一个实现点击监听器的视频

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

单击适配器内的按钮后,从自己的活动更改recyclerview适配器项目

如何从Android Kotlin中的RecyclerView适配器获取arraylist

在 Kotlin 适配器中处理 setOnClickListener 和 setOnLongClickListener

带仅按钮适配器的RecyclerView

RecyclerView() 适配器

RecyclerView适配器中的onBackPressed()

从适配器中刷新整个RecyclerView

在RecyclerView适配器中显示FragmentDialog

在recyclerview适配器中更改项目

在RecyclerView适配器中显示sharedpreference

RecyclerView适配器中的LayoutInflater

RecyclerView适配器中的导航组件

模仿RecyclerView适配器中的“ onActivityResult”

按钮Listview适配器中的showDialog

Worklight适配器中的xml处理

如何在自定义适配器中更改按钮单击时的按钮文本

如何使用Recyclerview中单击的适配器位置获取数据?

从适配器单击时,如何获取 RecyclerView 中的选定位置?

RecyclerView,适配器,单击侦听器和AsyncTask

Android:如何通过单击 RecyclerView 外部的按钮将所有数据从 RecyclerView 适配器传递到 NewActivity?

单击活动类中的按钮,如何在适配器的微调器上过滤列表

带按钮的Recyclerview适配器不起作用

E / RecyclerView:未连接适配器;跳过Android,kotlin中的布局

如何从适配器到Android Kotlin recyclerview中的活动获取变量值?

有没有办法在 recyclerview 适配器(Kotlin)中更改 LinearLayout 宽度

适配器类中的 OnClickListener 按钮使 Kotlin 中的应用程序崩溃

将通用的RecyclerView适配器转换为Kotlin

Kotlin-cant从RecyclerView适配器替换片段

RecyclerView:没有附加适配器;跳过布局 - kotlin