#android #android-studio #kotlin #android-fragments #android-recyclerview
Вопрос:
Я создаю приложение с двумя фрагментами, которые являются домашним фрагментом и фрагментом youtube. Когда я нажимаю кнопку «поиск», я могу правильно перейти на youtube-фрагмент. Однако, когда я нажимаю кнопку «Назад» («Назад» на моем телефоне вместо стрелки «Назад» на панели инструментов), я просто выхожу из приложения, не получая никаких ошибок или предупреждений. Я хотел бы вернуться к главному фрагменту после нажатия кнопки «Назад».
Вот мой код обоих фрагментов:
Фрагмент домашней страницы
package com.example.signlanguage_new
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.GridLayout
import android.widget.Toast
import android.widget.Toast.LENGTH_SHORT
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.GridLayoutManager
import com.example.signlanguage_new.databinding.FragmentHomeBinding
class HomeFragment : Fragment() {
private val viewModel: MyViewModel by activityViewModels {
MyViewModelFactory(
(activity?.application as SignLanguageApplication).database.VideoDao()
)
}
private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
viewModel.result.observe(viewLifecycleOwner)
{
if(it==null) {
Toast.makeText(requireContext(), "查無資料", LENGTH_SHORT).show()
}
else
{
val action=HomeFragmentDirections.actionHomeFragmentToYoutubeFragment()
findNavController().navigate(action)
}
}
super.onViewCreated(view, savedInstanceState)
binding.apply {
searchBtn.setOnClickListener {
val search=binding.search.text.toString()
if(search=="")
{
Toast.makeText(requireContext(), "請輸入關鍵字", LENGTH_SHORT).show()
}
else
{
viewModel.searchVideo(search)
}
}
}
val adapter=homeButtonAdapter{
viewModel.category(it)
}
binding.recyclerView.adapter=adapter
binding.recyclerView.layoutManager=GridLayoutManager(this.context,2)
}
}
Фрагмент YouTube
package com.example.signlanguage_new
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.OnBackPressedCallback
import androidx.activity.addCallback
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.signlanguage_new.data.Video
import com.example.signlanguage_new.databinding.FragmentYoutubeBinding
class youtubeFragment : Fragment() {
private val viewModel: MyViewModel by activityViewModels {
MyViewModelFactory(
(activity?.application as SignLanguageApplication).database.VideoDao()
)
}
private var _binding: FragmentYoutubeBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentYoutubeBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val Dataset= viewModel.result.value
binding.recyclerView.adapter= Dataset?.let {
VideoAdapter(requireContext(),
it,this.lifecycle)
}
binding.recyclerView.layoutManager = LinearLayoutManager(this.context)
}
}
And here is the nav_graph and my mainActivity:
nav_graph
<?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/nav_graph"
app:startDestination="@id/homeFragment">
<fragment
android:id="@ id/homeFragment"
android:name="com.example.signlanguage_new.HomeFragment"
android:label="fragment_home"
tools:layout="@layout/fragment_home" >
<action
android:id="@ id/action_homeFragment_to_youtubeFragment"
app:destination="@id/youtubeFragment"
app:popUpTo="@id/homeFragment"
app:popUpToInclusive="true" />
</fragment>
<fragment
android:id="@ id/youtubeFragment"
android:name="com.example.signlanguage_new.youtubeFragment"
android:label="fragment_youtube"
tools:layout="@layout/fragment_youtube" />
</navigation>
MainActivity
package com.example.signlanguage_new
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.KeyEvent
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.NavigationUI.setupActionBarWithNavController
class MainActivity : AppCompatActivity(R.layout.activity_main) {
private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Retrieve NavController from the NavHostFragment
val navHostFragment = supportFragmentManager
.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
navController = navHostFragment.navController
// Set up the action bar for use with the NavController
setupActionBarWithNavController(this, navController)
}
/**
* Handle navigation when the user chooses Up from the action bar.
*/
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp() || super.onSupportNavigateUp()
}
}
Я предполагаю, что это может быть как-то связано с моим адаптером для recyclerview в youtube-фрагменте, потому что я предоставляю жизненный цикл в качестве параметра для него.
Вот он:
ВидеоАдаптер
package com.example.signlanguage_new
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.example.signlanguage_new.data.Video
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.YouTubePlayer
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.listeners.AbstractYouTubePlayerListener
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.views.YouTubePlayerView
class VideoAdapter (private val context: Context, private val dataset:List<Video>, private val lifecycle: Lifecycle) :RecyclerView.Adapter<VideoAdapter.ItemViewHolder>(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
val youTubePlayerView: YouTubePlayerView = LayoutInflater.from(parent.context).inflate(R.layout.videolistitem,parent,false) as YouTubePlayerView
lifecycle.addObserver(youTubePlayerView)
return ItemViewHolder(youTubePlayerView)
}
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
val current=dataset[position]
holder.setIsRecyclable(false)
holder.loadVideo(current.ytId)
}
override fun getItemCount(): Int {
return dataset.size
}
class ItemViewHolder(playerView: YouTubePlayerView) :
RecyclerView.ViewHolder(playerView) {
val youTubePlayerView: YouTubePlayerView = playerView
var youTubePlayer: YouTubePlayer? = null
var currentVideoId: String? = null
fun loadVideo(videoId: String?) {
currentVideoId = videoId
if (youTubePlayer == null) return
if (videoId != null) {
youTubePlayer!!.cueVideo(videoId, 0F)
}
}
init {
youTubePlayerView.addYouTubePlayerListener(object : AbstractYouTubePlayerListener() {
override fun onReady(initializedYouTubePlayer: YouTubePlayer) {
youTubePlayer = initializedYouTubePlayer
currentVideoId?.let {
youTubePlayer!!.cueVideo(it, 0F)
}
}
})
}
}
}
Кто-нибудь знает, как я могу добраться до домашнего фрагмента вместо того, чтобы выходить из приложения?
Комментарии:
1. Зачем вы используете
app:popUpTo="@id/homeFragment"
, если не хотите удалять (всплывать)homeFragment
из заднего стека?
Ответ №1:
Когда вы добавляете app:popUpTo="@id/homeFragment", app:popUpToInclusive="true"
в свое действие навигации, это означает, что вы хотите удалить homeFragment
из заднего стека. по сути, это означает, что когда вы нажмете «Назад», homeFragment
вас там больше не будет, если вы хотите, чтобы кнопка «Назад» привела вас туда homeFragment
, вам нужно обновить действие как
<action
android:id="@ id/action_homeFragment_to_youtubeFragment"
app:destination="@id/youtubeFragment" />