Skip to content
This repository was archived by the owner on Jan 5, 2023. It is now read-only.

Commit 22806d5

Browse files
committed
Handle back presses on Schedule
Bug: 182714988 Change-Id: I8016f0e075f47fb7ff7b376caaa4b7516edfd4a9
1 parent d16342b commit 22806d5

File tree

2 files changed

+77
-2
lines changed

2 files changed

+77
-2
lines changed

mobile/src/main/java/com/google/samples/apps/iosched/ui/schedule/ScheduleTwoPaneFragment.kt

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@ import android.os.Bundle
2020
import android.view.LayoutInflater
2121
import android.view.View
2222
import android.view.ViewGroup
23+
import androidx.activity.OnBackPressedCallback
2324
import androidx.fragment.app.activityViewModels
2425
import androidx.navigation.NavController
26+
import androidx.navigation.NavDestination
2527
import androidx.navigation.fragment.NavHostFragment
28+
import androidx.slidingpanelayout.widget.SlidingPaneLayout
2629
import com.google.samples.apps.iosched.R
2730
import com.google.samples.apps.iosched.ScheduleDetailNavGraphDirections
2831
import com.google.samples.apps.iosched.databinding.FragmentScheduleTwoPaneBinding
@@ -47,6 +50,8 @@ class ScheduleTwoPaneFragment : MainNavigationFragment() {
4750
private lateinit var listPaneNavController: NavController
4851
private lateinit var detailPaneNavController: NavController
4952

53+
private val backPressHandler = BackPressHandler()
54+
5055
override fun onCreateView(
5156
inflater: LayoutInflater,
5257
container: ViewGroup?,
@@ -61,11 +66,20 @@ class ScheduleTwoPaneFragment : MainNavigationFragment() {
6166

6267
setupSnackbarManager(snackbarMessageManager, binding.snackbar)
6368

69+
binding.slidingPaneLayout.apply {
70+
// Disable dragging the detail pane.
71+
lockMode = SlidingPaneLayout.LOCK_MODE_LOCKED
72+
// Listen for movement of the detail pane.
73+
addPanelSlideListener(backPressHandler)
74+
}
75+
6476
childFragmentManager.run {
6577
listPaneNavController =
6678
(findFragmentById(R.id.list_pane) as NavHostFragment).navController
6779
detailPaneNavController =
6880
(findFragmentById(R.id.detail_pane) as NavHostFragment).navController
81+
listPaneNavController.addOnDestinationChangedListener(backPressHandler)
82+
detailPaneNavController.addOnDestinationChangedListener(backPressHandler)
6983
}
7084

7185
scheduleTwoPaneViewModel.navigateToSessionAction.observe(
@@ -74,6 +88,9 @@ class ScheduleTwoPaneFragment : MainNavigationFragment() {
7488
detailPaneNavController.navigate(
7589
ScheduleDetailNavGraphDirections.toSessionDetail(sessionId)
7690
)
91+
// On narrow screens, slide the detail pane over the list pane if it isn't already
92+
// on top. If both panes are visible, this will have no effect.
93+
binding.slidingPaneLayout.open()
7794
}
7895
)
7996

@@ -83,11 +100,69 @@ class ScheduleTwoPaneFragment : MainNavigationFragment() {
83100
openSignInDialog()
84101
}
85102
)
103+
104+
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, backPressHandler)
86105
}
87106

88107
// TODO convert this to a dialog destination in the nav graph
89108
private fun openSignInDialog() {
90109
val dialog = SignInDialogFragment()
91110
dialog.show(requireActivity().supportFragmentManager, SignInDialogFragment.DIALOG_SIGN_IN)
92111
}
112+
113+
/** Handles back button press while this fragment is on screen. */
114+
inner class BackPressHandler :
115+
OnBackPressedCallback(false),
116+
SlidingPaneLayout.PanelSlideListener,
117+
NavController.OnDestinationChangedListener {
118+
119+
override fun handleOnBackPressed() {
120+
// Back press can have three possible effects that we check for in order.
121+
// 1. In the detail pane, go back from Speaker Detail to Session Detail.
122+
val listDestination = listPaneNavController.currentDestination?.id
123+
val detailDestination = detailPaneNavController.currentDestination?.id
124+
var done = false
125+
if (detailDestination == R.id.navigation_speaker_detail) {
126+
done = detailPaneNavController.popBackStack()
127+
}
128+
// 2. On narrow screens, if the detail pane is in front, "go back" by sliding it away.
129+
if (!done) {
130+
done = binding.slidingPaneLayout.closePane()
131+
}
132+
// 3. Try to pop the list pane, e.g. back from Search to Schedule.
133+
if (!done && listDestination == R.id.navigation_schedule_search) {
134+
listPaneNavController.popBackStack()
135+
}
136+
137+
syncEnabledState()
138+
}
139+
140+
override fun onPanelSlide(panel: View, slideOffset: Float) {
141+
// noop
142+
}
143+
144+
override fun onPanelOpened(panel: View) {
145+
syncEnabledState()
146+
}
147+
148+
override fun onPanelClosed(panel: View) {
149+
syncEnabledState()
150+
}
151+
152+
override fun onDestinationChanged(
153+
controller: NavController,
154+
destination: NavDestination,
155+
arguments: Bundle?
156+
) {
157+
syncEnabledState()
158+
}
159+
160+
private fun syncEnabledState() {
161+
val listDestination = listPaneNavController.currentDestination?.id
162+
val detailDestination = detailPaneNavController.currentDestination?.id
163+
isEnabled = listDestination == R.id.navigation_schedule_search ||
164+
detailDestination == R.id.navigation_speaker_detail ||
165+
(binding.slidingPaneLayout.isSlideable && binding.slidingPaneLayout.isOpen)
166+
}
167+
}
93168
}

mobile/src/main/res/navigation/schedule_detail.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
xmlns:app="http://schemas.android.com/apk/res-auto"
2020
xmlns:tools="http://schemas.android.com/tools"
2121
android:id="@+id/schedule_detail_nav_graph"
22-
app:startDestination="@id/placeholderFragment">
22+
app:startDestination="@id/navigation_placeholder">
2323

2424
<!-- This is a global action since we can go to a session's detail regardless of the current
2525
destination. Use popUpTo and popUpToInclusive to avoid creating stacks of session details
@@ -56,7 +56,7 @@
5656

5757
<!-- Use an empty start destination until we can load and show the first session detail. -->
5858
<fragment
59-
android:id="@+id/placeholderFragment"
59+
android:id="@+id/navigation_placeholder"
6060
android:name="androidx.fragment.app.Fragment" />
6161

6262
</navigation>

0 commit comments

Comments
 (0)