From c7bcc6beac18bac385cca896d092423ebf647576 Mon Sep 17 00:00:00 2001 From: Emma Atkins <68222696+emmaatkins@users.noreply.github.com> Date: Wed, 8 Mar 2023 15:23:04 +0000 Subject: [PATCH] TalkBack Accessibility Fixes (#110) * HMA-6086 accessibility fixes * HMA-6086 TalkBack traversal bug fixed * HMA-6086 code tidy --- CHANGELOG.md | 6 ++- .../editable/EditableListItemViewState.kt | 1 + .../organism/editable/EditableListView.kt | 23 +++++----- .../editable/EditableListViewAdapter.kt | 45 ++++++++++++------- .../organisms/EditableListViewFragment.kt | 11 +++-- sample/src/main/res/values/strings.xml | 3 +- 6 files changed, 58 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e73f1bf8..a8bfcfe0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,11 +16,15 @@ Allowed headings: ## [Unreleased] +### Fixed + +* `EditableListView` further TalkBack related bug fixes. + ## [4.5.2] - 2023-02-23 ### Fixed -* `EditableListView` bug with content description and edit button using TalkBack +* `EditableListView` bug with content description and edit button using TalkBack. ## [4.5.1] - 2023-02-20 diff --git a/components/src/main/java/uk/gov/hmrc/components/organism/editable/EditableListItemViewState.kt b/components/src/main/java/uk/gov/hmrc/components/organism/editable/EditableListItemViewState.kt index 16712f8d..f751c79d 100644 --- a/components/src/main/java/uk/gov/hmrc/components/organism/editable/EditableListItemViewState.kt +++ b/components/src/main/java/uk/gov/hmrc/components/organism/editable/EditableListItemViewState.kt @@ -22,5 +22,6 @@ data class EditableListItemViewState( var value: String, @StringRes var buttonText: Int, var valueContentDescription: String? = null, + @StringRes var additionalActionContentDescription: Int? = null, val onClickListener: (Int) -> Unit ) diff --git a/components/src/main/java/uk/gov/hmrc/components/organism/editable/EditableListView.kt b/components/src/main/java/uk/gov/hmrc/components/organism/editable/EditableListView.kt index 15e4a063..db0b3187 100644 --- a/components/src/main/java/uk/gov/hmrc/components/organism/editable/EditableListView.kt +++ b/components/src/main/java/uk/gov/hmrc/components/organism/editable/EditableListView.kt @@ -25,6 +25,7 @@ import android.widget.LinearLayout import androidx.annotation.DrawableRes import androidx.core.view.AccessibilityDelegateCompat import androidx.core.view.ViewCompat +import androidx.recyclerview.widget.LinearLayoutManager import uk.gov.hmrc.components.R import uk.gov.hmrc.components.databinding.ComponentEditableListViewBinding import kotlin.random.Random @@ -40,8 +41,7 @@ open class EditableListView @JvmOverloads constructor( private var buttonText: Pair = Pair("", "") private var buttonAccessibility: Pair = Pair("", "") private var buttonIcon: Pair = Pair(0, 0) - private lateinit var editableListViewAdapter: EditableListViewAdapter - private var editableItems = ArrayList() + private val editableListViewAdapter = EditableListViewAdapter() var editMode = false private set @@ -65,6 +65,10 @@ open class EditableListView @JvmOverloads constructor( setTitle(title) typedArray.recycle() } + binding.listItems.apply { + adapter = editableListViewAdapter + layoutManager = LinearLayoutManager(binding.root.context) + } binding.title.id = Random.nextInt() setIconButtonClickListener(null) setFocusListener() @@ -72,9 +76,7 @@ open class EditableListView @JvmOverloads constructor( fun setIconButtonClickListener(additionalClickListener: (() -> Unit)?) { binding.iconButton.setOnClickListener { - if (::editableListViewAdapter.isInitialized) { - editableListViewAdapter.isEditEnable = !editableListViewAdapter.isEditEnable - } + editableListViewAdapter.isEditEnabled = !editableListViewAdapter.isEditEnabled setEditModeUI(!editMode) additionalClickListener?.invoke() } @@ -112,11 +114,7 @@ open class EditableListView @JvmOverloads constructor( } fun setData(editableItem: ArrayList) { - this.editableItems = editableItem - editableListViewAdapter = EditableListViewAdapter(editableItem) - binding.listItems.apply { - adapter = editableListViewAdapter - } + editableListViewAdapter.values = editableItem } fun setTitle(title: CharSequence?) { @@ -137,6 +135,11 @@ open class EditableListView @JvmOverloads constructor( binding.iconButton.accessibilityTraversalBefore = nextFocusForwardId } } + if (event.eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED) { + if (child.id == binding.iconButton.id) { + binding.iconButton.accessibilityTraversalBefore = nextFocusForwardId + } + } return super.onRequestSendAccessibilityEvent(viewGroup, child, event) } } diff --git a/components/src/main/java/uk/gov/hmrc/components/organism/editable/EditableListViewAdapter.kt b/components/src/main/java/uk/gov/hmrc/components/organism/editable/EditableListViewAdapter.kt index 439207e2..918c9fb3 100644 --- a/components/src/main/java/uk/gov/hmrc/components/organism/editable/EditableListViewAdapter.kt +++ b/components/src/main/java/uk/gov/hmrc/components/organism/editable/EditableListViewAdapter.kt @@ -15,17 +15,25 @@ */ package uk.gov.hmrc.components.organism.editable +import android.annotation.SuppressLint import android.view.LayoutInflater import android.view.ViewGroup import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import uk.gov.hmrc.components.databinding.EditableListItemsBinding -class EditableListViewAdapter( - private val values: List, -) : RecyclerView.Adapter() { +class EditableListViewAdapter : RecyclerView.Adapter() { - var isEditEnable: Boolean = false + var values: List = listOf() + @SuppressLint("NotifyDataSetChanged") + set(list) { + field = list + notifyDataSetChanged() + } + + var firstPass: Boolean = true + + var isEditEnabled: Boolean = false @Suppress("NotifyDataSetChanged") set(value) { field = value @@ -60,28 +68,35 @@ class EditableListViewAdapter( val positionLabel = position + 1 + val additionalAccessibility = additionalActionAccessibility(result) ?: "" + + // temporary accessibility fix as first pass through ELV doesn't add row information + val itemNumText = ", Item $positionLabel of $itemCount" + divider.isVisible = positionLabel < itemCount itemView.contentDescription = - if (isEditEnable) { - "$nameText: ${valueAccessibility(result)}, Tap to $actionButtonText," + - " Item $positionLabel of $itemCount." + if (isEditEnabled) { + "$nameText: ${valueAccessibility(result)}, " + + "$actionButtonText button, " + additionalAccessibility } else { - "$nameText: ${valueAccessibility(result)}, Item $positionLabel of $itemCount." + "$nameText: ${valueAccessibility(result)}" + if (firstPass) itemNumText else "" } - itemView.setOnClickListener { if (isEditEnable) result.onClickListener(adapterPosition) else null } - - actionButton.setOnClickListener { - result.onClickListener(adapterPosition) - } - - if (isEditEnable) { + if (isEditEnabled) { motionLayout.transitionToEnd() + itemView.setOnClickListener { result.onClickListener(adapterPosition) } + actionButton.setOnClickListener { result.onClickListener(adapterPosition) } + firstPass = false } else { + itemView.isClickable = false + actionButton.isClickable = false motionLayout.transitionToStart() } } + private fun additionalActionAccessibility(editableItem: EditableListItemViewState): String? = + editableItem.additionalActionContentDescription?.let { binding.root.context.getString(it) } + private fun valueAccessibility(editableItem: EditableListItemViewState): String = editableItem.valueContentDescription ?: editableItem.value } diff --git a/sample/src/main/java/uk/gov/hmrc/components/sample/organisms/EditableListViewFragment.kt b/sample/src/main/java/uk/gov/hmrc/components/sample/organisms/EditableListViewFragment.kt index 866e57cc..e9f8ad0a 100644 --- a/sample/src/main/java/uk/gov/hmrc/components/sample/organisms/EditableListViewFragment.kt +++ b/sample/src/main/java/uk/gov/hmrc/components/sample/organisms/EditableListViewFragment.kt @@ -62,26 +62,29 @@ class EditableListViewFragment : BaseComponentsFragment() { R.string.editable_list_view_example_1_name_r1, "£1000", R.string.editable_list_view_example_1_link_button, - "1000 pounds" + "1000 pounds", + R.string.editable_list_view_web_browser_accessibility ) { onCtaPressed() }, EditableListItemViewState( R.string.editable_list_view_example_1_name_r2, "£600", R.string.editable_list_view_example_1_link_button, - "600 pounds" + "600 pounds", + R.string.editable_list_view_web_browser_accessibility ) { onCtaPressed() }, EditableListItemViewState( R.string.editable_list_view_example_1_name_r3, "£300000", R.string.editable_list_view_example_1_link_button, - "300000 pounds" + "300000 pounds", + R.string.editable_list_view_web_browser_accessibility ) { onCtaPressed() }, EditableListItemViewState( R.string.editable_list_view_example_1_name_r4, "£55500", R.string.editable_list_view_example_1_link_button, "55500 pounds" - ) { onCtaPressed() } + ) { onCtaPressed() }, ) val editableItem2 = arrayListOf( EditableListItemViewState( diff --git a/sample/src/main/res/values/strings.xml b/sample/src/main/res/values/strings.xml index c6325f9e..04755d21 100644 --- a/sample/src/main/res/values/strings.xml +++ b/sample/src/main/res/values/strings.xml @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. --> - + HMRC App Components Sample @@ -378,5 +378,6 @@ Lorem ipsum dolor Lorem ipsum Lorem ipsum + opens in a web browser \ No newline at end of file