Skip to content

Instantly share code, notes, and snippets.

View miguelhincapie's full-sized avatar

MiguelHincapieC miguelhincapie

View GitHub Profile
@miguelhincapie
miguelhincapie / CarouselKeyEventDelegate.kt
Created April 8, 2020 00:07
Key event delegate to navigate through the carousel using TalkBack
class CarouselKeyEventDelegate : BaseKeyEventDelegate() {
init {
keyEventActionMap.let {
it.put(
createKey(
R.id.carousel_container,
KEYCODE_DPAD_DOWN
),
this::consumeDownKeyOnCarouselContainer
@miguelhincapie
miguelhincapie / GridKeyEventDelegateGist.kt
Created April 6, 2020 22:44
Snippet to navigate through recyclerView using accessibility
private fun onDownKeyPressed(currentFocus: View): Boolean = with(currentFocus) {
getNextElementPosition().let { nextElementPosition ->
if (isPositionInbound(nextElementPosition)) {
sendFocusToListItem(nextElementPosition)
} else {
rootView.findViewById<View>(R.id.carouselRV)?.sendAccessibilityFocus()
}
}
return true
}
@miguelhincapie
miguelhincapie / AccessibilityFocus.kt
Created April 6, 2020 20:41
Extension functions to enable/disable accessibility focus.
/**
* Extension function to set touch values for accessibility
*/
fun List<View>.enableAccessibilityFocus() {
this.forEach {
it.setAccessibilityFocus()
}
}
/**
@miguelhincapie
miguelhincapie / GeneralKeyEventDelegate.kt
Created April 6, 2020 02:05
Delegate implementation for general accessibility navigation using TalkBack.
class GeneralKeyEventDelegate : BaseKeyEventDelegate() {
init {
keyEventActionMap.let {
it.put(
createKey(
R.id.accessibility_state,
KEYCODE_DPAD_DOWN,
ACTION_DOWN
),
@miguelhincapie
miguelhincapie / KeyEventHandler.kt
Created April 6, 2020 01:10
Class designated to process TalkBack accessibility key events using delegate pattern.
const val KEYCODE_CHANGE_ACCESSIBILITY_STATE = KeyEvent.KEYCODE_S
class KeyEventHandler @Inject constructor() {
/**
* Contains all possible accessibility actions available for the current Activity.
*/
private var keyEventActionMap = SparseArrayCompat<KeyEventAction>()
fun addKeyEventDelegate(keyEventDelegateImpl: BaseKeyEventDelegate) {
@miguelhincapie
miguelhincapie / DelegatingKeyEventFromActivityToViewModel.kt
Created April 6, 2020 00:26
Snippet showing how to send an accessibility event to viewModel.
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
return event?.let {
currentFocus?.let { focusView ->
talkBackViewModel.dispatchKeyEvent(it, WeakReference(focusView))
}
} ?: super.dispatchKeyEvent(event)
}
@miguelhincapie
miguelhincapie / ButtonExtFun.kt
Created April 5, 2020 00:50
Extension functions to deal with enable/disable buttons with accessibility service ON.
/**
* Extension function to disable a Button.
* Workaround due we can't just set enable to false because it will lose focusable ability.
* Check canTakeFocus() function inside View.java file.
*/
fun Button.disable(@DrawableRes drawableForAccessibility: Int) {
if (TalkBackState.value == true) {
isEnabled = true
isClickable = false
contentDescription = String.format(context.getString(R.string.button_disabled_accessibility), text)
@miguelhincapie
miguelhincapie / PostDelayedUtil.kt
Created April 4, 2020 03:49
Util extension function to send an event after X time.
const val DELAY_AFTER_TALK_BACK_GETS_STARTED = 400L
fun View.weakPostDelayed(delay: Long = DELAY_AFTER_TALK_BACK_GETS_STARTED, code: (View) -> Unit) {
postDelayed(WeakRunnable(this) {
code(it)
}, delay)
}
class WeakRunnable<T>(instance: T?, private val action: (T) -> Unit) : Runnable {
private val weakReference: WeakReference<T?> = WeakReference(instance)
@miguelhincapie
miguelhincapie / SendFocusAfterTalkBackStart.kt
Created April 4, 2020 03:45
Snippet showing how to send accessibility focus to an specific UI element after TalkBack started.
/**
* With this function we are observing a specific accessibility service started/stopped: TalkBack
*/
private fun onTalkBackStateChanged(isOn: Boolean) {
if (isOn) {
accessibility_state.text = getString(R.string.accessibility_state_on)
accessibility_state.weakPostDelayed { sendFocusToTitle() }
} else {
accessibility_state.text = getString(R.string.accessibility_state_off)
}
@miguelhincapie
miguelhincapie / AccessibilityServiceListener.kt
Created April 4, 2020 03:33
Generic way to listen for any change in accessibility services state
/**
* Observe for any accessibility service state change. Use [AccessibilityManager] to list
* current accessibility service ON or send [AccessibilityEvent] like a speech out.
*/
private fun listenForAccessibilityServiceStatus(context: Context) {
val accessibilityManager =
context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
accessibilityManager.addAccessibilityStateChangeListener { enabled ->
// Do your stuff
}