-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Expand file tree
/
Copy pathFocusAwareSeekBar.kt
More file actions
101 lines (85 loc) · 3.26 KB
/
FocusAwareSeekBar.kt
File metadata and controls
101 lines (85 loc) · 3.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*
* SPDX-FileCopyrightText: 2026 NewPipe contributors <https://newpipe.net>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package org.schabi.newpipe.views
import android.content.Context
import android.graphics.Rect
import android.util.AttributeSet
import android.view.KeyEvent
import android.view.ViewTreeObserver
import android.widget.SeekBar
import androidx.appcompat.widget.AppCompatSeekBar
import org.schabi.newpipe.util.DeviceUtils
/**
* SeekBar, adapted for directional navigation. It emulates touch-related callbacks
* (onStartTrackingTouch/onStopTrackingTouch), so existing code does not need to be changed to
* work with it.
*/
open class FocusAwareSeekBar : AppCompatSeekBar {
private var listener: NestedListener? = null
private var treeObserver: ViewTreeObserver? = null
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
super(context, attrs, defStyleAttr)
override fun setOnSeekBarChangeListener(l: OnSeekBarChangeListener?) {
listener = if (l == null) null else NestedListener(l)
super.setOnSeekBarChangeListener(listener)
}
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
if (!isInTouchMode && DeviceUtils.isConfirmKey(keyCode)) {
releaseTrack()
}
return super.onKeyDown(keyCode, event)
}
override fun onFocusChanged(gainFocus: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect)
if (!isInTouchMode && !gainFocus) {
releaseTrack()
}
}
private val touchModeListener = ViewTreeObserver.OnTouchModeChangeListener { inTouchMode ->
if (inTouchMode) {
releaseTrack()
}
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
treeObserver = viewTreeObserver
treeObserver?.addOnTouchModeChangeListener(touchModeListener)
}
override fun onDetachedFromWindow() {
if (treeObserver?.isAlive != true) {
treeObserver = viewTreeObserver
}
treeObserver?.removeOnTouchModeChangeListener(touchModeListener)
treeObserver = null
super.onDetachedFromWindow()
}
private fun releaseTrack() {
val l = listener
if (l != null && l.isSeeking) {
l.onStopTrackingTouch(this)
}
}
private class NestedListener(private val delegate: OnSeekBarChangeListener) :
OnSeekBarChangeListener {
var isSeeking = false
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
if (!seekBar.isInTouchMode && !isSeeking && fromUser) {
isSeeking = true
onStartTrackingTouch(seekBar)
}
delegate.onProgressChanged(seekBar, progress, fromUser)
}
override fun onStartTrackingTouch(seekBar: SeekBar) {
isSeeking = true
delegate.onStartTrackingTouch(seekBar)
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
isSeeking = false
delegate.onStopTrackingTouch(seekBar)
}
}
}