Merge pull request #84 from esensar/fix/home-screen-accessibility
Implement accessibility for HomeScreenGrid
This commit is contained in:
commit
c5ea727398
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue