I'm making an app with two fragments, which are home-fragment and youtube-fragment. When I press the "search" button, I can get to youtube-fragment properly. However, when I press the back button(the back on my phone instead of the back arrow in the toolbar), I just exit the app without getting any error or warning. I would like to get back to the home-fragment after press the back button.
Here is my code of both fragments:
homeFragment
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)
}
}
youtubeFragment
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()
}
}
I guess it may have something to do with my adapter for the recyclerview in youtube-fragment because I provide the lifecycle as a parameter for it.
Here it is:
VideoAdapter
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)
}
}
})
}
}
}
Does anyone know how I can get to the home fragment instead of leaving the app?