【问题标题】:Navigation Component in RecyclerView AdapterRecyclerView 适配器中的导航组件
【发布时间】:2019-11-28 18:13:30
【问题描述】:

我在适配器中编写了以下代码。

holder.itemView.setOnClickListener {
    val action = SearchFragmentDirections.actionSearchFragmentToArtistFragment(artist.id)
    Navigation.createNavigateOnClickListener(action)
}

这是可能的导航xml:

 ...
    <fragment android:id="@+id/searchFragment"
          android:name="com.salmanseifian.spotiny.ui.search.SearchFragment"
          android:label="SearchFragment">

    <action android:id="@+id/action_searchFragment_to_artistFragment"
            app:destination="@id/artistFragment"
            app:popUpTo="@+id/searchFragment"/>
</fragment>

但它不会工作。有人可以帮忙吗?

【问题讨论】:

  • 你确定holder.itemView.setOnClickListenerSearchFragment里面吗?
  • @JohnJoe 是的,我确定。

标签: android kotlin android-recyclerview android-architecture-navigation


【解决方案1】:

您正在使用 lambda,它本身就是一个点击监听器。 检查这个Navigation Docs,它使用导航ID和createNavigationListener正确实现了点击监听器。

为您的案例使用以下代码。

holder.itemView.setOnClickListener(
Navigation.createNavigateOnClickListener(R.id.action_searchFragment_to_artistFragment)
)

或者,试试这个方法

holder.itemView.setOnClickListener{ view ->
 view.findNavController().navigate(R.id.action_searchFragment_to_artistFragment)
}

【讨论】:

  • 不幸的是,它没有帮助。问题依然存在。
  • holder.itemView.setOnClickListener( Navigation.createNavigateOnClickListener(R.id.productDetailsFragment) );是的,这对我有用,谢谢
【解决方案2】:

我认为最好将此添加到已接受的答案中:

holder.itemView.setOnClickListener(
 Navigation
 .createNavigateOnClickListener(R.id.action_searchFragment_to_artistFragment).onClick(holder.itemView)
)

【讨论】:

  • 我得到:does not have a NavController set
【解决方案3】:

在您的 RecyclerView Adapter OnBindViewHolder 方法中,您可以这样:

        holder.bookBtn.setOnClickListener(view -> {
            Bundle bundle = new Bundle();
            String salonJsonString = 
            HelperMethods.getGsonParser().toJson(salonModel);bundle.putString("SALON_DETAILS", salonJsonString);
            Navigation.findNavController(view).navigate(R.id.salonDetailFragment,bundle);     
        });

在上面,目标是SalonDetailFragment,其id 是salonDetailFragment,并将数据作为Bundle 传递到目标。

我的导航配置

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mobile_navigation"
    android:label="Salon"
    app:startDestination="@+id/nav_home">
    <fragment
        android:id="@+id/nearbySalonsFragment"
        android:name="my.package.NearbySalonsFragment"
        android:label="Nearby Salons"
        tools:layout="@layout/fragment_nearby_salons" >
        <action
            android:id="@+id/action_nearbySalonsFragment_to_salonDetailFragment"
            app:destination="@id/salonDetailFragment" />
    </fragment>
    <fragment
        android:id="@+id/salonDetailFragment"
        android:name="my.package.SalonDetailFragment"
        android:label="Salon Details"
        tools:layout="@layout/fragment_salon_detail" />
</navigation>

【讨论】:

【解决方案4】:

如果你使用viewBinding,这是连击

view.btnCategory.setOnClickListener {
    val navController= Navigation.findNavController((view.root.context) as Activity, R.id.nav_host_home)
    navController.navigate(R.id.action_movieFragment2_to_settingsFragment2)
}

【讨论】:

  • 为了更漂亮的答案,您可以将部分代码格式化为编辑答案。那么你的答案会更容易阅读。欢迎来到 stackOverflow :)
【解决方案5】:

基本上,您可以通过两种方式做到这一点。

  1. 您可以实例化 Navigation 类并创建导航点击监听器

      private fun openEditUser() {
         binding.userName.setOnClickListener {
    
          Navigation.createNavigateOnClickListener(R.id.addEditUserFragment)
             }
         }
    
  2. 您可以从按钮或您在项目布局中使用的任何其他元素获取视图,并使用 navigate() 方法调用 findNavController

     private fun openEditUser() {
     binding.userName.setOnClickListener {
         it.findNavController().navigate(R.id.addEditUserFragment)
     }
    

    }

在这两种情况下,您都需要来自将用于导航的操作 ID 的引用,您可以在片段 XML 标记下的导航文件夹中查看 ID

    <fragment
    android:id="@+id/addEditUserFragment"
    android:name="com.sajtek.user.xprsmartadmin.ui.add_edit_user.AddEditUserFragment"
    android:label="add_edit_user_fragment"
    tools:layout="@layout/add_edit_user_fragment" />

【讨论】:

    【解决方案6】:

    尝试通过您的 Fragment 与您的导航进行通信。因此,只需简单地创建从适配器到 Fragment/Activity 的回调,然后从 Fragment/Activity 尝试像普通方式一样使用导航方法。

    【讨论】:

      【解决方案7】:

      kotlin 中的示例

      对不起我的英语

      尝试做一个点击界面,在Adapter里面使用,可以获取item的位置

      示例 ==> 接口

      interface MyInterface {
          fun OnClickListener( string : String , position: Int, view: View)
      }
      

      如何在适配器内部使用

      class ProductAdadapter(
          val context: Context,
          private var myInterface : MyInterface 
          ) : RecyclerView.Adapter<ProductAdadapter.ProductViewModel>() {
      
      
          override fun onCreateViewHolder(
              parent: ViewGroup,
              viewType: Int
          ): ProductViewModel {
              val view = LayoutInflater.from(context).inflate(R.layout.item_product_adapter, parent, false)
              return ProductViewModel(view)
          }
      
          override fun getItemCount() =  product.size
      
          override fun getItemViewType(position: Int): Int {
              return super.getItemViewType(position)
          }
      
      
          override fun onBindViewHolder(holder: ProductViewModel, position: Int) {
              holder.bindView(product[position])
      
              holder.mcvProductsAd.setOnClickListener{
                  myInterface .OnClickListener(product[position],position, it)
              }
          }
      
      
          class ProductViewModel(item: View) : RecyclerView.ViewHolder(item) {
              val mcvProductsAd = item.mcv_products_ad
      
              fun bindView(product: Product) {
                  Glide.with(itemView.context).load(product.image).into(imageProduct)
              }
          }
      }
      

      然后在 Fragment 中制作一个工具

      class ProductFragment : Fragment(), MyInterface {
      
          lateinit var productAdadapter: ProductAdadapter
      
      
          companion object {
              fun newInstance() = ProductFragment()
          }
      
          private lateinit var viewModel: ProductViewModel
      
          override fun onCreateView(
              inflater: LayoutInflater, container: ViewGroup?,
              savedInstanceState: Bundle?
          ): View? {
              return inflater.inflate(R.layout.product_fragment, container, false)
          }
      
          override fun onActivityCreated(savedInstanceState: Bundle?) {
              super.onActivityCreated(savedInstanceState)
              viewModel = ViewModelProviders.of(this).get(ProductViewModel::class.java)
      
              viewModel.loadMessages().observe(viewLifecycleOwner, androidx.lifecycle.Observer {
                  it?.let {
                      grid.layoutManager = GridLayoutManager(context!!, 2)
                      grid.adapter = ProductAdadapter(context!!, it, this)
                  }
              })
      
              mt_product_new.setOnClickListener { activity!!.onBackPressed() }
          }
      
          override fun OnClickListener(string: String, position: Int, view: View) {
              Navigation.findNavController(it)
                 .navigate(R.id.action_my_orders_fragment_to_offers_fragment, null)
               }
      
          }
      
      }
      

      【讨论】:

        【解决方案8】:

        如果你使用数据绑定,你只是

        val 动作 = MessageListFragmentDirections.actionMessageListFragmentToSearchFragment() binding.root.findNavController().navigate(action)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-05-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多