-
Notifications
You must be signed in to change notification settings - Fork 4
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-15405 -- PosterCard component #398
Merged
Merged
Changes from 32 commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
adb61a7
dhonti/ANDROID-15405-postercard: First approach "PosterCard" component
dhonti-axpe e2c7a55
dhonti/ANDROID-15405: Update approach in order to accept images
dhonti-axpe 45088ea
dhonti/ANDROID-15405-postercard: Fix viewing correctly lower custom c…
dhonti-axpe 4402233
dhonti/ANDROID-15405-postercard: Integration new "TopActions" attributos
dhonti-axpe ff2a984
dhonti/ANDROID-15405-postercard: Removing "Video" type from current "…
dhonti-axpe f43a07f
dhonti/ANDROID-15405-postercard: Entry "PosterCard" creation in Misti…
dhonti-axpe 7eeef69
dhonti/ANDROID-15405-postercard: Add sample background
dhonti-axpe 8166136
dhonti/ANDROID-15405-postercard: Update components "TopAction" compon…
dhonti-axpe c74285e
dhonti/ANDROID-15405-postercard: Update some components
dhonti-axpe 78a3947
dhonti/ANDROID-15405-postercard: Update sample attributes
dhonti-axpe 85958e2
dhonti/NADROID-15405-postercard:
dhonti-axpe ad8a3ad
dhonti/ANDROID-15405-postercard: FIXED rescale when is provided an fi…
dhonti-axpe 7ffe1aa
dhonti/ANDROID-15405-postercard: Place correctly the PosterCardTopAct…
dhonti-axpe e775585
dhonti/ANDROID-15405-postercard: Remove unused import
dhonti-axpe 528c8cf
dhonti/ANDROID-15405-postercard: Some code corrections
dhonti-axpe 2d4f90c
dhonti/ANDROID-15405-postercard: Create README.md file in "postercard…
dhonti-axpe d877419
dhonti/ANDROID-15405-postercard: Fixed linking to "compose" folder
dhonti-axpe af8fb30
dhonti/ANDRID-15405-postercard: Update location "sample_background"
dhonti-axpe cea0eb5
dhonti/ANDROID-15405-postercard: Update CONTRIBUTING.md
dhonti-axpe 6c1f09a
dhonti/ANDROID-15405-postercard: Update PosterCard README file
dhonti-axpe e1fbfc4
dhonti/ANDROID-15405-postercard: Applied some corrections proposed by…
dhonti-axpe 91ca854
dhonti/ANDROID-15405-postercard: Update modifier function in order to…
dhonti-axpe 97a3b69
dhonti/ANDROID-15405-postercard: Update clickable() in modifier action
dhonti-axpe 3586a36
dhonti/ANDROID-15405-postercard: New way to manage top actions list p…
dhonti-axpe 573a304
dhonti/ANDROID-15405-postercard: Update corresponding README.md poste…
dhonti-axpe faf034f
dhonti/ANDROID-15405-postercard: Update use the "cardContentOverlay" …
dhonti-axpe ef9ca70
dhonti/ANDROID-15405-postercard:
dhonti-axpe f1f1d21
dhonti/ANDROID-15405-postercard: Update top actions management in code
dhonti-axpe 2d4ce56
dhonti/ANDROID-15405-postercard: Update resource to catalog and chang…
dhonti-axpe 6b3637a
dhonti/ANDROID-15405-postercard: New preview reference with no images
dhonti-axpe 4c400f5
dhont/ANDROID-15405-postercard: Update correct reference to resource …
dhonti-axpe f73ec02
dhonti/ANDROID-15405-postercard: Update R mistica Catalog module in P…
dhonti-axpe 2c44779
dhonti/ANDROID-15405-postercard: 1st approach for accesibility Poster…
dhonti-axpe bdea242
dhonti/ANDROID-15405-postercard: Remove unused imports
dhonti-axpe a3f85e6
dhonti/ANDROID-15405-postercard: Change colors to support dark mode t…
dhonti-axpe 1d90eb7
dhonti/ANDROID-15405-postercard: 2nd approach a11 postercard
dhonti-axpe 52bb0b9
dhonti/ANDROID-15405-postercard: First approach with a11 integrated
dhonti-axpe 3ada235
dhonti/ANDROID-15405-postercard: A11 approach using "Modifier.zIndex(…
dhonti-axpe f78acfa
dhonti/ANDROID-15405-postercard: Apply some corrections from PR @jepr…
dhonti-axpe 1686468
Merge remote-tracking branch 'origin/main' into dhonti/ANDROID-15405-…
dhonti-axpe File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
231 changes: 231 additions & 0 deletions
231
catalog/src/main/java/com/telefonica/mistica/catalog/ui/compose/components/PosterCards.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,231 @@ | ||
package com.telefonica.mistica.catalog.ui.compose.components | ||
|
||
import androidx.annotation.AttrRes | ||
import androidx.compose.foundation.background | ||
import androidx.compose.foundation.border | ||
import androidx.compose.foundation.layout.Arrangement | ||
import androidx.compose.foundation.layout.Box | ||
import androidx.compose.foundation.layout.Column | ||
import androidx.compose.foundation.layout.Row | ||
import androidx.compose.foundation.layout.fillMaxSize | ||
import androidx.compose.foundation.layout.fillMaxWidth | ||
import androidx.compose.foundation.layout.padding | ||
import androidx.compose.foundation.layout.size | ||
import androidx.compose.foundation.rememberScrollState | ||
import androidx.compose.foundation.verticalScroll | ||
import androidx.compose.material.Checkbox | ||
import androidx.compose.material.OutlinedTextField | ||
import androidx.compose.material.Text | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.getValue | ||
import androidx.compose.runtime.mutableIntStateOf | ||
import androidx.compose.runtime.mutableStateOf | ||
import androidx.compose.runtime.remember | ||
import androidx.compose.runtime.setValue | ||
import androidx.compose.ui.Alignment | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.graphics.Brush | ||
import androidx.compose.ui.graphics.Color | ||
import androidx.compose.ui.graphics.SolidColor | ||
import androidx.compose.ui.unit.dp | ||
import com.telefonica.mistica.catalog.R | ||
import com.telefonica.mistica.compose.card.postercard.PosterCard | ||
import com.telefonica.mistica.compose.card.postercard.PosterCardAspectRatio | ||
import com.telefonica.mistica.compose.card.postercard.PosterCardBackgroundType | ||
import com.telefonica.mistica.compose.card.postercard.TopActionData | ||
import com.telefonica.mistica.compose.input.DropDownInput | ||
import com.telefonica.mistica.compose.tag.Tag | ||
import com.telefonica.mistica.compose.theme.MisticaTheme | ||
import com.telefonica.mistica.tag.TagView | ||
import com.telefonica.mistica.tag.TagView.Companion.TYPE_PROMO | ||
|
||
@Composable | ||
fun PosterCards() { | ||
|
||
var tag: String by remember { mutableStateOf("Headline") } | ||
var tagType: Int by remember { mutableIntStateOf(TYPE_PROMO) } | ||
|
||
var aspectRatioType: PosterCardAspectRatio by remember { mutableStateOf(PosterCardAspectRatio.AR_AUTO) } | ||
|
||
var inverseDisplay: Boolean by remember { mutableStateOf(true) } | ||
var backgroundType: BackgroundType by remember { mutableStateOf(BackgroundType.IMAGE) } | ||
|
||
var topActionsType: TopActionsType by remember { mutableStateOf(TopActionsType.NONE) } | ||
|
||
var preTitle: String by remember { mutableStateOf("Pretitle") } | ||
var title: String by remember { mutableStateOf("Title") } | ||
var subtitle: String by remember { mutableStateOf("Subtitle") } | ||
var description: String by remember { mutableStateOf("Description") } | ||
|
||
var withAdditionalContent: Boolean by remember { mutableStateOf(false) } | ||
|
||
|
||
Column( | ||
modifier = Modifier | ||
.fillMaxSize() | ||
.padding(16.dp) | ||
.verticalScroll(rememberScrollState()), | ||
verticalArrangement = Arrangement.Center, | ||
horizontalAlignment = Alignment.CenterHorizontally, | ||
) { | ||
DropDownInput( | ||
modifier = Modifier | ||
.fillMaxWidth() | ||
.padding(top = 4.dp), | ||
items = PosterCardAspectRatio.entries.map { aspectRatioLabelsMaps[it].orEmpty() }, | ||
currentItemIndex = PosterCardAspectRatio.entries.indexOf(aspectRatioType), | ||
onItemSelected = { index -> aspectRatioType = PosterCardAspectRatio.entries.toTypedArray()[index] }, | ||
hint = "Aspect Ratio", | ||
) | ||
|
||
DropDownInput( | ||
modifier = Modifier | ||
.fillMaxWidth() | ||
.padding(top = 4.dp), | ||
items = BackgroundType.entries.map { backgroundTypeLabelsMap[it].orEmpty() }, | ||
currentItemIndex = BackgroundType.entries.indexOf(backgroundType), | ||
onItemSelected = { index -> backgroundType = BackgroundType.entries.toTypedArray()[index] }, | ||
hint = "Background type", | ||
) | ||
|
||
if (backgroundType != BackgroundType.IMAGE) { | ||
Row(verticalAlignment = Alignment.CenterVertically) { | ||
Text("Inverse display") | ||
Checkbox(checked = inverseDisplay, onCheckedChange = { | ||
inverseDisplay = !inverseDisplay | ||
backgroundType.backgroundValue.inverseDisplay = inverseDisplay | ||
}) | ||
} | ||
} | ||
|
||
DropDownInput( | ||
modifier = Modifier | ||
.fillMaxWidth() | ||
.padding(top = 4.dp), | ||
items = TopActionsType.entries.map { topActionsTypeLabelsMap[it].orEmpty() }, | ||
currentItemIndex = TopActionsType.entries.indexOf(topActionsType), | ||
onItemSelected = { index -> topActionsType = TopActionsType.entries.toTypedArray()[index] }, | ||
hint = "Top actions", | ||
) | ||
|
||
OutlinedTextField( | ||
modifier = Modifier.fillMaxWidth(), | ||
value = tag, | ||
onValueChange = { tag = it }, label = { Text("Tag label") } | ||
) | ||
|
||
DropDownInput( | ||
modifier = Modifier | ||
.fillMaxWidth() | ||
.padding(top = 4.dp), | ||
items = TagColorsValues.entries.map { it.name }, | ||
currentItemIndex = tagType, | ||
onItemSelected = { index -> tagType = index }, | ||
hint = "Tag style", | ||
) | ||
|
||
OutlinedTextField(modifier = Modifier.fillMaxWidth(), value = preTitle, onValueChange = { preTitle = it }, label = { Text("Pretitle") }) | ||
OutlinedTextField(modifier = Modifier.fillMaxWidth(), value = title, onValueChange = { title = it }, label = { Text("Title") }) | ||
OutlinedTextField(modifier = Modifier.fillMaxWidth(), value = subtitle, onValueChange = { subtitle = it }, label = { Text("Subtitle") }) | ||
OutlinedTextField(modifier = Modifier.fillMaxWidth(), value = description, onValueChange = { description = it }, label = { Text("Description") }) | ||
|
||
Row(verticalAlignment = Alignment.CenterVertically) { | ||
Text("With additional content") | ||
Checkbox(checked = withAdditionalContent, onCheckedChange = { withAdditionalContent = !withAdditionalContent }) | ||
} | ||
|
||
PosterCard( | ||
modifier = Modifier.fillMaxWidth(), | ||
aspectRatio = aspectRatioType, | ||
backgroundType = backgroundType.backgroundValue, | ||
headline = if (tag.isNotEmpty()) Tag(tag).withStyle(tagType) else null, | ||
preTitle = preTitle.getOrNullIfEmpty(), | ||
title = title.getOrNullIfEmpty(), | ||
subtitle = subtitle.getOrNullIfEmpty(), | ||
description = description.getOrNullIfEmpty(), | ||
firstTopAction = topActionsType.info?.firstTopAction, | ||
secondTopAction = topActionsType.info?.secondTopAction, | ||
customContent = { | ||
if (withAdditionalContent) { | ||
AdditionalContent() | ||
} | ||
} | ||
) | ||
} | ||
} | ||
|
||
private enum class TagColorsValues(@AttrRes val tagStyle: Int) { | ||
PROMO(TYPE_PROMO), | ||
ACTIVE(TagView.TYPE_ACTIVE), | ||
INACTIVE(TagView.TYPE_INACTIVE), | ||
SUCCESS(TagView.TYPE_SUCCESS), | ||
WARNING(TagView.TYPE_WARNING), | ||
ERROR(TagView.TYPE_ERROR), | ||
INVERSE(TagView.TYPE_INVERSE), | ||
} | ||
|
||
private val aspectRatioLabelsMaps = mapOf( | ||
PosterCardAspectRatio.AR_AUTO to "Auto", | ||
PosterCardAspectRatio.AR_1_1 to "1:1", | ||
PosterCardAspectRatio.AR_7_10 to "7:10", | ||
PosterCardAspectRatio.AR_9_10 to "9:10", | ||
PosterCardAspectRatio.AR_16_9 to "16:9" | ||
) | ||
|
||
private val backgroundTypeLabelsMap = mapOf( | ||
BackgroundType.SOLID_COLOR to "Solid color", | ||
BackgroundType.GRADIENT_COLOR to "Gradient color", | ||
BackgroundType.IMAGE to "Image" | ||
) | ||
|
||
private val topActionsTypeLabelsMap = mapOf( | ||
TopActionsType.NONE to "None", | ||
TopActionsType.ONE_ACTION_DISMISS to "One action (Dismiss)", | ||
TopActionsType.TWO_ACTIONS to "Two actions (View + Dismiss)" | ||
) | ||
|
||
private enum class BackgroundType(val backgroundValue: PosterCardBackgroundType) { | ||
IMAGE(PosterCardBackgroundType.Image(imageResource = R.drawable.sample_background)), | ||
SOLID_COLOR(PosterCardBackgroundType.Color(brush = SolidColor(Color.Red))), | ||
GRADIENT_COLOR(PosterCardBackgroundType.Color(brush = Brush.verticalGradient(colors = listOf(Color.Blue, Color.Cyan)))), | ||
} | ||
|
||
private enum class TopActionsType(val info: PosterCardTopActionInfo? = null) { | ||
NONE, | ||
ONE_ACTION_DISMISS( | ||
info = PosterCardTopActionInfo( | ||
firstTopAction = TopActionData(iconRes = R.drawable.ic_close_regular) | ||
) | ||
), | ||
TWO_ACTIONS( | ||
info = PosterCardTopActionInfo( | ||
firstTopAction = TopActionData(iconRes = R.drawable.icn_visibility), | ||
secondTopAction = TopActionData(iconRes = R.drawable.ic_close_regular) | ||
) | ||
) | ||
} | ||
|
||
private data class PosterCardTopActionInfo( | ||
val firstTopAction: TopActionData? = null, | ||
val secondTopAction: TopActionData? = null | ||
) | ||
|
||
@Composable | ||
internal fun AdditionalContent() { | ||
Box( | ||
modifier = Modifier | ||
.fillMaxWidth() | ||
.size(150.dp) | ||
.background(color = MisticaTheme.colors.successHighInverse.copy(alpha = 0.5f)) | ||
.border(width = 1.dp, color = MisticaTheme.colors.success), | ||
contentAlignment = Alignment.Center | ||
) { | ||
Text( | ||
text = "Additional content", | ||
style = MisticaTheme.typography.preset2, | ||
color = MisticaTheme.colors.textPrimaryInverse | ||
) | ||
} | ||
} | ||
|
||
private fun String.getOrNullIfEmpty(): String? = this.ifEmpty { null } |
Binary file not shown.
100 changes: 100 additions & 0 deletions
100
library/src/main/java/com/telefonica/mistica/compose/card/postercard/PosterCard.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package com.telefonica.mistica.compose.card.postercard | ||
|
||
import androidx.annotation.DrawableRes | ||
import androidx.compose.foundation.clickable | ||
import androidx.compose.foundation.layout.Arrangement | ||
import androidx.compose.foundation.layout.BoxWithConstraints | ||
import androidx.compose.foundation.layout.Column | ||
import androidx.compose.foundation.layout.Spacer | ||
import androidx.compose.foundation.layout.height | ||
import androidx.compose.foundation.layout.heightIn | ||
import androidx.compose.foundation.layout.width | ||
import androidx.compose.foundation.shape.RoundedCornerShape | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.ui.Alignment | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.graphics.Brush | ||
import androidx.compose.ui.semantics.focused | ||
import androidx.compose.ui.semantics.semantics | ||
import androidx.compose.ui.unit.Dp | ||
import androidx.compose.ui.unit.dp | ||
import com.telefonica.mistica.compose.tag.Tag | ||
import com.telefonica.mistica.compose.theme.MisticaTheme | ||
|
||
@Composable | ||
fun PosterCard( | ||
modifier: Modifier = Modifier, | ||
aspectRatio: PosterCardAspectRatio, | ||
backgroundType: PosterCardBackgroundType, | ||
headline: Tag? = null, | ||
preTitle: String? = null, | ||
title: String? = null, | ||
subtitle: String? = null, | ||
description: String? = null, | ||
firstTopAction: TopActionData? = null, | ||
secondTopAction: TopActionData? = null, | ||
onClickAction: (() -> Unit)? = null, | ||
customContent: (@Composable () -> Unit)? = null, | ||
) { | ||
val anyTopActionsLoaded = firstTopAction!=null || secondTopAction!=null | ||
|
||
BoxWithConstraints(modifier = modifier) { | ||
androidx.compose.material.Card( | ||
elevation = 0.dp, | ||
shape = RoundedCornerShape(MisticaTheme.radius.containerBorderRadius), | ||
modifier = Modifier | ||
.width(maxWidth) | ||
.clickable(enabled = onClickAction!=null) { | ||
onClickAction?.invoke() | ||
} | ||
.heightIn( | ||
min = maxWidth / aspectRatio.ratio, | ||
max = Dp.Infinity | ||
) | ||
.semantics { | ||
focused = true | ||
} | ||
) { | ||
PosterCardBackground(backgroundType = backgroundType) { | ||
Column( | ||
modifier = Modifier.align(alignment = Alignment.BottomCenter), | ||
verticalArrangement = Arrangement.Bottom | ||
) { | ||
if (anyTopActionsLoaded) { | ||
Spacer(modifier = Modifier.height(40.dp)) | ||
} | ||
PosterCardMainContent( | ||
backgroundType = backgroundType, | ||
tag = headline, | ||
preTitle = preTitle, | ||
title = title, | ||
description = description, | ||
subtitle = subtitle, | ||
customContent = customContent | ||
) | ||
} | ||
if (anyTopActionsLoaded) { | ||
PosterCardTopActions( | ||
modifier = Modifier.align(alignment = Alignment.TopCenter), | ||
firstTopAction = firstTopAction, | ||
secondTopAction = secondTopAction | ||
) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
enum class PosterCardAspectRatio(val ratio: Float) { | ||
AR_AUTO(ratio = Float.NaN), | ||
AR_1_1(ratio = 1f), | ||
AR_7_10(ratio = 0.7f), | ||
AR_9_10(ratio = 0.9f), | ||
AR_16_9(16 / 9f) | ||
} | ||
|
||
sealed class PosterCardBackgroundType(open var inverseDisplay: Boolean) { | ||
data class Image(@DrawableRes val imageResource: Int, val contentDescription: String = "") : PosterCardBackgroundType(inverseDisplay = true) | ||
data class Color(val brush: Brush, override var inverseDisplay: Boolean = true) : PosterCardBackgroundType(inverseDisplay = inverseDisplay) | ||
} | ||
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://blog.simprasuite.com/jetpack-compose-respect-the-contract-of-modifiers-ecbbe8ce03db#:~:text=The%20modifier%20should%20be%20the,other%20parameters%20with%20default%20values.