In Compose for Wear OS Alpha 14 now, the `offset` ...
# compose-wear
y
In Compose for Wear OS Alpha 14 now, the
offset
of
ScalingLazyListItemInfo
are either related aligned to the centre of the viewport or to the top edge either from center or edge of a list item with anchorType
ScalingLazyListAnchorType.ItemCenter
or
ItemStart
while initialising the ScalingLazyColumn, the option of offset to its initial position of Alpha 13 are now gone. How can I detect that the ScalingLazyColumn has been scrolled up e.g. 15dp?
In Alpha 13, I can do something like
Copy code
val listState = rememberScalingLazyListState()        
        Scaffold(
            timeText = {
                val itemInfoList = listState.layoutInfo.visibleItemsInfo
                // the first element is scrolled up more than 15dp, deactivate the Time Text
                if (itemInfoList.isNotEmpty()
                    && itemInfoList[0].index == 0 // the first visible index is the first element
                    && itemInfoList[0].offset >= -15 // the first element is scrolled up less than 15dp
                ) {
                    // show time text
                    TimeText()
                }
            },
and with Alpha 14, I would need to cache or copy the first
listState.centerItemScrollOffset
which is a lazy property. Any hint of this would be grateful.
I managed to initialize the
ScalingLazyListState
with initial values and test
centerItemScrollOffset
against the initial offset value. But still I am not quite happy with this solution, since I will need to compute these initial value by myself according to Layout Dimension to get whether a
ScalingLazyColumn
has been scrolled up 15dp.
Copy code
val initCenterItemOffset = -21
        val initCenterItemIdx = 1

        val listState: ScalingLazyListState = rememberScalingLazyListState(
            initialCenterItemIndex = initCenterItemIdx,
            initialCenterItemScrollOffset = initCenterItemOffset
        )

        Scaffold(
            timeText = {
                if (listState.centerItemIndex == initCenterItemIdx
                    && listState.centerItemScrollOffset <= initCenterItemOffset + 15) { // scroll up 15dp and deactivate Time
                    TimeText()
                }
What I would like to achieve is to hide the TimeText in Scaffold, should the Items in ScalingLazyColumn collides with TimeText view.
j
Determining if something has collided with the time text is not really possible in a generic way - however for your use case it should be possible. You can use the initial center item and offset to place the items. As you say you can use the change in offset to the centralItem and centralOffset as the trigger to work out when to scroll away the timetext - I managed to do this fine in some examples
We considered whether generic collision detection was feasible, desirable and achievable and I can't think of a good generic way of doing it as there are many factors such as the size of the time text (if it was long enough it could cover most/all of the screen), internationalisation meaning that the size of the time text will vary, screen size meaning that the arc that the time text will make is not possible t determine up front, etc. etc.
BTW you mentioned anchor type earlier and I want to clarify one think. The offsets are always with respect to the center of the viewport. The Edge anchor type is about whether the Edge or Center of the list items is aligned to the center of the viewport. Items are never aligned to the Edge of the viewport
y
@John Nichol Thanks for mention
Copy code
The Edge anchor type is about whether the Edge or Center of the list items is aligned to the center of the viewport
I didn’t know this, now the number of offset makes sense. A generic collision detection seems really difficult at this point. Can you give me a hint of how to get the list item dimensions from the
ScalingLazyListItemInfo
, I thought of doing some calculation with screenHeights and the dimensions (height and width) of list items. The anchor type controls whether the Edge or Center of the list items is aligned to the center of the viewport, the list item dimension should be available right?
y
Is there a modifier that gives the absolute position/offset of an element on the display (after layout)? Could we use that on the first item to see if it's shown and below the timetext area?
j
If the
ScalingLazyList
is taking the whole screen (which I think will usually be the case) then I think all you need to know if the list height/screen height and then you can easily convert offsets to absolute values - offset + height /2f. If you are taking up part of the screen then you might need onGloballyPositioned on the list instead and do some slighly more interesting but still really simple maths instead. I think I would avoid onGloballyPositioned() on the list items - better to observe the state than have callbacks.
y
If I go with
ItemStart
for `anchorType`and then use
offset + screenHeight /2f
to get the absolute value will work for this first item with TimeText example. But we have also the item expansion via click event for text message. This means the view dimension of an item can change in run time. It would be great also be able to get the view dimension info from the State? But I don’t know how to get this item view dimension in runtime.
j
you can use onSizeChanged() Modifier on the list items you care about to know when its size changes
y
Ah.. I got it now. I can also subtract from the offset of previous Item to get the Item view dimension.