如何从Android Studio 3.5.2中的RecyclerView.ViewHolder(itemView)获取活动?

时间:2019-11-07 14:04:27

标签: android android-studio kotlin

函数Navigation.findNavController()在代码A中需要一个Activity参数,但是我只能通过context获得一个itemView.context

如何在Android Studio中从Activity获得RecyclerView.ViewHolder(itemView)

目前,我必须将private val mActivity: Activity从代码B传递到代码A,它可以工作,但是我认为这不是一个好方法。

添加的内容:

致Miriana Itani:谢谢!

您的代码运行良好。我粘贴了FrameLayout xml文件,可以看到代码C

我很奇怪,代码Navigation.findNavController(temView)...是如何找到NavController控件的? 你能告诉我吗?

您知道使用代码Navigation.findNavController(mActivity, R.id.fragment_container)很容易理解,因为NavController的ID是fragment_container,而且是唯一的。

代码A

class VideoListAdapter (private val videoList: List<File>, private val mActivity: Activity) : RecyclerView.Adapter<VideoListAdapter.MyViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VideoListAdapter.MyViewHolder {
        val v = LayoutInflater.from(parent.context).inflate(R.layout.layout_fragment_video_list_recycleview, parent, false)
        return MyViewHolder(v)
    }

    override fun onBindViewHolder(holder: VideoListAdapter.MyViewHolder, position: Int) {
        holder.bindItems(videoList[position])
    }

    override fun getItemCount(): Int {
        return videoList.size
    }

    inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        fun bindItems(aFile: File) {           
            itemView.tvVideoFileName.text=aFile.name
            itemView.btnPlay.setOnClickListener {
                Navigation.findNavController(mActivity, R.id.fragment_container).navigate(
                    UIFragmentVideoListDirections.aVideoList2Video((aFile.absolutePath)) )

            }
        }
    }

}

代码B

class UIFragmentVideoList : Fragment() {

    private lateinit var listFile: MutableList<File>

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? = inflater.inflate(R.layout.layout_fragment_video_list, container, false)


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

        val outputDirectoryOfVideo = getVideoOutputDirectory(requireContext())
        listFile =outputDirectoryOfVideo.listFiles{file -> VIDEO_EXTENSION_WHITELIST.contains(file.extension.toUpperCase())}
                   .sorted().reversed().toMutableList()

        videoRecyclerView.layoutManager =  LinearLayoutManager(requireContext(), RecyclerView.VERTICAL, false)
        val aVideoListAdapter=VideoListAdapter(listFile,requireActivity())
        videoRecyclerView.adapter=aVideoListAdapter

    }

}

代码C

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
    >

    <fragment
            android:id="@+id/fragment_container"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_graph" />

</FrameLayout>

3 个答案:

答案 0 :(得分:2)

事实上,我认为您无需通过该活动即可使NavController工作:

我认为更好的方法是:

Navigation.findNavController(temView).navigate(
            UIFragmentVideoListDirections.aVideoList2Video((aFile.absolutePath))
        )

请尝试让我知道。

添加的答案:

NavHostFragment -用于创建片段目标的NavHost的实现。它具有自己的NavController和导航图。通常,每个活动将有一个NavHostFragment。

导航-帮助程序类,用于获取NavController实例,并将导航连接到UI事件,例如单击按钮。

NavigationUI —用于将应用导航模式(如抽屉,底部导航或操作栏)与NavController连接的类。

答案 1 :(得分:0)

您可以像这样从视图的上下文中检索活动:

tailrec fun Context.findActivity(): Activity {
    if (this is Activity) {
        @Suppress("UNCHECKED_CAST")
        return this
    } else {
        if (this is ContextWrapper) {
            return this.baseContext.findActivity()
        }
        throw IllegalStateException("The context chain does not contain Activity!")
    }
}

现在您可以做

val activity = view.context.findActivity()

答案 2 :(得分:0)

您可以将函数传递给片段中的适配器。这样您就不必通过活动

class VideoListAdapter (private val videoList: List<File>, val btnPlayClick: (File) -> Unit) : RecyclerView.Adapter<VideoListAdapter.MyViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VideoListAdapter.MyViewHolder {
        val v = LayoutInflater.from(parent.context).inflate(R.layout.layout_fragment_video_list_recycleview, parent, false)
        return MyViewHolder(v)
    }

    override fun onBindViewHolder(holder: VideoListAdapter.MyViewHolder, position: Int) {
        holder.bindItems(videoList[position], btnPlayClicked )
    }

    override fun getItemCount(): Int {
        return videoList.size
    }

    inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        fun bindItems(aFile: File, click -> (File) -> Unit) {           
            itemView.tvVideoFileName.text=aFile.name
            itemView.btnPlay.setOnClickListener {
                 click(aFile)
            }
        }
    }
}

并在片段中构建这样的适配器

val aVideoListAdapter = VideoListAdapter(listFile) { myFile ->
    Navigation.findNavController(activity!!, R.id.fragment_container).navigate(
                    UIFragmentVideoListDirections.aVideoList2Video((myFile.absolutePath)) 
    )
}