-
Notifications
You must be signed in to change notification settings - Fork 92
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
Update Uamp Player Screen bottom buttons layout #2407
base: main
Are you sure you want to change the base?
Changes from all commits
284987b
75ca640
270c5dd
bf563aa
d555e8f
46efae6
e54fb59
d3f7853
3d282ca
c18f0ff
99f8c92
c004f78
ee0d541
cb517ec
387bc85
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,6 @@ import androidx.compose.foundation.ExperimentalFoundationApi | |
import androidx.compose.foundation.MarqueeSpacing | ||
import androidx.compose.foundation.basicMarquee | ||
import androidx.compose.foundation.layout.PaddingValues | ||
import androidx.compose.foundation.layout.height | ||
import androidx.compose.foundation.layout.padding | ||
import androidx.compose.foundation.text.InlineTextContent | ||
import androidx.compose.runtime.Composable | ||
|
@@ -75,7 +74,10 @@ import kotlin.time.Duration.Companion.seconds | |
* @param textAlign The alignment of the text within the lines of the paragraph. | ||
* See [TextStyle.textAlign]. | ||
* @param followGap the width between end of each scrolling text and the start of the following one. | ||
* @param edgeGradientWidth the width of the fade out zone on the edges, so text isn't cut off | ||
* @param startGap the padding in [Dp] added before the [text]. | ||
* @param startEdgeGradientWidth the width of the fade out zone on the start edge, so text isn't cut | ||
* off harshly. | ||
* @param endEdgeGradientWidth the width of the fade out zone on the end edge, so text isn't cut off | ||
* harshly. | ||
* @param marqueeDpPerSecond the speed of scrolling in dp per second. | ||
* @param pauseTime the duration before initially scrolling and each additional scroll. | ||
|
@@ -90,12 +92,17 @@ public fun MarqueeText( | |
style: TextStyle = LocalTextStyle.current, | ||
textAlign: TextAlign = TextAlign.Left, | ||
followGap: Dp = 96.dp, | ||
edgeGradientWidth: Dp = 16.dp, | ||
startGap: Dp = 0.dp, | ||
startEdgeGradientWidth: Dp = 16.dp, | ||
endEdgeGradientWidth: Dp = 16.dp, | ||
marqueeDpPerSecond: Dp = 64.dp, | ||
pauseTime: Duration = 4.seconds, | ||
) { | ||
val controller = remember(text, style) { MarqueeController(edgeGradientWidth) } | ||
controller.edgeGradientWidth = edgeGradientWidth | ||
val controller = remember(text, style) { | ||
MarqueeController(startEdgeGradientWidth, endEdgeGradientWidth, startGap) | ||
} | ||
controller.startEdgeGradientWidth = startEdgeGradientWidth | ||
controller.endEdgeGradientWidth = endEdgeGradientWidth | ||
|
||
Text( | ||
text = text, | ||
|
@@ -135,6 +142,118 @@ public fun MarqueeText( | |
* @param textAlign The alignment of the text within the lines of the paragraph. | ||
* See [TextStyle.textAlign]. | ||
* @param followGap the width between end of each scrolling text and the start of the following one. | ||
* @param startGap the padding in [Dp] added before the [text]. | ||
* @param startEdgeGradientWidth the width of the fade out zone on the start edge, so text isn't cut | ||
* off harshly. | ||
* @param endEdgeGradientWidth the width of the fade out zone on the end edge, so text isn't cut off | ||
* harshly. | ||
* @param marqueeDpPerSecond the speed of scrolling in dp per second. | ||
* @param pauseTime the duration before initially scrolling and each additional scroll. | ||
*/ | ||
@ExperimentalHorologistApi | ||
@Composable | ||
public fun MarqueeText( | ||
text: String, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have a lot of new forms of this method, if this is a more advanced form and we want to keep the existing simpler forms, should we only add the AnnotatedString version? |
||
modifier: Modifier = Modifier, | ||
color: Color = Color.Unspecified, | ||
style: TextStyle = LocalTextStyle.current, | ||
textAlign: TextAlign = TextAlign.Left, | ||
followGap: Dp = 96.dp, | ||
startGap: Dp = 0.dp, | ||
startEdgeGradientWidth: Dp = 16.dp, | ||
endEdgeGradientWidth: Dp = 16.dp, | ||
marqueeDpPerSecond: Dp = 64.dp, | ||
pauseTime: Duration = 4.seconds, | ||
) { | ||
MarqueeText( | ||
text = AnnotatedString(text), | ||
inlineContent = emptyMap(), | ||
modifier = modifier, | ||
color = color, | ||
style = style, | ||
textAlign = textAlign, | ||
followGap = followGap, | ||
startGap = startGap, | ||
startEdgeGradientWidth = startEdgeGradientWidth, | ||
endEdgeGradientWidth = endEdgeGradientWidth, | ||
marqueeDpPerSecond = marqueeDpPerSecond, | ||
pauseTime = pauseTime, | ||
) | ||
} | ||
|
||
/** | ||
* Show a single line Marquee text, with a pause (initial and between cycles) and speed. | ||
* | ||
* Otherwise is mostly the same as the [Text] composable, without params that don't apply for | ||
* marquee, such as maxLines. | ||
* | ||
* Only scrolls if required, and otherwise uses textAlign to show the content in a | ||
* stationary position. | ||
* | ||
* @param text The text to be displayed, where [AnnotatedString] allows multiple styles to be used. | ||
* @param modifier [Modifier] to apply to this layout node. | ||
* @param inlineContent A map store composables that replaces certain ranges of the text. It's | ||
* used to insert composables into text layout. Check [InlineTextContent] for more information. | ||
* @param color [Color] to apply to the text. If [Color.Unspecified], and [style] has no color set, | ||
* this will be [LocalContentColor]. | ||
* @param style Style configuration for the text such as color, font, line height etc. | ||
* @param textAlign The alignment of the text within the lines of the paragraph. | ||
* See [TextStyle.textAlign]. | ||
* @param followGap the width between end of each scrolling text and the start of the following one. | ||
* @param startGap the padding in [Dp] added before the [text]. | ||
* @param edgeGradientWidth the width of the fade out zone on the edges, so text isn't cut off | ||
* harshly. | ||
* @param marqueeDpPerSecond the speed of scrolling in dp per second. | ||
* @param pauseTime the duration before initially scrolling and each additional scroll. | ||
*/ | ||
@ExperimentalHorologistApi | ||
@Composable | ||
public fun MarqueeText( | ||
text: AnnotatedString, | ||
modifier: Modifier = Modifier, | ||
inlineContent: Map<String, InlineTextContent> = mapOf(), | ||
color: Color = Color.Unspecified, | ||
style: TextStyle = LocalTextStyle.current, | ||
textAlign: TextAlign = TextAlign.Left, | ||
followGap: Dp = 96.dp, | ||
startGap: Dp = 0.dp, | ||
edgeGradientWidth: Dp = 16.dp, | ||
marqueeDpPerSecond: Dp = 64.dp, | ||
pauseTime: Duration = 4.seconds, | ||
) { | ||
MarqueeText( | ||
text = text, | ||
inlineContent = inlineContent, | ||
modifier = modifier, | ||
color = color, | ||
style = style, | ||
textAlign = textAlign, | ||
followGap = followGap, | ||
startGap = startGap, | ||
startEdgeGradientWidth = edgeGradientWidth, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this also set endEdgeGradientWidth? |
||
marqueeDpPerSecond = marqueeDpPerSecond, | ||
pauseTime = pauseTime, | ||
) | ||
} | ||
|
||
/** | ||
* Show a single line Marquee text, with a pause (initial and between cycles) and speed. | ||
* | ||
* Otherwise is mostly the same as the [Text] composable, without params that don't apply for | ||
* marquee, such as maxLines. | ||
* | ||
* Only scrolls if required, and otherwise uses textAlign to show the content in a | ||
* stationary position. | ||
* | ||
* @param text The text to be displayed. | ||
* @param modifier [Modifier] to apply to this layout node. | ||
* @param color [Color] to apply to the text. If [Color.Unspecified], and [style] has no color set, | ||
* this will be [LocalContentColor]. | ||
* @param style Style configuration for the text such as color, font, line height etc. | ||
* @param textAlign The alignment of the text within the lines of the paragraph. | ||
* See [TextStyle.textAlign]. | ||
* @param followGap the width between end of each scrolling text and the start of the following one. | ||
* @param startGap the padding in [Dp] added before the [text]. | ||
* @param edgeGradientWidth the width of the fade out zone on the edges, so text isn't cut off | ||
* harshly. | ||
* @param marqueeDpPerSecond the speed of scrolling in dp per second. | ||
|
@@ -149,6 +268,7 @@ public fun MarqueeText( | |
style: TextStyle = LocalTextStyle.current, | ||
textAlign: TextAlign = TextAlign.Left, | ||
followGap: Dp = 96.dp, | ||
startGap: Dp = 0.dp, | ||
edgeGradientWidth: Dp = 16.dp, | ||
marqueeDpPerSecond: Dp = 64.dp, | ||
pauseTime: Duration = 4.seconds, | ||
|
@@ -161,15 +281,21 @@ public fun MarqueeText( | |
style = style, | ||
textAlign = textAlign, | ||
followGap = followGap, | ||
startGap = startGap, | ||
edgeGradientWidth = edgeGradientWidth, | ||
marqueeDpPerSecond = marqueeDpPerSecond, | ||
pauseTime = pauseTime, | ||
) | ||
} | ||
|
||
private class MarqueeController(edgeGradientWidth: Dp) { | ||
private class MarqueeController( | ||
startEdgeGradientWidth: Dp, | ||
endEdgeGradientWidth: Dp, | ||
startGap: Dp, | ||
) { | ||
|
||
var edgeGradientWidth: Dp by mutableStateOf(edgeGradientWidth) | ||
var startEdgeGradientWidth: Dp by mutableStateOf(startEdgeGradientWidth) | ||
var endEdgeGradientWidth: Dp by mutableStateOf(endEdgeGradientWidth) | ||
private var needsScrolling by mutableStateOf(false) | ||
private var contentWidth: Int by mutableStateOf(-1) | ||
|
||
|
@@ -197,18 +323,41 @@ private class MarqueeController(edgeGradientWidth: Dp) { | |
|
||
private val padding = object : PaddingValues { | ||
override fun calculateLeftPadding(layoutDirection: LayoutDirection): Dp = | ||
if (needsScrolling && layoutDirection == LayoutDirection.Ltr) edgeGradientWidth else 0.dp | ||
if (layoutDirection == LayoutDirection.Ltr) { | ||
if (startGap > 0.dp) { | ||
startGap | ||
} else if (needsScrolling) { | ||
startEdgeGradientWidth | ||
} else { | ||
0.dp | ||
} | ||
} else { | ||
0.dp | ||
} | ||
|
||
override fun calculateRightPadding(layoutDirection: LayoutDirection): Dp = | ||
if (needsScrolling && layoutDirection != LayoutDirection.Ltr) edgeGradientWidth else 0.dp | ||
if (layoutDirection != LayoutDirection.Ltr) { | ||
if (startGap > 0.dp) { | ||
startGap | ||
} else if (needsScrolling) { | ||
startEdgeGradientWidth | ||
} else { | ||
0.dp | ||
} | ||
} else { | ||
0.dp | ||
} | ||
|
||
override fun calculateTopPadding(): Dp = 0.dp | ||
override fun calculateBottomPadding(): Dp = 0.dp | ||
} | ||
val insideMarqueeModifier: Modifier = Modifier.padding(padding) | ||
|
||
private fun Modifier.drawFadeGradient() = this.drawWithCache { | ||
val width = edgeGradientWidth.toPx() | ||
val leftWidth = | ||
if (layoutDirection == LayoutDirection.Ltr) startEdgeGradientWidth.toPx() else endEdgeGradientWidth.toPx() | ||
val rightWidth = | ||
if (layoutDirection == LayoutDirection.Ltr) endEdgeGradientWidth.toPx() else startEdgeGradientWidth.toPx() | ||
// Create the brush here and leverage it within the onDrawWithContent block below | ||
// The brush will only be instantiated on first render and if the size of the composable | ||
// changes. Otherwise the same brush instance will be used. | ||
|
@@ -218,22 +367,22 @@ private class MarqueeController(edgeGradientWidth: Dp) { | |
Color.Black, | ||
), | ||
startX = 0f, | ||
endX = width, | ||
endX = leftWidth, | ||
) | ||
val rightBrush = Brush.horizontalGradient( | ||
listOf( | ||
Color.Transparent, | ||
Color.Black, | ||
), | ||
startX = size.width, | ||
endX = size.width - width, | ||
endX = size.width - rightWidth, | ||
) | ||
onDrawWithContent { | ||
drawContent() | ||
|
||
if (needsScrolling) { | ||
drawRect( | ||
size = Size(width, size.height), | ||
size = Size(leftWidth, size.height), | ||
topLeft = Offset( | ||
0f, | ||
0f, | ||
|
@@ -242,9 +391,9 @@ private class MarqueeController(edgeGradientWidth: Dp) { | |
blendMode = BlendMode.DstIn, | ||
) | ||
drawRect( | ||
size = Size(width, size.height), | ||
size = Size(rightWidth, size.height), | ||
topLeft = Offset( | ||
size.width - width, | ||
size.width - rightWidth, | ||
0f, | ||
), | ||
brush = rightBrush, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -54,6 +54,7 @@ android { | |
unitTests { | ||
isIncludeAndroidResources = true | ||
} | ||
animationsDisabled = true | ||
} | ||
|
||
buildTypes { | ||
|
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.
If we think the new form with separate startGap, startEdgeGradientWidth, endEdgeGradientWidth is the right general form, then we should either
a) Remove the old form.
b) Leave them for compatibility, maybe deprecated.
As in the old methods are gone, since you have changed the params, added startGap.