Skip to content

Instantly share code, notes, and snippets.

@dovahkiin98
Last active July 16, 2024 05:04
Show Gist options
  • Save dovahkiin98/85acb72ab0c4ddfc6b53413c955bcd10 to your computer and use it in GitHub Desktop.
Save dovahkiin98/85acb72ab0c4ddfc6b53413c955bcd10 to your computer and use it in GitHub Desktop.
A Jetpack Compose implementation of the `fadingEdge` effect.
import androidx.compose.foundation.ScrollState
import androidx.compose.material.MaterialTheme
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.debugInspectorInfo
import androidx.compose.ui.unit.Dp
fun Modifier.horizontalFadingEdge(
scrollState: ScrollState,
length: Dp,
edgeColor: Color? = null,
) = composed(
debugInspectorInfo {
name = "length"
value = length
}
) {
val color = edgeColor ?: MaterialTheme.colors.surface
drawWithContent {
val lengthValue = length.toPx()
val scrollFromStart = scrollState.value
val scrollFromEnd = scrollState.maxValue - scrollState.value
val startFadingEdgeStrength = lengthValue * (scrollFromStart / lengthValue).coerceAtMost(1f)
val endFadingEdgeStrength = lengthValue * (scrollFromEnd / lengthValue).coerceAtMost(1f)
drawContent()
drawRect(
brush = Brush.horizontalGradient(
colors = listOf(
color,
Color.Transparent,
),
startX = 0f,
endX = startFadingEdgeStrength,
),
size = Size(
startFadingEdgeStrength,
this.size.height,
),
)
drawRect(
brush = Brush.horizontalGradient(
colors = listOf(
Color.Transparent,
color,
),
startX = size.width - endFadingEdgeStrength,
endX = size.width,
),
topLeft = Offset(x = size.width - endFadingEdgeStrength, y = 0f),
)
}
}
fun Modifier.verticalFadingEdge(
scrollState: ScrollState,
length: Dp,
edgeColor: Color? = null,
) = composed(
debugInspectorInfo {
name = "length"
value = length
}
) {
val color = edgeColor ?: MaterialTheme.colors.surface
drawWithContent {
val lengthValue = length.toPx()
val scrollFromTop = scrollState.value
val scrollFromBottom = scrollState.maxValue - scrollState.value
val topFadingEdgeStrength = lengthValue * (scrollFromTop / lengthValue).coerceAtMost(1f)
val bottomFadingEdgeStrength = lengthValue * (scrollFromBottom / lengthValue).coerceAtMost(1f)
drawContent()
drawRect(
brush = Brush.verticalGradient(
colors = listOf(
color,
Color.Transparent,
),
startY = 0f,
endY = topFadingEdgeStrength,
),
size = Size(
this.size.width,
topFadingEdgeStrength
),
)
drawRect(
brush = Brush.verticalGradient(
colors = listOf(
Color.Transparent,
color,
),
startY = size.height - bottomFadingEdgeStrength,
endY = size.height,
),
topLeft = Offset(x = 0f, y = size.height - bottomFadingEdgeStrength),
)
}
}
@fargus9
Copy link

fargus9 commented Nov 20, 2022

Thanks for the fixes!

@EaseTheWorld
Copy link

For material3, I used default edgeColor to MaterialTheme.colorScheme.background.

@EaseTheWorld
Copy link

visibleItemsInfo.size in 0..1 should be before visibleItemsInfo.first()/last()
otherwise NoSuchElementException("List is empty.")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment