如何获取 RecyclerView 列表项的上下文?

huangapple go评论82阅读模式
英文:

How would I get the context of a RecyclerView List Item?

问题

以下是您提供的代码的翻译部分:

ShoppingListFragment.kt

class ShoppingListFragment : Fragment() {
    // ...(略去了部分代码)

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // 启用 Firestore 日志记录
        FirebaseFirestore.setLoggingEnabled(true)

        // 初始化 Firestore
        firestore = Firebase.firestore

        // 获取用户喜欢的食谱,最多 ${LIMIT} 个
        query = firestore.collection("recipes").whereArrayContains(
            "plannedBy",
            Firebase.auth.uid.toString()
        )
            .orderBy("name", Query.Direction.ASCENDING)
            .limit(LIMIT.toLong())

        // 初始化适配器来保存食谱对象
        adapter = object : ShoppingListAdapter(query) {
            override fun onDataChanged() {
                if (itemCount == 0) {
                    shoppingListRecycler.visibility = View.GONE
                    viewEmpty.visibility = View.VISIBLE
                } else {
                    shoppingListRecycler.visibility = View.VISIBLE
                    viewEmpty.visibility = View.GONE
                }
            }

            override fun onError(e: FirebaseFirestoreException) {
                // 发生错误时显示一个 Snackbar
                view?.let {
                    Snackbar.make(
                        it,
                        "错误:请查看日志获取信息。",
                        Snackbar.LENGTH_LONG
                    ).show()
                }
            }
        }
         // ...
    }
    // ...
}

ShoppingListAdapter.kt

open class ShoppingListAdapter(query: Query) :
    FirestoreAdapter<ShoppingListViewHolder>(query) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ShoppingListViewHolder {
        return ShoppingListViewHolder(
            ItemShoppingListBinding.inflate(
                LayoutInflater.from(parent.context), parent, false))
    }

    override fun onBindViewHolder(holder: ShoppingListViewHolder, position: Int) {
        holder.bind(getSnapshot(position))
    }
}

ShoppingListViewHolder.kt

class ShoppingListViewHolder(val binding: ItemShoppingListBinding) :
    RecyclerView.ViewHolder(binding.root) {

    fun bind(snapshot: DocumentSnapshot) {

        val recipe = snapshot.toObject<Recipe>() ?: return

        binding.listTitle.text = recipe.name
        if (recipe.ingredients.size > 1) {
            binding.shoppingListItem.text = recipe.ingredients[0].original

            for (i in 1 until recipe.ingredients.size) {
                val checkBox = CheckBox(binding.root.context) // 在此处使用 recyclerview 列表项的上下文
                checkBox.text = recipe.ingredients[i].original
                checkBox.layoutParams = LinearLayout.LayoutParams(
                    ViewGroup.LayoutParams.WRAP_CONTENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT)
                binding.shoppingListContainer.addView(checkBox)
            }
        } else {
            binding.shoppingListItem.text = recipe.ingredients[0].original
        }
    }
}

请注意,我已经将代码中的注释翻译成了中文。如果您有关于翻译的任何问题,请随时询问。

英文:

I am new to Firebase and RecyclerViews and I am trying to get a list of ingredients from my Firebase Database and I want to create checkboxes for every item I retrieve from the database. I got as far as creating a RecyclerView and adapter for my Firebase Query but binding lists from the query doesn't seem to be covered anywhere I could find.

Please find below the code for putting the data into the recycler view as well as the layout files being used for the recycler view.

Data being retrieved
that I want to display the original field of my object as checkboxes

ShoppingListFragment.kt

class ShoppingListFragment : Fragment() {



    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        //Enable Firestore logging
        FirebaseFirestore.setLoggingEnabled(true)

        //Firestore
        firestore = Firebase.firestore

        // Get recipes that the user has liked up to ${LIMIT}
        query = firestore.collection(&quot;recipes&quot;).whereArrayContains(
            &quot;plannedBy&quot;,
            Firebase.auth.uid.toString()
        )
            .orderBy(&quot;name&quot;, Query.Direction.ASCENDING)
            .limit(LIMIT.toLong())


        // Init the adapter to hold the recipe objects.
        adapter = object : ShoppingListAdapter(query) {
            override fun onDataChanged() {
                if (itemCount == 0) {
                    shoppingListRecycler.visibility = View.GONE
                    viewEmpty.visibility = View.VISIBLE
                } else {
                    shoppingListRecycler.visibility = View.VISIBLE
                    viewEmpty.visibility = View.GONE
                }

            }

            override fun onError(e: FirebaseFirestoreException) {
                // Show a snackbar on errors
                view?.let {
                    Snackbar.make(
                        it,
                        &quot;Error: check logs for info.&quot;, Snackbar.LENGTH_LONG
                    ).show()
                }
            }

        }
         ...

    }
...

}

ShoppingListAdapter.kt

open class ShoppingListAdapter(query: Query) :
    FirestoreAdapter&lt;ShoppingListViewHolder&gt;(query) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ShoppingListViewHolder {
        return ShoppingListViewHolder(
            ItemShoppingListBinding.inflate(
                LayoutInflater.from(parent.context), parent, false))
    }


    override fun onBindViewHolder(holder: ShoppingListViewHolder, position: Int) {
        holder.bind(getSnapshot(position))
    }


}

ShoppingListViewHolder.kt

class ShoppingListViewHolder(val binding: ItemShoppingListBinding) :
    RecyclerView.ViewHolder(binding.root) {

    fun bind(snapshot: DocumentSnapshot) {

        val recipe = snapshot.toObject&lt;Recipe&gt;() ?: return

        binding.listTitle.text = recipe.name
        if(recipe.ingredients.size &gt; 1) {
            binding.shoppingListItem.text = recipe.ingredients[0].original

            for(i in 1 until recipe.ingredients.size) {
                val checkBox = CheckBox() //Not sure what to put here as the context for my recyclerview List Item

                checkBox.text = recipe.ingredients[i].original
                checkBox.layoutParams = LinearLayout.LayoutParams(
                    ViewGroup.LayoutParams.WRAP_CONTENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT)

                binding.shoppingListContainer.addView(checkBox)
            }


        } else {
            binding.shoppingListItem.text = recipe.ingredients[0].original
        }
    }
}

I have tried passing a context parameter through ShoppingListViewHolder.kt and in turn adding that parameter to the adapter and so forth like so.

class ShoppingListViewHolder(val binding: ItemShoppingListBinding, val context: Context) : RecyclerView.ViewHolder(binding.root) {
   
    fun bind(snapshot: DocumentSnapshot) {

        val recipe = snapshot.toObject&lt;Recipe&gt;() ?: return

        binding.listTitle.text = recipe.name
        if(recipe.ingredients.size &gt; 1) {
            binding.shoppingListItem.text = recipe.ingredients[0].original

            for(i in 1 until recipe.ingredients.size) {
                val checkBox = CheckBox(context) 
            ...

}

ShoppingListFragment.kt

        // Init the adapter to hold the recipe objects.
        adapter = object : ShoppingListAdapter(query, requireContext()) {
            override fun onDataChanged() {
                if (itemCount == 0) {
                    shoppingListRecycler.visibility = View.GONE
                    viewEmpty.visibility = View.VISIBLE
                } else {
                    shoppingListRecycler.visibility = View.VISIBLE
                    viewEmpty.visibility = View.GONE
                }

            }

            override fun onError(e: FirebaseFirestoreException) {
                // Show a snackbar on errors
                view?.let {
                    Snackbar.make(
                        it,
                        &quot;Error: check logs for info.&quot;, Snackbar.LENGTH_LONG
                    ).show()
                }
            }

        }

But all that did was create a huge amount of white space between entries. After some debugging, it looks like passing the context from the fragment gave it the MainActivity context. I'm not too sure where to go from here and any help would be appreciated. Thank you!

答案1

得分: 0

你可以使用binding.root.context,而不是传递context

英文:

you can use binding.root.context except passing context

huangapple
  • 本文由 发表于 2020年10月5日 14:00:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/64203155.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定