Skip to content

Commit

Permalink
ANDROID-14573 is list row item title heading (#348)
Browse files Browse the repository at this point in the history
* ANDROID-14573 add isTitleHeading to ListRowItem in compose

* ANDROID-14573 add isTitleHeading to ListRowView for classic views

* ANDROID-14573 fix typo

* ANDROID-14573 add compose tests about accessibility headings

* ANDROID-14573 add views tests about accessibility headings

* ANDROID-14573 removing importantForAccessibility disabled

* Updated screenshots baseline

* ANDROID-14573 update title heading test layout

* Updated screenshots baseline

* ANDROID-14573 add OptIn in ListRowItem

---------

Co-authored-by: jeprubio <[email protected]>
  • Loading branch information
jeprubio and jeprubio authored Apr 26, 2024
1 parent 99b4a86 commit 314ac81
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class ListsCatalogFragment : Fragment() {
{
it.configureView(
withInverseBackground = withInverseBackground,
withTitleHeading = true,
)
},
{
Expand Down Expand Up @@ -111,6 +112,7 @@ class ListsCatalogFragment : Fragment() {
it.configureView(
withLongDescription = false,
withInverseBackground = withInverseBackground,
withTitleHeading = true,
)
},
{
Expand Down Expand Up @@ -461,6 +463,7 @@ class ListsCatalogFragment : Fragment() {
private fun ListRowView.configureView(
withLongTitle: Boolean = false,
withTitleMaxLines: Int? = null,
withTitleHeading: Boolean? = false,
withLongDescription: Boolean? = null,
withDescriptionMaxLines: Int? = null,
withAsset: Boolean = false,
Expand Down Expand Up @@ -491,6 +494,9 @@ class ListsCatalogFragment : Fragment() {
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")
if (withTitleHeading == true) {
setTitleHeading()
}
withSubtitleMaxLines?.let { setSubtitleMaxLines(it) }
setSubtitle(if (withSubtitle) "Any Subtitle" else null)
withDescriptionMaxLines?.let { setDescriptionMaxLines(it) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Divider
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Switch
import androidx.compose.material.Text
Expand Down Expand Up @@ -49,6 +48,7 @@ const val DESCRIPTION = "Description"
fun samples() = listOf(
ListItem(
title = TITLE,
isTitleHeading = true,
),
ListItem(
title = TITLE,
Expand All @@ -68,6 +68,7 @@ fun samples() = listOf(
ListItem(
title = TITLE,
subtitle = SUBTITLE,
isTitleHeading = true,
),
ListItem(
title = TITLE,
Expand Down Expand Up @@ -299,7 +300,6 @@ fun samples() = listOf(

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

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun Lists() {
val samples = samples()
Expand All @@ -319,6 +319,7 @@ fun Lists() {
listRowIcon = item.listRowIcon,
headline = item.headline,
title = item.title,
isTitleHeading = item.isTitleHeading,
subtitle = item.subtitle,
description = item.description,
trailing = item.action,
Expand Down Expand Up @@ -390,14 +391,15 @@ fun Lists() {
data class ListItem(
val listRowIcon: ListRowIcon? = null,
val title: String? = null,
val isTitleHeading: Boolean = false,
val subtitle: String? = null,
val description: String? = null,
val backgroundType: BackgroundType = BackgroundType.TYPE_NORMAL,
val badge: String? = null,
val isBadgeVisible: Boolean = false,
val headline: Tag? = null,
val action: @Composable (() -> Unit)? = null,
val onClick: () -> Unit = {},
val onClick: (() -> Unit)? = null,
val bottom: @Composable (() -> Unit)? = null,
)

Expand Down Expand Up @@ -449,7 +451,6 @@ private fun CustomSlot() {
}

@Composable
@OptIn(ExperimentalMaterialApi::class)
private fun ClickableAssetSample(context: Context, onRowClick: () -> Unit) {
ListRowItem(
title = "Clickable Asset in Clickable Row",
Expand Down
9 changes: 9 additions & 0 deletions library-test-utils/src/main/res/layout/test_list_row_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,13 @@
app:listRowAssetType="image_1_1"
app:listRowIsBoxed="true"
app:listRowTitle="Image_1_1" />
<com.telefonica.mistica.list.ListRowView
android:id="@+id/list_row_view_title_heading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:listRowBadgeCount="gone"
app:listRowBadgeVisible="false"
app:listRowIsBoxed="true"
app:listRowTitle="Title Heading"
app:listRowIsTitleHeading="true" />
</LinearLayout>
Binary file modified library/screenshots/check_ListRowView_xml.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.semantics.heading
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.telefonica.mistica.R
Expand All @@ -38,12 +40,13 @@ import com.telefonica.mistica.compose.tag.Tag
import com.telefonica.mistica.compose.theme.MisticaTheme
import com.telefonica.mistica.compose.theme.brand.MovistarBrand

@ExperimentalMaterialApi
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun ListRowItem(
modifier: Modifier = Modifier,
listRowIcon: ListRowIcon? = null,
title: String? = null,
isTitleHeading: Boolean = false,
subtitle: String? = null,
description: String? = null,
backgroundType: BackgroundType = BackgroundType.TYPE_NORMAL,
Expand All @@ -59,6 +62,7 @@ fun ListRowItem(
modifier = modifier,
icon = { listRowIcon?.Draw() },
title = title,
isTitleHeading = isTitleHeading,
subtitle = subtitle,
description = description,
backgroundType = backgroundType,
Expand All @@ -72,13 +76,14 @@ fun ListRowItem(
)
}

@ExperimentalMaterialApi
@OptIn(ExperimentalMaterialApi::class)
@Composable
@Deprecated(replaceWith = ReplaceWith("ListRowItem"), message = "Use new ListRowItem with ListRowIcon param instead")
fun ListRowItem(
modifier: Modifier = Modifier,
icon: @Composable (() -> Unit)? = null,
title: String? = null,
isTitleHeading: Boolean = false,
subtitle: String? = null,
description: String? = null,
backgroundType: BackgroundType = BackgroundType.TYPE_NORMAL,
Expand All @@ -100,6 +105,7 @@ fun ListRowItem(
badge = badge,
isBadgeVisible = isBadgeVisible,
headline = headline,
isTitleHeading = isTitleHeading,
trailing = trailing,
onClick = onClick,
bottom = bottom,
Expand All @@ -113,6 +119,7 @@ private fun ListRowItemImp(
modifier: Modifier = Modifier,
icon: @Composable (() -> Unit)? = null,
title: String? = null,
isTitleHeading: Boolean = false,
subtitle: String? = null,
description: String? = null,
backgroundType: BackgroundType = BackgroundType.TYPE_NORMAL,
Expand Down Expand Up @@ -206,7 +213,15 @@ private fun ListRowItemImp(
text = it,
style = MisticaTheme.typography.preset3,
color = textColorPrimary,
modifier = Modifier.testTag(ListRowItemTestTags.LIST_ROW_ITEM_TITLE),
modifier = Modifier
.testTag(ListRowItemTestTags.LIST_ROW_ITEM_TITLE)
.then(
if (isTitleHeading) {
Modifier.semantics { heading() }
} else {
Modifier
}
),
)
}
subtitle?.let {
Expand Down
13 changes: 13 additions & 0 deletions library/src/main/java/com/telefonica/mistica/list/ListRowView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import androidx.annotation.LayoutRes
import androidx.appcompat.content.res.AppCompatResources
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.core.view.ViewCompat
import androidx.core.view.isVisible
import androidx.databinding.BindingAdapter
import androidx.databinding.BindingMethod
Expand Down Expand Up @@ -245,6 +246,14 @@ class ListRowView @JvmOverloads constructor(
)
.takeIf { it != TypedValue.TYPE_NULL }
.let { setActionLayout(it ?: ACTION_NONE) }

styledAttrs.getBoolean(
R.styleable.ListRowView_listRowIsTitleHeading,
false
)
.takeIf { it }
?.let { setTitleHeading() }

styledAttrs.recycle()
}
}
Expand Down Expand Up @@ -380,6 +389,10 @@ class ListRowView @JvmOverloads constructor(
}
}

fun setTitleHeading() {
ViewCompat.setAccessibilityHeading(titleTextView, true)
}

@Deprecated(
message = "setBoxed is deprecated, please use 'setBackgroundType' instead",
replaceWith = ReplaceWith(expression = "this.setBackgroundType(type)"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Implemented as a custom view, `com.telefonica.mistica.ListRowView` can be used i
</attr>
<attr name="listRowHeadlineVisible" format="boolean" />
<attr name="listRowTitle" format="string" />
<attr name="isTitleHeading" format="boolean" />
<attr name="listRowTitleMaxLines" format="integer" />
<attr name="listRowSubtitle" format="string" />
<attr name="listRowSubtitleMaxLines" format="integer" />
Expand Down
1 change: 1 addition & 0 deletions library/src/main/res/values/attrs_components.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
</attr>
<attr name="listRowHeadlineVisible" format="boolean" />
<attr name="listRowTitle" format="string" />
<attr name="listRowIsTitleHeading" format="boolean" />
<attr name="listRowTitleMaxLines" format="integer" />
<attr name="listRowSubtitle" format="string" />
<attr name="listRowSubtitleMaxLines" format="integer" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
package com.telefonica.mistica.compose.list

import androidx.compose.foundation.clickable
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.test.assert
import androidx.compose.ui.test.hasTestTag
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.isHeading
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performClick
import com.telefonica.mistica.R
import com.telefonica.mistica.compose.shape.Chevron
import com.telefonica.mistica.compose.tag.Tag
import com.telefonica.mistica.compose.theme.MisticaTheme
import com.telefonica.mistica.compose.theme.brand.MovistarBrand
import com.telefonica.mistica.list.model.ImageDimensions
import com.telefonica.mistica.testutils.ScreenshotsTest
import org.junit.Assert.assertEquals
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import com.telefonica.mistica.R
import org.junit.Assert.assertEquals

private const val LIST_ROW_ITEM_ASSET_TAG = "listRowItemAssetTag"

@RunWith(RobolectricTestRunner::class)
internal class ListRowItemKtTest: ScreenshotsTest() {
internal class ListRowItemKtTest : ScreenshotsTest() {
@get:Rule
val composeTestRule = createComposeRule()

Expand Down Expand Up @@ -58,15 +60,38 @@ internal class ListRowItemKtTest: ScreenshotsTest() {
assertEquals(1, clicked)
}

@OptIn(ExperimentalMaterialApi::class)
@Test
fun `check ListRowItem with accessibility heading is heading`() {
val titleText = "Title With Heading"
`when ListRowItem with title`(
title = titleText,
isTitleHeading = true,
)
composeTestRule.onNode(hasText(titleText))
.assert(isHeading())
}

@Test
fun `check ListRowItem without accessibility heading is NOT heading`() {
val titleText = "Title NO Heading"
`when ListRowItem with title`(
title = titleText,
isTitleHeading = false,
)
composeTestRule.onNode(hasText(titleText))
.assert(!isHeading())
}

private fun `when ListRowItem with asset`(dimensions: ImageDimensions, onAssetClick: () -> Unit = {}) {
composeTestRule.setContent {
MisticaTheme(brand = MovistarBrand) {
ListRowItem(
listRowIcon = ListRowIcon.ImageAsset(
painter = painterResource(id = R.drawable.placeholder),
dimensions = ImageDimensions(width = dimensions.width, height = dimensions.height),
modifier = Modifier.testTag(LIST_ROW_ITEM_ASSET_TAG).clickable { onAssetClick() },
modifier = Modifier
.testTag(LIST_ROW_ITEM_ASSET_TAG)
.clickable { onAssetClick() },
),
headline = Tag("Promo"),
isBadgeVisible = true,
Expand All @@ -79,6 +104,22 @@ internal class ListRowItemKtTest: ScreenshotsTest() {
}
}

private fun `when ListRowItem with title`(title: String, isTitleHeading: Boolean) {
composeTestRule.setContent {
MisticaTheme(brand = MovistarBrand) {
ListRowItem(
listRowIcon = null,
headline = Tag("Promo"),
isBadgeVisible = true,
title = title,
isTitleHeading = isTitleHeading,
subtitle = "Subtitle",
description = "Description",
)
}
}
}

private fun `then screenshot is OK`() {
compareScreenshot(composeTestRule.onRoot())
}
Expand Down
Loading

0 comments on commit 314ac81

Please sign in to comment.