https://kotlinlang.org logo
p

prat

03/26/2020, 3:03 AM
I made an expand-collapse button. sharing it here in case it might be useful for anyone. (It's easy & fun to make with Compose!) https://gist.github.com/pt2121/3fa9e0e3e2659171102d752b33d1b1c7
👍 14
z

Zach Klippenstein (he/him) [MOD]

03/26/2020, 4:02 AM
under 150 lines for the whole thing, nice!
👍 1
s

shikasd

03/26/2020, 10:25 AM
Is the rest of the demo (fullscreen one in gist) done in compose as well?
p

prat

03/26/2020, 1:35 PM
Yes, the rest of the demo is also done in compose. The code is still very hacky tho - especially, the transition animation.
s

shikasd

03/26/2020, 1:51 PM
Can you share it? Despite being hacky, it looks incredible :)
c

caelum19

03/26/2020, 2:32 PM
that's so cool
p

prat

03/26/2020, 3:03 PM
just made the repo public https://github.com/pt2121/kramer any feedback is welcome
l

Leland Richardson [G]

03/26/2020, 3:48 PM
just curious - did you find that the
Box
here was required? It seems like it wouldn’t be since Canvas is basically just a child-less box with a draw call
very nice though. this code made me smile 🙂
p

prat

03/26/2020, 4:02 PM
Thanks, Leland. The
Box
is a workaround to increase there tap target size. not sure if there is a proper way to do this?
l

Leland Richardson [G]

03/26/2020, 4:07 PM
i think there is a
TouchSlop
notion, but i’m not familiar with it. though if you’re just using a
Box
right now i think just adding a
LayoutPadding
modifier to the canvas would be sufficient
👍 1
cc @Shep Shapard
p

prat

03/26/2020, 4:11 PM
ah, I didn't think about adding
LayoutPadding
. will try that
l

Leland Richardson [G]

03/26/2020, 4:56 PM
there is a simple animate API that will be coming out (or is out already? I can never remember). I tweaked your code a bit to show you how I might do this a bit simpler:
Copy code
@Composable
fun ExpandCollapseButton(
  up: Boolean,
  onStateChange: (Boolean) -> Unit,
  modifier: Modifier = Modifier.None,
  animationDuration: Int = 200,
  color: Color = MaterialTheme.colors().secondary
) {
  Box(modifier) {
    Ripple(bounded = false) {
      Caret(
        LayoutPadding(14.dp) + 
        ContentGravity.Center + 
        LayoutSize(20.dp) + 
        OnClick {
          onStateChange(!up)
        }
        up, 
        color, 
        animationDuration
      )
    }
  }
}

@Composable
private fun Caret(
  modifier: Modifier,
  up: Boolean,
  activeColor: Color,
  animationDuration: Int
) {
  val strokeWidthDp = 3.dp
  val paint = remember {
    Paint().apply {
      isAntiAlias = true
      strokeCap = StrokeCap.round
      color = activeColor
      style = PaintingStyle.stroke
    }
  }

  // simpler animation api for simple transitions
  // return value will be animated between 1f and 0f. It's just a Float.
  val t = animate(if (up) 1f else 0f, animationDuration)
  val animatedYOffset = lerp(0f, 1f, t) // equivalent to just `t`, but you get the idea
  val fraction = lerp(-1f, 1f, t)
  
  Canvas(modifier) {
    val strokeWidth = strokeWidthDp.toPx().value
    paint.strokeWidth = strokeWidth
    val height = size.height.value / 4
    val x = size.height.value / 4
    val yOffset = (size.height.value - height) / 2
    val path = Path()

    path.moveTo(x, yOffset + height * animatedYOffset)
    path.relativeLineTo(x, -height * fraction)
    path.relativeLineTo(x, height * fraction)

    drawPath(path, paint)
  }
}
z

Zach Klippenstein (he/him) [MOD]

03/26/2020, 5:18 PM
This animation API is so nice to reason about, it’s so easy to just animate everything. It actually makes me excited about writing custom animations 😂
😂 1
😁 1
1
🙏 1
p

prat

03/26/2020, 5:52 PM
Yeah, Zach. I really like the API too. Thanks for the tweaks Leland.
t

Thiago

03/26/2020, 6:09 PM
Nice transitions. The app looks nice too. Congrats
🙏 1
l

Leland Richardson [G]

03/26/2020, 6:11 PM
cc @Nader Jawad is there a recommended way that we can have the code above avoid the
Paint
allocation?
t

Thiago

03/26/2020, 6:15 PM
@Leland Richardson [G] on your code above, the
OnClick
is a modifier?
d

Doris Liu

03/26/2020, 6:15 PM
BTW, the
animate
API that @Leland Richardson [G] mentioned above is available to use, since a couple of releases ago. Here is the API doc.
👍 1
🙏 1
l

Leland Richardson [G]

03/26/2020, 6:16 PM
yeah, that is coming. not sure what is released yet or not
it’s easier for me to just keep track of where things are headed than keeping track of where everything currently is 🙂 sorry, that means this code sample might not work verbatim
p

prat

03/26/2020, 6:47 PM
Doris, I'll def check it out. Thanks, all