Merge pull request #84 from esensar/fix/home-screen-accessibility

Implement accessibility for HomeScreenGrid
This commit is contained in:
Tibor Kaputa 2023-07-18 14:30:31 +02:00 committed by GitHub
commit c5ea727398
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 104 additions and 20 deletions

View File

@ -23,6 +23,7 @@ import android.os.Handler
import android.provider.Telephony import android.provider.Telephony
import android.telecom.TelecomManager import android.telecom.TelecomManager
import android.view.* import android.view.*
import android.view.accessibility.AccessibilityNodeInfo
import android.view.animation.DecelerateInterpolator import android.view.animation.DecelerateInterpolator
import android.widget.PopupMenu import android.widget.PopupMenu
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
@ -139,6 +140,14 @@ class MainActivity : SimpleActivity(), FlingListener {
} }
} }
} }
home_screen_grid.itemClickListener = {
performItemClick(it)
}
home_screen_grid.itemLongClickListener = {
performItemLongClick(home_screen_grid.getClickableRect(it).left.toFloat(), it)
}
} }
private fun findFirstEmptyCell(): Rect? { private fun findFirstEmptyCell(): Rect? {
@ -241,6 +250,7 @@ class MainActivity : SimpleActivity(), FlingListener {
refetchLaunchers() refetchLaunchers()
} }
} }
REQUEST_ALLOW_BINDING_WIDGET -> mActionOnCanBindWidget?.invoke(resultCode == Activity.RESULT_OK) REQUEST_ALLOW_BINDING_WIDGET -> mActionOnCanBindWidget?.invoke(resultCode == Activity.RESULT_OK)
REQUEST_CONFIGURE_WIDGET -> mActionOnWidgetConfiguredWidget?.invoke(resultCode == Activity.RESULT_OK) REQUEST_CONFIGURE_WIDGET -> mActionOnWidgetConfiguredWidget?.invoke(resultCode == Activity.RESULT_OK)
REQUEST_CREATE_SHORTCUT -> { REQUEST_CREATE_SHORTCUT -> {
@ -403,6 +413,7 @@ class MainActivity : SimpleActivity(), FlingListener {
window.navigationBarColor = resources.getColor(R.color.semitransparent_navigation) window.navigationBarColor = resources.getColor(R.color.semitransparent_navigation)
home_screen_grid.fragmentExpanded() home_screen_grid.fragmentExpanded()
home_screen_grid.hideResizeLines() home_screen_grid.hideResizeLines()
fragment.performAccessibilityAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null)
} }
private fun hideFragment(fragment: View) { private fun hideFragment(fragment: View) {
@ -433,12 +444,7 @@ class MainActivity : SimpleActivity(), FlingListener {
mIgnoreMoveEvents = true mIgnoreMoveEvents = true
val clickedGridItem = home_screen_grid.isClickingGridItem(x.toInt(), y.toInt()) val clickedGridItem = home_screen_grid.isClickingGridItem(x.toInt(), y.toInt())
if (clickedGridItem != null) { if (clickedGridItem != null) {
if (clickedGridItem.type == ITEM_TYPE_ICON || clickedGridItem.type == ITEM_TYPE_SHORTCUT) { performItemLongClick(x, clickedGridItem)
main_holder.performHapticFeedback()
}
val anchorY = home_screen_grid.sideMargins.top + (clickedGridItem.top * home_screen_grid.cellHeight.toFloat())
showHomeIconMenu(x, anchorY, clickedGridItem, false)
return return
} }
@ -450,24 +456,37 @@ class MainActivity : SimpleActivity(), FlingListener {
home_screen_grid.hideResizeLines() home_screen_grid.hideResizeLines()
val clickedGridItem = home_screen_grid.isClickingGridItem(x.toInt(), y.toInt()) val clickedGridItem = home_screen_grid.isClickingGridItem(x.toInt(), y.toInt())
if (clickedGridItem != null) { if (clickedGridItem != null) {
if (clickedGridItem.type == ITEM_TYPE_ICON) { performItemClick(clickedGridItem)
launchApp(clickedGridItem.packageName, clickedGridItem.activityName) }
} else if (clickedGridItem.type == ITEM_TYPE_SHORTCUT) { }
if (clickedGridItem.intent.isNotEmpty()) {
launchShortcutIntent(clickedGridItem) private fun performItemClick(clickedGridItem: HomeScreenGridItem) {
} else { if (clickedGridItem.type == ITEM_TYPE_ICON) {
// launch pinned shortcuts launchApp(clickedGridItem.packageName, clickedGridItem.activityName)
val id = clickedGridItem.shortcutId } else if (clickedGridItem.type == ITEM_TYPE_SHORTCUT) {
val packageName = clickedGridItem.packageName if (clickedGridItem.intent.isNotEmpty()) {
val userHandle = android.os.Process.myUserHandle() launchShortcutIntent(clickedGridItem)
val shortcutBounds = home_screen_grid.getClickableRect(clickedGridItem) } else {
val launcherApps = applicationContext.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps // launch pinned shortcuts
launcherApps.startShortcut(packageName, id, shortcutBounds, null, userHandle) val id = clickedGridItem.shortcutId
} val packageName = clickedGridItem.packageName
val userHandle = android.os.Process.myUserHandle()
val shortcutBounds = home_screen_grid.getClickableRect(clickedGridItem)
val launcherApps = applicationContext.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
launcherApps.startShortcut(packageName, id, shortcutBounds, null, userHandle)
} }
} }
} }
private fun performItemLongClick(x: Float, clickedGridItem: HomeScreenGridItem) {
if (clickedGridItem.type == ITEM_TYPE_ICON || clickedGridItem.type == ITEM_TYPE_SHORTCUT) {
main_holder.performHapticFeedback()
}
val anchorY = home_screen_grid.sideMargins.top + (clickedGridItem.top * home_screen_grid.cellHeight.toFloat())
showHomeIconMenu(x, anchorY, clickedGridItem, false)
}
fun showHomeIconMenu(x: Float, y: Float, gridItem: HomeScreenGridItem, isOnAllAppsFragment: Boolean) { fun showHomeIconMenu(x: Float, y: Float, gridItem: HomeScreenGridItem, isOnAllAppsFragment: Boolean) {
home_screen_grid.hideResizeLines() home_screen_grid.hideResizeLines()
mLongPressedIcon = gridItem mLongPressedIcon = gridItem

View File

@ -15,8 +15,12 @@ import android.text.TextUtils
import android.util.AttributeSet import android.util.AttributeSet
import android.util.Size import android.util.Size
import android.util.SizeF import android.util.SizeF
import android.view.View
import android.widget.RelativeLayout import android.widget.RelativeLayout
import androidx.core.graphics.drawable.toDrawable import androidx.core.graphics.drawable.toDrawable
import androidx.core.view.ViewCompat
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
import androidx.customview.widget.ExploreByTouchHelper
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.helpers.isSPlus import com.simplemobiletools.commons.helpers.isSPlus
@ -58,7 +62,12 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
val appWidgetHost = MyAppWidgetHost(context, WIDGET_HOST_ID) val appWidgetHost = MyAppWidgetHost(context, WIDGET_HOST_ID)
private val appWidgetManager = AppWidgetManager.getInstance(context) private val appWidgetManager = AppWidgetManager.getInstance(context)
var itemClickListener: ((HomeScreenGridItem) -> Unit)? = null
var itemLongClickListener: ((HomeScreenGridItem) -> Unit)? = null
init { init {
ViewCompat.setAccessibilityDelegate(this, HomeScreenGridTouchHelper(this))
textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG).apply { textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG).apply {
color = Color.WHITE color = Color.WHITE
textSize = context.resources.getDimension(R.dimen.smaller_text_size) textSize = context.resources.getDimension(R.dimen.smaller_text_size)
@ -706,4 +715,60 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
return null return null
} }
private inner class HomeScreenGridTouchHelper(host: View) : ExploreByTouchHelper(host) {
override fun getVirtualViewAt(x: Float, y: Float): Int {
val item = isClickingGridItem(x.toInt(), y.toInt())
return if (item != null) {
item.id?.toInt() ?: INVALID_ID
} else {
INVALID_ID
}
}
override fun getVisibleVirtualViews(virtualViewIds: MutableList<Int>?) {
val sorted = gridItems.sortedBy { it.top * 100 + it.left }
sorted.forEachIndexed { index, homeScreenGridItem ->
virtualViewIds?.add(index, homeScreenGridItem.id?.toInt() ?: index)
}
}
override fun onPopulateNodeForVirtualView(virtualViewId: Int, node: AccessibilityNodeInfoCompat) {
val item = gridItems.firstOrNull { it.id?.toInt() == virtualViewId } ?: throw IllegalArgumentException("Unknown id")
node.text = item.title
val viewLocation = IntArray(2)
getLocationOnScreen(viewLocation)
val viewBounds = getClickableRect(item)
val onScreenBounds = Rect(viewBounds)
onScreenBounds.offset(viewLocation[0], viewLocation[1])
node.setBoundsInScreen(onScreenBounds)
node.setBoundsInParent(viewBounds)
node.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK)
node.addAction(AccessibilityNodeInfoCompat.ACTION_LONG_CLICK)
node.setParent(this@HomeScreenGrid)
}
override fun onPerformActionForVirtualView(virtualViewId: Int, action: Int, arguments: Bundle?): Boolean {
val item = gridItems.firstOrNull { it.id?.toInt() == virtualViewId } ?: throw IllegalArgumentException("Unknown id")
when (action) {
AccessibilityNodeInfoCompat.ACTION_CLICK -> itemClickListener?.apply {
invoke(item)
return true
}
AccessibilityNodeInfoCompat.ACTION_LONG_CLICK -> itemLongClickListener?.apply {
invoke(item)
return true
}
}
return false
}
}
} }