Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ANDROID-14098 set asset dimensions #322

Merged
merged 8 commits into from
Dec 19, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ import com.telefonica.mistica.list.ListRowView.Companion.TYPE_IMAGE
import com.telefonica.mistica.list.ListRowView.Companion.TYPE_IMAGE_16_9
import com.telefonica.mistica.list.ListRowView.Companion.TYPE_IMAGE_1_1
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.MisticaRecyclerView
import com.telefonica.mistica.list.model.ImageDimensions
import com.telefonica.mistica.tag.TagStyle
import com.telefonica.mistica.tag.TagView
import com.telefonica.mistica.tag.TagView.Companion.TYPE_INVERSE
Expand Down Expand Up @@ -438,6 +440,17 @@ class ListsCatalogFragment : Fragment() {
withInverseBackground = withInverseBackground,
)
},
{
it.configureView(
withAsset = true,
withAssetType = TYPE_IMAGE_ROUNDED,
withDimensions = ImageDimensions(width = 64, height = 64),
withAction = true,
withSubtitle = true,
withHeadline = true,
withInverseBackground = withInverseBackground,
)
},
)

@SuppressLint("SetTextI18n")
Expand All @@ -448,6 +461,7 @@ class ListsCatalogFragment : Fragment() {
withDescriptionMaxLines: Int? = null,
withAsset: Boolean = false,
@AssetType withAssetType: Int = TYPE_SMALL_ICON,
withDimensions: ImageDimensions? = null,
withAction: Boolean = false,
withBadge: Boolean = false,
withBadgeNumeric: Int = 0,
Expand Down Expand Up @@ -487,6 +501,10 @@ class ListsCatalogFragment : Fragment() {
}
)

withDimensions?.let {
setAssetHeight(withDimensions.height)
setAssetWidth(withDimensions.width)
}
setAssetType(withAssetType)
withUrlIcon?.let {
setAssetUrl(it, errorDrawable = withErrorIcon)
Expand Down Expand Up @@ -522,6 +540,7 @@ class ListsCatalogFragment : Fragment() {
TYPE_IMAGE_1_1,
TYPE_IMAGE_16_9,
TYPE_IMAGE_7_10,
TYPE_IMAGE_ROUNDED,
-> R.drawable.highlighted_card_custom_background

else -> R.drawable.ic_lists
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import com.telefonica.mistica.compose.list.ListRowItem
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.list.model.ImageDimensions
import com.telefonica.mistica.tag.TagView.Companion.TYPE_PROMO

const val TITLE = "Title"
Expand Down Expand Up @@ -276,6 +277,18 @@ fun samples() = listOf(
painter = painterResource(id = R.drawable.list_row_drawable),
aspectRatio = ListRowIcon.AspectRatio.RATIO_7_10
),
),
ListItem(
title = TITLE,
subtitle = SUBTITLE,
description = DESCRIPTION,
action = { Switch(checked = true, onCheckedChange = {}) },
isBadgeVisible = true,
badge = "1",
listRowIcon = ListRowIcon.ImageAsset(
painter = painterResource(id = R.drawable.list_row_drawable),
dimensions = ImageDimensions(width = 64, height = 64),
),
)
)

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 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 @@ -19,6 +19,7 @@ import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.telefonica.mistica.compose.shape.Circle
import com.telefonica.mistica.list.model.ImageDimensions

sealed class ListRowIcon(val contentDescription: String?) {

Expand All @@ -45,6 +46,13 @@ sealed class ListRowIcon(val contentDescription: String?) {
private val description: String? = null,
) : ListRowIcon(description)

data class ImageAsset(
val painter: Painter? = null,
val dimensions: ImageDimensions = ImageDimensions(width = 64, height = 64),
val contentScale: ContentScale = ContentScale.Crop,
private val description: String? = null,
) : ListRowIcon(description)

enum class AspectRatio(val width: Dp, val height: Dp) {
RATIO_1_1(80.dp, 80.dp),
RATIO_7_10(80.dp, 116.dp),
Expand All @@ -58,6 +66,7 @@ sealed class ListRowIcon(val contentDescription: String?) {
is CircleIcon -> DrawCircleIcon()
is SmallAsset -> DrawSmallAsset()
is LargeAsset -> DrawLargeAsset()
is ImageAsset -> DrawImageAsset()
}
}

Expand Down Expand Up @@ -121,4 +130,19 @@ sealed class ListRowIcon(val contentDescription: String?) {
)
}
}

@Composable
private fun ImageAsset.DrawImageAsset() {
painter?.let {
Image(
painter = painter,
contentDescription = contentDescription,
modifier = Modifier
.width(dimensions.width.dp)
.height(dimensions.height.dp)
.clip(RoundedCornerShape(4.dp)),
contentScale = contentScale,
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ There are 4 types of icons:
- `SmallAsset`: it's a circle icon, it could be a `Drawable` resource or a external url with a `description` parameter inside.
- `LargeAsset`: it's a custom image, it could be a `Drawable` resource or a external url with a `description` parameter inside. It's possible to define the
`aspectRatio` of the image and the `contentScale` type
- `ImageAsset`: it's a custom image, it could be a `Drawable` resource or a external url with a `description` parameter inside. It's possible to define the
`dimensions` which is of type `ImageDimensions`.

![image](https://user-images.githubusercontent.com/944814/143047368-3494885c-6324-4b4b-bcc0-4177525208bf.png)

Expand Down
52 changes: 48 additions & 4 deletions library/src/main/java/com/telefonica/mistica/list/ListRowView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import androidx.databinding.BindingMethods
import coil.load
import com.telefonica.mistica.R
import com.telefonica.mistica.badge.Badge
import com.telefonica.mistica.list.model.ImageDimensions
import com.telefonica.mistica.util.convertDpToPx
import com.telefonica.mistica.util.getThemeColor
import com.telefonica.mistica.util.setAlpha
Expand Down Expand Up @@ -95,6 +96,16 @@ import com.telefonica.mistica.util.setAlpha
attribute = "listRowActionLayout",
method = "setActionLayout"
),
BindingMethod(
type = ListRowView::class,
attribute = "listRowAssetHeight",
method = "setAssetHeight"
),
BindingMethod(
type = ListRowView::class,
attribute = "listRowAssetWidth",
method = "setAssetWidth"
),
)
class ListRowView @JvmOverloads constructor(
context: Context,
Expand All @@ -109,7 +120,8 @@ class ListRowView @JvmOverloads constructor(
TYPE_LARGE_ICON,
TYPE_IMAGE_1_1,
TYPE_IMAGE_7_10,
TYPE_IMAGE_16_9
TYPE_IMAGE_16_9,
TYPE_IMAGE_ROUNDED,
)
annotation class AssetType

Expand Down Expand Up @@ -143,6 +155,8 @@ class ListRowView @JvmOverloads constructor(
private var currentHeadlineLayoutRes: Int = HEADLINE_NONE
private var currentActionLayoutRes: Int = ACTION_NONE
private var assetType: Int = TYPE_SMALL_ICON
private var assetHeight: Int = ASSET_DEFAULT_SIZE
private var assetWidth: Int = ASSET_DEFAULT_SIZE

init {
LayoutInflater.from(context).inflate(R.layout.list_row_item, this, true)
Expand Down Expand Up @@ -201,6 +215,18 @@ class ListRowView @JvmOverloads constructor(
backgroundTypeDefaultValue
)
)
setAssetHeight(
styledAttrs.getInt(
R.styleable.ListRowView_listRowAssetHeight,
ASSET_DEFAULT_SIZE
)
)
setAssetWidth(
styledAttrs.getInt(
R.styleable.ListRowView_listRowAssetWidth,
ASSET_DEFAULT_SIZE
)
)
setAssetType(
styledAttrs.getInt(
R.styleable.ListRowView_listRowAssetType,
Expand Down Expand Up @@ -242,7 +268,8 @@ class ListRowView @JvmOverloads constructor(
TYPE_IMAGE -> assetCircularImageView
TYPE_IMAGE_1_1,
TYPE_IMAGE_7_10,
TYPE_IMAGE_16_9 -> assetRoundedImageView
TYPE_IMAGE_16_9,
TYPE_IMAGE_ROUNDED -> assetRoundedImageView
else -> assetImageView
}.also { imageView ->
imageView.load(url) {
Expand Down Expand Up @@ -270,6 +297,7 @@ class ListRowView @JvmOverloads constructor(
TYPE_IMAGE_1_1,
TYPE_IMAGE_7_10,
TYPE_IMAGE_16_9,
TYPE_IMAGE_ROUNDED
-> assetRoundedImageView.setImageDrawable(drawable)

else -> assetImageView.setImageDrawable(drawable)
Expand All @@ -283,15 +311,28 @@ class ListRowView @JvmOverloads constructor(

private fun updateIconVisibility() {
assetCircularImageView.isVisible = assetType == TYPE_IMAGE
assetRoundedImageView.isVisible = assetType == TYPE_IMAGE_1_1 || assetType == TYPE_IMAGE_7_10 || assetType == TYPE_IMAGE_16_9
assetRoundedImageView.isVisible = assetType == TYPE_IMAGE_1_1 || assetType == TYPE_IMAGE_7_10
|| assetType == TYPE_IMAGE_16_9 || assetType == TYPE_IMAGE_ROUNDED
assetImageView.isVisible = assetType == TYPE_SMALL_ICON || assetType == TYPE_LARGE_ICON
}

fun setAssetType(@AssetType type: Int) {
fun setAssetType(@AssetType type: Int, dimensions: ImageDimensions? = null) {
Copy link
Contributor

@dpastor dpastor Dec 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Appart from programatic configuration we expose also configurable elements with xml attributes. Check ListRowView styleable in attrs_components.xml to add new asset type enum and height/width attributes. Ideally if databinding method matches attribute definition behaviour, its better, so there's no difference in the usage when using databinding and when not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I forgot doing that, I'll do that now. Thanks!

Copy link
Contributor Author

@jeprubio jeprubio Dec 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 396f739
Screenshot 2023-12-19 at 10 15 14
Screenshot 2023-12-19 at 10 17 07

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it working the binding method with this new parameter? Or is it just ignored because is nullable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That one of the fun setAssetType will be null with binding and there are the other two of setAssetHeight and setAssetWidth to set the dimensions. That param is in order to use it when creating the element programmatically, but can be changed, it was thought as a shortcut.

assetType = type
dimensions?.let {
setAssetHeight(it.height)
setAssetWidth(it.width)
}
configureAsset()
}

fun setAssetHeight(height: Int) {
assetHeight = height
}

fun setAssetWidth(width: Int) {
assetWidth = width
}

private fun configureAsset() {
when (assetType) {
TYPE_IMAGE -> {
Expand All @@ -311,6 +352,7 @@ class ListRowView @JvmOverloads constructor(
TYPE_IMAGE_1_1 -> assetRoundedImageView.setSize(80, 80)
TYPE_IMAGE_7_10 -> assetRoundedImageView.setSize(80, 116)
TYPE_IMAGE_16_9 -> assetRoundedImageView.setSize(138, 80)
TYPE_IMAGE_ROUNDED -> assetRoundedImageView.setSize(assetWidth, assetHeight)
}
recalculateAssetPosition()
}
Expand Down Expand Up @@ -555,6 +597,7 @@ class ListRowView @JvmOverloads constructor(

companion object {
private const val BADGE_GONE = 0
private const val ASSET_DEFAULT_SIZE = 64
const val ACTION_NONE = -1
const val HEADLINE_NONE = -1
const val TYPE_IMAGE = 0
Expand All @@ -563,6 +606,7 @@ class ListRowView @JvmOverloads constructor(
const val TYPE_IMAGE_1_1 = 3
const val TYPE_IMAGE_7_10 = 4
const val TYPE_IMAGE_16_9 = 5
const val TYPE_IMAGE_ROUNDED = 6

@BindingAdapter(
value = ["listRowBadgeCount", "listRowBadgeDescription"],
Expand Down
7 changes: 7 additions & 0 deletions library/src/main/java/com/telefonica/mistica/list/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ Implemented as a custom view, `com.telefonica.mistica.ListRowView` can be used i
<enum name="image_1_1" value="3" />
<enum name="image_7_10" value="4" />
<enum name="image_16_9" value="5" />
<enum name="image_rounded" value="6" />
</attr>
<attr name="listRowAssetHeight" format="integer">
<enum name="undefined" value="64" />
</attr>
<attr name="listRowAssetWidth" format="integer">
<enum name="undefined" value="64" />
</attr>
<attr name="listRowBackgroundType" format="enum">
<enum name="normal" value="0" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.telefonica.mistica.list.model

data class ImageDimensions(
val width: Int,
val height: Int,
)
7 changes: 7 additions & 0 deletions library/src/main/res/values/attrs_components.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@
<enum name="image_1_1" value="3" />
<enum name="image_7_10" value="4" />
<enum name="image_16_9" value="5" />
<enum name="image_rounded" value="6" />
</attr>
<attr name="listRowAssetHeight" format="integer">
<enum name="undefined" value="64" />
</attr>
<attr name="listRowAssetWidth" format="integer">
<enum name="undefined" value="64" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should these attrs be of type "dimension" in case someone uses them as follows?

listRowAssetWidth="@dimen/some_width"

Copy link
Contributor

@jeslat jeslat Dec 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, I think it should be dimension to avoid putting just a raw number, we should use dp

Copy link
Contributor Author

@jeprubio jeprubio Dec 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, I can do this now. Good shout.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, both in 1c1ee2b

</attr>
<!-- {@deprecated This attribute is deprecated. Use <code>listRowBackgroundType</code> instead } -->
<attr name="listRowIsBoxed" format="boolean" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.telefonica.mistica.compose.list

import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onRoot
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.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import com.telefonica.mistica.R

@RunWith(RobolectricTestRunner::class)
internal class ListRowItemKtTest: ScreenshotsTest() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, why that Kt in the middle of the class name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you create a test with Android Studio it creates them this way sometimes, I'm not sure which rules does it follow. I can remove that if you want.

@get:Rule
val composeTestRule = createComposeRule()

@Test
fun `check ListRowItem with 64x64 asset`() {
`when ListRowItem with asset`(ImageDimensions(width = 64, height = 64))

`then screenshot is OK`()
}

@Test
fun `check ListRowItem with 32x32 asset`() {
`when ListRowItem with asset`(ImageDimensions(width = 32, height = 32))

`then screenshot is OK`()
}

@OptIn(ExperimentalMaterialApi::class)
private fun `when ListRowItem with asset`(dimensions: ImageDimensions) {
composeTestRule.setContent {
MisticaTheme(brand = MovistarBrand) {
ListRowItem(
listRowIcon = ListRowIcon.ImageAsset(
painter = painterResource(id = R.drawable.placeholder),
dimensions = ImageDimensions(width = dimensions.width, height = dimensions.height),
),
headline = Tag("Promo"),
isBadgeVisible = true,
title = "Title",
subtitle = "Subtitle",
description = "Description",
trailing = { Chevron() },
)
}
}
}

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