Skip to content

Commit

Permalink
ANDROID-14884. Improve accessibility for XML list items (Classic) (#376)
Browse files Browse the repository at this point in the history
* ANDROID-14884. Add new ListRowItem subcomponent for Switch

* ANDROID: 14884 Add. Initial contentDescription proposal for RowList

* ANDROID-14884 Update. finish main logic for customContentDescription

* ANDROID-14884 Update. Refactor code

* ANDROID-14884 Update. Improve headline contentDescription logic

* ANDROID-14884 Update. Expose new components into Catalog place

* ANDROID-14884 Add. Warning when using Toggleable in ListRowView component

* ANDROID-14884 Add. Testing for ListRowItem toggleables

* Updated screenshots baseline

* ANDROID-14884 Update. Improve a11y compatibility with headings

* ANDROID-14884 Update. New sub-component documentation

* ANDROID-14884 Update. Improve documentation readability

* ANDROID-14884 Add. Translations to toggle action click accessibility info

* ANDROID-14884 Update. Improve code readability

* ANDROID-14884 Update. Apply review suggestions

* ANDROID-14884 Fix. Some references to getActionLayout method with crashes

* ANDROID-14884 Update. Setup disable override logic for a11y

* ANDROID-14884 Update. Disable automatic announcement for Novum testing

* ANDROID-14884 Remove. Title heading a11y logic since it triggers a bad impl behavior

---------

Co-authored-by: haynlo <[email protected]>
  • Loading branch information
haynlo and haynlo authored Aug 27, 2024
1 parent a88ace8 commit 4eacf9c
Show file tree
Hide file tree
Showing 19 changed files with 704 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import android.widget.Toast
import androidx.appcompat.content.res.AppCompatResources
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.telefonica.mistica.catalog.R
import com.telefonica.mistica.catalog.ui.classic.components.ListsCatalogFragment.ToggleableListAdapter.ViewType.CHECKBOX
import com.telefonica.mistica.catalog.ui.classic.components.ListsCatalogFragment.ToggleableListAdapter.ViewType.SWITCH
import com.telefonica.mistica.list.ListRowView
import com.telefonica.mistica.list.ListRowView.AssetType
import com.telefonica.mistica.list.ListRowView.Companion.TYPE_IMAGE
Expand All @@ -20,6 +23,8 @@ import com.telefonica.mistica.list.ListRowView.Companion.TYPE_IMAGE_7_10
import com.telefonica.mistica.list.ListRowView.Companion.TYPE_IMAGE_ROUNDED
import com.telefonica.mistica.list.ListRowView.Companion.TYPE_LARGE_ICON
import com.telefonica.mistica.list.ListRowView.Companion.TYPE_SMALL_ICON
import com.telefonica.mistica.list.ListRowViewWithCheckBox
import com.telefonica.mistica.list.ListRowViewWithSwitch
import com.telefonica.mistica.list.MisticaRecyclerView
import com.telefonica.mistica.list.model.ImageDimensions
import com.telefonica.mistica.tag.TagStyle
Expand Down Expand Up @@ -53,6 +58,9 @@ class ListsCatalogFragment : Fragment() {

val clickableRow: MisticaRecyclerView = view.findViewById(R.id.clickable_list)
clickableRow.adapter = ClickableListAdapter()

val toggleableRow: MisticaRecyclerView = view.findViewById(R.id.toggleable_list)
toggleableRow.adapter = ToggleableListAdapter()
}

class ListAdapter(
Expand Down Expand Up @@ -368,7 +376,7 @@ class ListsCatalogFragment : Fragment() {
withHeadline = true,
withInverseBackground = withInverseBackground,
withUrlIcon = "fail_image_url",
withErrorIcon = AppCompatResources.getDrawable(it.context, R.drawable.ic_error)
withErrorIcon = AppCompatResources.getDrawable(it.context, R.drawable.ic_error)
)
},
{
Expand All @@ -380,7 +388,7 @@ class ListsCatalogFragment : Fragment() {
withHeadline = true,
withInverseBackground = withInverseBackground,
withUrlIcon = "fail_image_url",
withErrorIcon = AppCompatResources.getDrawable(it.context, R.drawable.ic_error)
withErrorIcon = AppCompatResources.getDrawable(it.context, R.drawable.ic_error)
)
},
{
Expand All @@ -392,7 +400,7 @@ class ListsCatalogFragment : Fragment() {
withHeadline = true,
withInverseBackground = withInverseBackground,
withUrlIcon = "fail_image_url",
withErrorIcon = AppCompatResources.getDrawable(it.context, R.drawable.ic_error)
withErrorIcon = AppCompatResources.getDrawable(it.context, R.drawable.ic_error)
)
},
{
Expand All @@ -404,7 +412,7 @@ class ListsCatalogFragment : Fragment() {
withHeadline = true,
withInverseBackground = withInverseBackground,
withUrlIcon = "fail_image_url",
withErrorIcon = AppCompatResources.getDrawable(it.context, R.drawable.ic_error)
withErrorIcon = AppCompatResources.getDrawable(it.context, R.drawable.ic_error)
)
},
{
Expand All @@ -416,7 +424,7 @@ class ListsCatalogFragment : Fragment() {
withHeadline = true,
withInverseBackground = withInverseBackground,
withUrlIcon = "fail_image_url",
withErrorIcon = AppCompatResources.getDrawable(it.context, R.drawable.ic_error)
withErrorIcon = AppCompatResources.getDrawable(it.context, R.drawable.ic_error)
)
},
{
Expand All @@ -428,7 +436,7 @@ class ListsCatalogFragment : Fragment() {
withHeadline = true,
withInverseBackground = withInverseBackground,
withUrlIcon = "fail_image_url",
withErrorIcon = AppCompatResources.getDrawable(it.context, R.drawable.ic_error)
withErrorIcon = AppCompatResources.getDrawable(it.context, R.drawable.ic_error)
)
},
{
Expand Down Expand Up @@ -482,18 +490,22 @@ class ListsCatalogFragment : Fragment() {
withErrorIcon: Drawable? = null,
) {
if (withHeadline) {
setHeadlineLayout(R.layout.list_row_tag_headline)
val headlineText = "Headline"
setHeadlineLayout(layoutRes = R.layout.list_row_tag_headline, contentDescription = headlineText)
(getHeadline()!! as TagView).apply {
setTagStyle(if (withInverseBackground) TYPE_INVERSE else withHeadlineStyle)
text = "Headline"
text = headlineText
}
} else {
setHeadlineLayout(ListRowView.HEADLINE_NONE)
}

withTitleMaxLines?.let { setTitleMaxLines(it) }
setTitle(if (withLongTitle) "Title long enough to need more than 2 lines to show it, just for testing purposes." +
"More sample text just for testing purposes." else "Title")
setTitle(
if (withLongTitle) "Title long enough to need more than 2 lines to show it, just for testing purposes. " +
"More sample text just for testing purposes."
else "Title"
)
if (withTitleHeading == true) {
setTitleHeading()
}
Expand Down Expand Up @@ -560,7 +572,7 @@ class ListsCatalogFragment : Fragment() {
}
}

class ListViewHolder(val rowView: ListRowView) : RecyclerView.ViewHolder(rowView)
class ListViewHolder(val rowView: ListRowView) : ViewHolder(rowView)

class ClickableListAdapter : RecyclerView.Adapter<ListViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder {
Expand Down Expand Up @@ -595,8 +607,45 @@ class ListsCatalogFragment : Fragment() {
}
}

class ListSwitchViewHolder(val rowView: ListRowViewWithSwitch) : ViewHolder(rowView)
class ListCheckBoxViewHolder(val rowView: ListRowViewWithCheckBox) : ViewHolder(rowView)

class ToggleableListAdapter : RecyclerView.Adapter<ViewHolder>() {

override fun getItemViewType(position: Int): Int = position
override fun getItemCount(): Int = 2

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return when (viewType) {
0 -> ListSwitchViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.screen_fragment_lists_catalog_item_with_switch, parent, false)
as ListRowViewWithSwitch
)

else -> ListCheckBoxViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.screen_fragment_lists_catalog_item_with_checkbox, parent, false)
as ListRowViewWithCheckBox
)
}
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
when (holder.itemViewType) {
SWITCH.viewType -> with((holder as ListSwitchViewHolder).rowView) {
setOnClickListener { changeSwitchState() }
}
CHECKBOX.viewType -> with((holder as ListCheckBoxViewHolder).rowView) {
setOnClickListener { changeCheckBoxState() }
}
}
}

private enum class ViewType(val viewType: Int) {
SWITCH(0), CHECKBOX(1)
}
}

private companion object {
const val IMAGE_URL = "https://www.fotoaparat.cz/imgs/a/26/2639/0n1wjdf0-cr-em13-09-1200x627x9.jpg"
}

}
21 changes: 20 additions & 1 deletion catalog/src/main/res/layout/screen_fragment_lists_catalog.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,24 @@
app:listLayoutType="full_width"
/>

<com.telefonica.mistica.title.TitleView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
app:title="Toggleables"
/>

<com.telefonica.mistica.list.MisticaRecyclerView
android:nestedScrollingEnabled="false"
android:id="@+id/toggleable_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_weight="0.5"
app:listLayoutType="full_width"
/>

</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.core.widget.NestedScrollView>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<com.telefonica.mistica.list.ListRowViewWithCheckBox xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:viewBindingIgnore="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:listRowAssetDrawable="@drawable/highlighted_card_custom_background"
app:listRowBadgeCount="gone"
app:listRowBadgeVisible="false"
app:listRowDescription="Any subtitle"
app:listRowAssetType="smallIcon"
app:listRowTitle="Title" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<com.telefonica.mistica.list.ListRowViewWithSwitch xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:viewBindingIgnore="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:listRowAssetDrawable="@drawable/highlighted_card_custom_background"
app:listRowBadgeCount="gone"
app:listRowBadgeVisible="false"
app:listRowIsTitleHeading="true"
app:listRowDescription="Any subtitle"
app:listRowAssetType="smallIcon"
app:listRowTitle="Title" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:orientation="vertical">

<com.telefonica.mistica.list.ListRowViewWithSwitch
android:id="@+id/list_row_view_with_switch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:listRowBadgeCount="gone"
app:listRowBadgeVisible="false"
app:listRowDescription="Test Subtitle"
app:listRowTitle="ListRowView with Switch" />

<com.telefonica.mistica.list.ListRowViewWithCheckBox
android:id="@+id/list_row_view_with_checkbox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:listRowBadgeCount="gone"
app:listRowBadgeVisible="false"
app:listRowDescription="Test Subtitle"
app:listRowTitle="ListRowView with CheckBox"/>
</LinearLayout>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 4 additions & 3 deletions library/src/main/java/com/telefonica/mistica/badge/Badge.kt
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,11 @@ object Badge {
}
}

private fun getDefaultBadgeDescription(
@JvmStatic
fun getDefaultBadgeDescription(
anchor: View,
count: Int,
) = if (count == 0) {
count: Int = NON_NUMERIC_BADGE,
) = if (count == NON_NUMERIC_BADGE) {
anchor.context.getString(R.string.badge_notification_description)
} else {
count.toString()
Expand Down
Loading

0 comments on commit 4eacf9c

Please sign in to comment.