I was just messing around with creating a slidable...
# compose
m
I was just messing around with creating a slidable drawer with
ViewDragHelper
and noticed that this code has a lot of state and calbacks interacting with each other (for example see all the touch callbacks in
androidx.drawerlayout.widget.DrawerLayout
from androidx). I cannot fanthem how could such monstrosity be implemented with just composable functions. Will there be a way to create classes for views or some other way to properly manage complex views like this?
👆 1
k
assuming that it will be something like:
Copy code
val drawer = @Composable { Drawer {
  for(i in 0 until 3) {
    DrawerItem(icon = iconName, title = iconTitle)
  }
} 
}
and use it as the following:
Copy code
Scaffold(
  drawer = drawer
  body = @Composable { /* ... */ }
)
That is quite hypothetical.
if you look at how flutter does it, it might gives you a little idea how it might look in Compose. https://flutter.dev/docs/cookbook/design/drawer It is not that they copy flutter, but both of them a declarative UI framework so probably they do have similarities
ViewDragHelper
I had the leverage to avoid using this api but I presume they will provide a
GestureDetector
where we can update a Model with the detected swipe and calculate the percentage of the drawer
m
Yes, that is how you would use drawer.
But how would you create one?
l
which part exactly do you think would be difficult? It’s not a trivial component but it seems pretty doable to me, though not really “slack pseudo-code-able”. If there’s a part of it that feels intuitively impossible or hard to you, i’m happy to shed light on how I might approach that particular part of it?
m
Here are some issues I see: 1. Code organization. While View system is overkill for small views, it is good for managing complex views since all its methods are nicely contained inside class. I'm not sure how would that work for composable functions (I guess you would have to declare onTouch, onTouchIntercept etc. methods separately as private top level functions and pass all required state parameters into it?) 2. At the moment
ViewDragHelper
(or similar helper classes) is used as field. I guess this helper need to be converted into composable view later to allow for it to use state? How would we access it since composable functions do not return anything? For example, at the moment you have to get the touch callback, filter it if necessary and then pass it to
ViewDragHelper
. But with compose, I cannot pass it to VDH, because I don't have its instance. 3. Does compose have notion of view IDs? Since VDH works by calling back and checking whether view should be dragged on touch events.
l
Thanks for clarifying. I think I’m going to write a blog post on this type of thing, since there’s been a handful of questions around this recently and I didn’t think there would be. 1) not all logic needs to be contained within a composable function. it is pretty easy to build a model class that contains some of this stateful logic and it can create and maintain a lot of these things. your composable function can be quite a bit smaller and simpler as a result, and you can test the other pieces without ever composing a function if you want to. Fun fact, you can even make a composable operator invoke function on the model be your composable function 🙂. Keep in mind that a big mental model shift around composable functions is that composable functions have a special ability to “persist” data across invocations. This is how state and memo and stuff work. So you can hold on to things across invocations (like stateful models) and use them across invocations. 2) ViewDragHelper (or something like it) could easily just be one of the models i mentioned in (1). ie,
val vdh = memo { ViewDragHelper() }
and
vdh
will be the same instance across composes. 3) Compose has no specific notion of View IDs. If you are composing normal android views, you can pass ids into them (ie,
TextView(id=R.id.my_text_view)
), but this is just because TextView itself knows what view ids are. For Compose UI (ie, composables coming from androidx.ui.*) do not have such a notion, and APIs that we build around them will be structured in a way to avoid them since we think it goes against the grain / best practices of Compose’s architecture
m
so what would
vdh
from your example in 2 really be? Some sort of view type?
I see, so basically I would have model type (like
ViewDragHelper
) and composable function would just be bunch of callbacks that trigger this model class?