[英]How to navigate to 2 different fragments using same adapter according to the type of model?
我想根據我的 model 的類型使用相同的適配器導航 2 個不同的片段。但我的問題是我無法使用兩種不同的模型處理 onItemClicked。 如你看到的:
private val onItemClicked: (WordsWithMeanings) -> Unit
最喜歡的片段
class FavoriteFragment : Fragment(R.layout.fragment_favorite) {
private var _binding: FragmentFavoriteBinding? = null
private val binding get() = _binding!!
private val viewModel: WordViewModel by activityViewModels {
WordViewModelFactory(
(activity?.application as WordApplication).database.wordDao()
)
}
private lateinit var adapter: FavoriteListAdapter
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentFavoriteBinding.inflate(inflater)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
adapter = FavoriteListAdapter(viewModel) {
val action = FavoriteFragmentDirections.actionFavouriteFragmentToWordDetailFragment(it).
this.findNavController().navigate(action)
}
binding.recyclerView.adapter = adapter
viewModel.allWordsWithMeanings.observe(this.viewLifecycleOwner) { items ->
items.let {
for (i in items) {
if (i.word.isFavorite == true) {
adapter.mData.add(i)
}
}
}
favoriteFragmentFavoriteStatus()
}
viewModel.allProverbs.observe(this.viewLifecycleOwner) { items ->
items.let {
for (i in items) {
if (i.isFavorite == true) {
adapter.mData.add(i)
}
}
}
}
binding.recyclerView.layoutManager = LinearLayoutManager(this.context)
}
}`
```
收藏列表適配器
private const val WORD_VIEW_TYPE = 0
private const val PROVERB_VIEW_TYPE = 1
class FavoriteListAdapter(
private val viewModel: WordViewModel,
private val onItemClicked: (WordsWithMeanings) -> Unit
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
val mData = mutableListOf<Any>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return when (viewType) {
WORD_VIEW_TYPE -> WordItemViewHolder(
FavoriteItemsBinding.inflate(
inflater,
parent,
false
)
)
PROVERB_VIEW_TYPE -> ProverbItemViewHolder(
FavoriteItemsBinding.inflate(
inflater,
parent,
false
)
)
else -> throw IllegalArgumentException("Invalid view type")
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val element = mData[position]
when (getItemViewType(position)) {
WORD_VIEW_TYPE -> {
holder.itemView.setOnClickListener {
onItemClicked(element as WordsWithMeanings)
}
(holder as WordItemViewHolder).bind(
element as WordsWithMeanings,
viewModel
)
}
PROVERB_VIEW_TYPE -> {
(holder as ProverbItemViewHolder).bind(element as Proverb, viewModel)
}
}
}
class WordItemViewHolder(private var binding: FavoriteItemsBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(favoriteWordsWithMeanings: WordsWithMeanings, viewModel: WordViewModel) {
binding.apply {
title.text = favoriteWordsWithMeanings.word.word
content.text = favoriteWordsWithMeanings.means[0].wordMean
favoriteButton.isChecked =
favoriteWordsWithMeanings.word.isFavorite == true
favoriteButton.setOnClickListener {
if (favoriteButton.isChecked) {
favoriteButton.isChecked = true
viewModel.updateFavoriteWord(favoriteWordsWithMeanings, true)
} else {
favoriteButton.isChecked = false
viewModel.updateFavoriteWord(favoriteWordsWithMeanings, false)
}
}
}
}
}
class ProverbItemViewHolder(private var binding: FavoriteItemsBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(favoriteProverb: Proverb, viewModel: WordViewModel) {
binding.apply {
title.text = favoriteProverb.proverb
content.text = favoriteProverb.proverbMean
favoriteButton.isChecked =
favoriteProverb.isFavorite == true
favoriteButton.setOnClickListener {
if (favoriteButton.isChecked) {
favoriteButton.isChecked = true
viewModel.updateFavoriteProverb(favoriteProverb, true)
} else {
favoriteButton.isChecked = false
viewModel.updateFavoriteProverb(favoriteProverb, false)
}
}
}
}
}
override fun getItemCount(): Int {
return mData.size
}
override fun getItemViewType(position: Int): Int {
return when (mData[position]) {
is WordsWithMeanings -> WORD_VIEW_TYPE
is Proverb -> PROVERB_VIEW_TYPE
else -> throw IllegalArgumentException("Unsupported type")
}
}
}
所以我只導航到一個片段。 我想要做的是,如果單擊的項目是“WordsWithMeanings”,則導航到 WordDetailFragment,如果單擊的項目是“Proverb”,則導航到 ProverbDetailFragment。 有沒有正確的方法來做到這一點?
解決方案:
首先我改變了這個
private val onItemClicked: (WordsWithMeanings) -> Unit
對此
private val onItemClicked: (Any) -> Unit
之后使用這樣的操作解決了我的問題。
action = if (it is WordsWithMeanings) {
FavoriteFragmentDirections.actionFavouriteFragmentToWordDetailFragment(it)
} else {
FavoriteFragmentDirections.actionFavouriteFragmentToProverbDetailFragment(it as Proverb)
}
this.findNavController().navigate(action as NavDirections)
您正在適配器 onItemClicked 回調中傳遞一個WordsWithMeaning項目。 您可以檢查傳遞給回調的項目是WordsWithMeaning類型還是Proverb類型,然后采取相應措施:
adapter = FavoriteListAdapter(viewModel) {
val action = if (it is Proverb) {
// navigate to proverb details
} else {
// navigate to word details
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.