Как получить активность из RecyclerView.ViewHolder (itemView) в Android Studio 3.5.2? - PullRequest
1 голос
/ 07 ноября 2019

Для функции Navigation.findNavController() нужен код Activity в коде A, но я могу получить context только через itemView.context.

Как мне получить Activity из RecyclerView.ViewHolder(itemView) вAndroid Studio?

В настоящее время я должен передать private val mActivity: Activity из кода B в код A, это работает, но я думаю, что это не очень хороший способ.

Добавленный контент:

Мириане Итани: Спасибо!

Ваш код работает хорошо. Я вставляю XML-файл FrameLayout, вы можете увидеть код C

Мне очень странно, как код Navigation.findNavController(temView)... находит элемент управления NavController? Не могли бы вы сказать мне ?

Вы знаете, что легко понять код Navigation.findNavController(mActivity, R.id.fragment_container), потому что идентификатор NavController равен 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 ]

2 голосов
/ 07 ноября 2019

На самом деле, я не думаю, что вам нужно передавать действие для работы NavController:

Я думаю, что лучший подход был бы следующим:

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

Пожалуйста, попробуйте и дайте мне знать.

Добавлен ответ:

NavHostFragment - реализация NavHost для создания мест назначения фрагмента. Он имеет свой собственный NavController и график навигации. Как правило, у вас будет один NavHostFragment для каждого действия.

Navigation - вспомогательный класс для получения экземпляра NavController и для подключения навигации к событиям пользовательского интерфейса, например нажатию кнопки.

NavigationUI - класс для соединения шаблонов навигации приложения, таких как ящик, нижняя панель навигации или панель действий, с NavController.

0 голосов
/ 07 ноября 2019

Вы можете передать функцию адаптеру во фрагменте. Таким образом, вам не нужно передавать действие

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)) 
    )
}
0 голосов
/ 07 ноября 2019

Вы можете извлечь действие из контекста представления следующим образом:

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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...