Skip to content

Commit

Permalink
Use indication for focus scaling
Browse files Browse the repository at this point in the history
  • Loading branch information
nielsvanvelzen committed Sep 17, 2023
1 parent e935792 commit c16fd9d
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package nl.ndat.tvlauncher.ui.component.card

import android.content.Intent
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.clickable
import androidx.compose.foundation.focusable
import androidx.compose.foundation.indication
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
Expand All @@ -22,7 +24,6 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.scale
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.colorResource
Expand All @@ -32,6 +33,7 @@ import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage
import nl.ndat.tvlauncher.R
import nl.ndat.tvlauncher.data.entity.App
import nl.ndat.tvlauncher.ui.indication.FocusScaleIndication
import nl.ndat.tvlauncher.util.createDrawable
import nl.ndat.tvlauncher.util.ifElse

Expand All @@ -44,14 +46,15 @@ fun AppCard(
val context = LocalContext.current
val image = remember { app.createDrawable(context) }
var focused by remember { mutableStateOf(false) }
val scale = animateFloatAsState(if (focused) 1.125f else 1.0f)
val interactionSource = remember { MutableInteractionSource() }

val launchIntentUri = app.launchIntentUriLeanback ?: app.launchIntentUriDefault

Column(
modifier = modifier
.width(160.dp)
.scale(scale.value)
.focusable(true, interactionSource)
.indication(interactionSource, FocusScaleIndication(1.125f))
.onFocusChanged { focused = it.hasFocus }
.clickable(enabled = launchIntentUri != null) {
if (launchIntentUri != null) context.startActivity(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package nl.ndat.tvlauncher.ui.component.card

import android.content.Intent
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.clickable
import androidx.compose.foundation.focusable
import androidx.compose.foundation.indication
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.aspectRatio
Expand All @@ -23,7 +25,6 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.scale
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.colorResource
Expand All @@ -33,6 +34,7 @@ import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage
import nl.ndat.tvlauncher.R
import nl.ndat.tvlauncher.data.entity.ChannelProgram
import nl.ndat.tvlauncher.ui.indication.FocusScaleIndication
import nl.ndat.tvlauncher.util.ifElse

@OptIn(ExperimentalFoundationApi::class)
Expand All @@ -43,12 +45,13 @@ fun ChannelProgramCard(
) {
val context = LocalContext.current
var focused by remember { mutableStateOf(false) }
val scale = animateFloatAsState(if (focused) 1.125f else 1.0f)
val interactionSource = remember { MutableInteractionSource() }

Column(
modifier = modifier
.width(90.dp * (program.posterArtAspectRatio?.floatValue ?: 1f))
.scale(scale.value)
.focusable(true, interactionSource)
.indication(interactionSource, FocusScaleIndication(1.125f))
.onFocusChanged { focused = it.hasFocus }
.clickable(enabled = program.intentUri != null) {
if (program.intentUri != null) context.startActivity(
Expand Down
39 changes: 39 additions & 0 deletions app/src/main/kotlin/nl/ndat/tvlauncher/ui/indication/scale.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package nl.ndat.tvlauncher.ui.indication

import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.Indication
import androidx.compose.foundation.IndicationInstance
import androidx.compose.foundation.interaction.FocusInteraction
import androidx.compose.foundation.interaction.InteractionSource
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.graphics.drawscope.scale

private class ScaleIndicationInstance(
private val scale: Float,
) : IndicationInstance {
override fun ContentDrawScope.drawIndication() {
scale(scale) {
this@drawIndication.drawContent()
}
}
}

class FocusScaleIndication(
private val focusedScale: Float,
) : Indication {
@Composable
override fun rememberUpdatedInstance(interactionSource: InteractionSource): IndicationInstance {
val interaction by interactionSource.interactions.collectAsState(initial = null)
val currentScale = when (interaction) {
is FocusInteraction.Focus -> focusedScale
else -> 1.0f
}

val scale by animateFloatAsState(currentScale)
return remember(scale) { ScaleIndicationInstance(scale) }
}
}

0 comments on commit c16fd9d

Please sign in to comment.