Skip to content

Commit 567a4b0

Browse files
authored
ADFA-3494 | Remove top bar auto-hide in landscape mode (#1134)
refactor: remove top bar auto-hide in landscape immersive mode Drop TouchObservingLinearLayout and explicitly handle window insets on attach.
1 parent dc29191 commit 567a4b0

6 files changed

Lines changed: 20 additions & 118 deletions

File tree

app/src/main/java/com/itsaky/androidide/activities/editor/BaseEditorActivity.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,6 @@ abstract class BaseEditorActivity :
630630
immersiveController = LandscapeImmersiveController(
631631
contentBinding = content,
632632
bottomSheetBehavior = editorBottomSheet!!,
633-
coroutineScope = lifecycleScope,
634633
).also {
635634
it.bind()
636635
it.onConfigurationChanged(resources.configuration)
@@ -853,7 +852,6 @@ abstract class BaseEditorActivity :
853852
}
854853

855854
override fun onResume() {
856-
immersiveController?.onResume()
857855
super.onResume()
858856
invalidateOptionsMenu()
859857

app/src/main/java/com/itsaky/androidide/activities/editor/LandscapeImmersiveController.kt

Lines changed: 3 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ package com.itsaky.androidide.activities.editor
22

33
import android.annotation.SuppressLint
44
import android.content.res.Configuration
5-
import android.view.InputDevice
6-
import android.view.MotionEvent
75
import android.view.View
86
import android.view.View.OnLayoutChangeListener
97
import android.view.ViewGroup
@@ -13,19 +11,14 @@ import androidx.core.view.updateLayoutParams
1311
import com.google.android.material.bottomsheet.BottomSheetBehavior
1412
import com.google.android.material.appbar.AppBarLayout
1513
import com.itsaky.androidide.databinding.ContentEditorBinding
16-
import kotlinx.coroutines.CoroutineScope
17-
import kotlinx.coroutines.Job
18-
import kotlinx.coroutines.delay
19-
import kotlinx.coroutines.launch
2014
import kotlin.math.roundToInt
2115

2216
/**
2317
* Controls immersive behavior for the editor in landscape mode.
2418
*
2519
* Top bar:
2620
* - expands/collapses through AppBarLayout behavior
27-
* - supports auto-hide after being shown
28-
* - pauses auto-hide while the user is interacting with the top bar
21+
* - stays visible until the user manually hides it
2922
*
3023
* Bottom bar:
3124
* - remains backed by BottomSheetBehavior
@@ -34,7 +27,6 @@ import kotlin.math.roundToInt
3427
class LandscapeImmersiveController(
3528
contentBinding: ContentEditorBinding,
3629
private val bottomSheetBehavior: BottomSheetBehavior<out View?>,
37-
private val coroutineScope: CoroutineScope,
3830
) {
3931
private val topBar = contentBinding.editorAppBarLayout
4032
private val appBarContent = contentBinding.editorAppbarContent
@@ -44,15 +36,13 @@ class LandscapeImmersiveController(
4436
private val topToggle = contentBinding.btnToggleTopBar
4537
private val bottomToggle = contentBinding.btnToggleBottomBar
4638

47-
private var autoHideJob: Job? = null
4839
private var isBound = false
4940

5041
private var isLandscape = false
5142
private var isTopBarRequestedVisible = true
5243
private var isBottomBarRequestedVisible = true
5344
private var isBottomBarShown = true
5445
private var isPendingBottomBarHideAfterCollapse = false
55-
private var isUserInteractingWithTopBar = false
5646

5747
private var statusBarTopInset = 0
5848
private var currentAppBarOffset = 0
@@ -115,30 +105,6 @@ class LandscapeImmersiveController(
115105
setupClickListeners()
116106
}
117107

118-
private val topBarTouchObserver: (MotionEvent) -> Unit = { event ->
119-
when (event.actionMasked) {
120-
MotionEvent.ACTION_DOWN -> onTopBarInteractionStarted()
121-
MotionEvent.ACTION_UP,
122-
MotionEvent.ACTION_CANCEL -> onTopBarInteractionEnded()
123-
}
124-
}
125-
126-
/**
127-
* Observes mouse hover events to manage the top bar's auto-hide behavior.
128-
* It pauses the auto-hide timer while the cursor is over the bar (or its buttons),
129-
* and resumes it when the cursor leaves.
130-
*/
131-
private val topBarHoverObserver: (MotionEvent) -> Unit = { event ->
132-
if (event.isFromSource(InputDevice.SOURCE_MOUSE)) {
133-
when (event.actionMasked) {
134-
MotionEvent.ACTION_HOVER_ENTER,
135-
MotionEvent.ACTION_HOVER_MOVE -> onTopBarInteractionStarted()
136-
137-
MotionEvent.ACTION_HOVER_EXIT -> onTopBarInteractionEnded()
138-
}
139-
}
140-
}
141-
142108
@SuppressLint("ClickableViewAccessibility")
143109
fun bind() {
144110
if (isBound) return
@@ -147,13 +113,9 @@ class LandscapeImmersiveController(
147113
topBar.addOnOffsetChangedListener(topBarOffsetListener)
148114
appBarContent.addOnLayoutChangeListener(appBarLayoutChangeListener)
149115
bottomSheetBehavior.addBottomSheetCallback(bottomSheetCallback)
150-
appBarContent.onTouchEventObserved = topBarTouchObserver
151-
appBarContent.onHoverEventObserved = topBarHoverObserver
152116
}
153117

154118
fun onPause() {
155-
cancelAutoHide()
156-
isUserInteractingWithTopBar = false
157119
cancelBottomSheetAnimation()
158120
setBottomSheetTranslation(
159121
if (!isBottomBarShown && bottomSheetBehavior.state == BottomSheetBehavior.STATE_COLLAPSED) {
@@ -164,12 +126,6 @@ class LandscapeImmersiveController(
164126
)
165127
}
166128

167-
fun onResume() {
168-
if (isLandscape && isTopBarRequestedVisible && !isUserInteractingWithTopBar) {
169-
scheduleTopBarAutoHide()
170-
}
171-
}
172-
173129
@SuppressLint("ClickableViewAccessibility")
174130
fun destroy() {
175131
onPause()
@@ -183,8 +139,6 @@ class LandscapeImmersiveController(
183139
topBar.removeOnOffsetChangedListener(topBarOffsetListener)
184140
appBarContent.removeOnLayoutChangeListener(appBarLayoutChangeListener)
185141
bottomSheetBehavior.removeBottomSheetCallback(bottomSheetCallback)
186-
appBarContent.onTouchEventObserved = null
187-
appBarContent.onHoverEventObserved = null
188142
}
189143

190144
fun onConfigurationChanged(newConfig: Configuration) {
@@ -217,7 +171,7 @@ class LandscapeImmersiveController(
217171
private fun setupClickListeners() {
218172
topToggle.setOnClickListener {
219173
if (!isLandscape) return@setOnClickListener
220-
if (isTopBarRequestedVisible) hideTopBar() else showTopBar(autoHide = true)
174+
if (isTopBarRequestedVisible) hideTopBar() else showTopBar()
221175
}
222176

223177
bottomToggle.setOnClickListener {
@@ -226,18 +180,6 @@ class LandscapeImmersiveController(
226180
}
227181
}
228182

229-
private fun onTopBarInteractionStarted() {
230-
if (!isLandscape || !isTopBarRequestedVisible) return
231-
isUserInteractingWithTopBar = true
232-
cancelAutoHide()
233-
}
234-
235-
private fun onTopBarInteractionEnded() {
236-
if (!isLandscape || !isTopBarRequestedVisible) return
237-
isUserInteractingWithTopBar = false
238-
scheduleTopBarAutoHide()
239-
}
240-
241183
private fun onBottomBarExpandedOrHalfExpanded() {
242184
cancelBottomSheetAnimation()
243185
setBottomSheetTranslation(0f)
@@ -268,8 +210,6 @@ class LandscapeImmersiveController(
268210
}
269211

270212
private fun disableImmersiveMode() {
271-
cancelAutoHide()
272-
isUserInteractingWithTopBar = false
273213
setTogglesVisible(false)
274214

275215
isTopBarRequestedVisible = true
@@ -290,16 +230,12 @@ class LandscapeImmersiveController(
290230
bottomToggle.isVisible = visible
291231
}
292232

293-
private fun showTopBar(autoHide: Boolean, animate: Boolean = true) {
294-
cancelAutoHide()
233+
private fun showTopBar(animate: Boolean = true) {
295234
isTopBarRequestedVisible = true
296235
topBar.setExpanded(true, animate)
297-
if (autoHide) scheduleTopBarAutoHide()
298236
}
299237

300238
private fun hideTopBar(animate: Boolean = true) {
301-
cancelAutoHide()
302-
isUserInteractingWithTopBar = false
303239
isTopBarRequestedVisible = false
304240
topBar.setExpanded(false, animate)
305241
}
@@ -309,22 +245,6 @@ class LandscapeImmersiveController(
309245
currentAppBarOffset = -topBar.totalScrollRange
310246
}
311247

312-
private fun scheduleTopBarAutoHide() {
313-
if (isUserInteractingWithTopBar || !isTopBarRequestedVisible) return
314-
315-
autoHideJob = coroutineScope.launch {
316-
delay(TOP_BAR_AUTO_HIDE_DELAY_MS)
317-
if (!isUserInteractingWithTopBar && isTopBarRequestedVisible) {
318-
hideTopBar()
319-
}
320-
}
321-
}
322-
323-
private fun cancelAutoHide() {
324-
autoHideJob?.cancel()
325-
autoHideJob = null
326-
}
327-
328248
private fun showBottomBar(animate: Boolean = true, expandHalfWay: Boolean = false) {
329249
isBottomBarRequestedVisible = true
330250
isBottomBarShown = true
@@ -419,7 +339,6 @@ class LandscapeImmersiveController(
419339
}
420340

421341
private companion object {
422-
const val TOP_BAR_AUTO_HIDE_DELAY_MS = 3500L
423342
const val BOTTOM_BAR_ANIMATION_DURATION_MS = 200L
424343
}
425344
}

app/src/main/java/com/itsaky/androidide/utils/WindowInsetsExtensions.kt

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ fun View.applyRootSystemInsetsAsPadding(
6868
) {
6969
val initial = getOrStoreInitialPadding()
7070

71-
ViewCompat.setOnApplyWindowInsetsListener(this) { view, windowInsets ->
71+
fun applyInsets(view: View, windowInsets: WindowInsetsCompat) {
7272
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
7373

7474
view.updatePadding(
@@ -77,10 +77,20 @@ fun View.applyRootSystemInsetsAsPadding(
7777
right = initial.right + if (applyRight) insets.right else 0,
7878
bottom = initial.bottom + if (applyBottom) insets.bottom else 0
7979
)
80+
}
81+
82+
ViewCompat.setOnApplyWindowInsetsListener(this) { view, windowInsets ->
83+
applyInsets(view, windowInsets)
8084
windowInsets
8185
}
8286

83-
doOnAttach { it.requestApplyInsets() }
87+
doOnAttach { view ->
88+
ViewCompat.requestApplyInsets(view)
89+
90+
ViewCompat.getRootWindowInsets(view)?.let { rootInsets ->
91+
applyInsets(view, rootInsets)
92+
}
93+
}
8494
}
8595

8696
/**

app/src/main/res/layout-land/content_editor.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
android:fitsSystemWindows="false"
3131
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$Behavior">
3232

33-
<com.itsaky.androidide.ui.TouchObservingLinearLayout
33+
<LinearLayout
3434
android:id="@+id/editor_appbar_content"
3535
android:layout_width="match_parent"
3636
android:layout_height="wrap_content"
@@ -96,7 +96,7 @@
9696
android:layout_height="wrap_content"
9797
android:paddingHorizontal="8dp"
9898
app:tabGravity="start" />
99-
</com.itsaky.androidide.ui.TouchObservingLinearLayout>
99+
</LinearLayout>
100100

101101
</com.google.android.material.appbar.AppBarLayout>
102102

app/src/main/res/layout/content_editor.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
android:fitsSystemWindows="false"
3232
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$Behavior">
3333

34-
<com.itsaky.androidide.ui.TouchObservingLinearLayout
34+
<LinearLayout
3535
android:id="@+id/editor_appbar_content"
3636
android:layout_width="match_parent"
3737
android:layout_height="wrap_content"
@@ -94,7 +94,7 @@
9494
android:paddingHorizontal="8dp"
9595
app:tabGravity="start" />
9696

97-
</com.itsaky.androidide.ui.TouchObservingLinearLayout>
97+
</LinearLayout>
9898
</com.google.android.material.appbar.AppBarLayout>
9999

100100
<ViewFlipper
@@ -192,4 +192,4 @@
192192
android:visibility="gone"
193193
tools:visibility="gone" />
194194

195-
</androidx.coordinatorlayout.widget.CoordinatorLayout>
195+
</androidx.coordinatorlayout.widget.CoordinatorLayout>

common/src/main/java/com/itsaky/androidide/ui/TouchObservingLinearLayout.kt

Lines changed: 0 additions & 25 deletions
This file was deleted.

0 commit comments

Comments
 (0)