Android Question Parallax? Like CLVHeader - but different...

wimpie3

Well-Known Member
Licensed User
Longtime User
I'm currently playing around with xCustomListView to make B4X compatible listviews.

Has anyone already created a parallax image scroll like the one shown here in this video?

I have been looking at CLVHeader , but the listview scrolls BEHIND the image in that example.

If you look closely to the video, you will see that in the case of parallax scrolling, the listview scrolls ABOVE the image. I think this needs some kind of "empty" or "transparent" cells in the listview, but that does not seem to be supported.

I've tried playing with CustomListView1.AsView.BringToFront but that doesn't seem to help either.
 

William Lancee

Well-Known Member
Licensed User
Longtime User
I experimented a bit with the CLVHeader example.

I believe that if you make two small changes it will work as you describe. At least in first phase of animation.

B4X:
'In Main
Sub pnlTop_Click
    CLVHeader1.Resize(100%x, 100%y)        'ADD THIS
    CustomListView1.ScrollToItem(0)
End Sub

'In CLVHeader
Public Sub ScrollChanged (Position As Int)
    Dim delta As Int = (Position - ScrollGestureStartPosition) / 3
    delta = Max(-20dip, Min(20dip, delta))
    ScrollGestureStartPosition = 1            'CHANGE THIS
    Dim NewSVTop As Int = Min(MaxHeaderHeight, Max(mCLV.sv.Top - delta, MinHeaderHeight))
    If mCLV.sv.Top <> NewSVTop Then
        SetSVTop(NewSVTop)
    End If
End Sub

EDIT: The above disables to down scroll. So back to the drawing board.
 
Last edited:
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
After quite a lot more experimenting (I like a challenge), it was clear that when the list is at its top position, no more up scrolling events can be generated.
That seems obvious now, but it means that if you want to scroll to the top before shrinking the header, another approach is needed.

I modified the layout to put the pnlTop above the CLV, so that they are not overlapping. Then I put a transparent panel covering the CLV.
This way I can monitor touch events, which function sometimes to shrink/enlarge the header and other times to send a scroll offset to the CVL.

It seems somewhat wonky but it works in my test. The following does NOT need the CVLHeader class. But you'll still have to figure out how to capture the itemClick event with the touchPanel masking the CLV. Perhaps by making the touchPanel Invisible when the touch action is "Up".

B4X:
Sub Process_Globals
    Private xui As XUI
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

    Private CustomListView1 As CustomListView
    Private pnlTop As B4XView
    Private lblHeader As B4XView
    Private ImageView1 As B4XView
    Private busy As Boolean
    Private touchPanel As Panel

    Private lastAction As Int
    Private inPanelY As Float
    Private origHeight As Float
    Private origTextSize As Float
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("1")
    origHeight = pnlTop.height
    origTextSize = lblHeader.TextSize
    ImageView1.Height = origHeight
    CustomListView1.DefaultTextBackgroundColor = Colors.White
    pnlTop.Visible = True
    pnlTop.SendToBack
    For i = 1 To 100
        CustomListView1.AddTextItem("Item #" & i, "")
    Next
End Sub

Private Sub touchPanel_Touch (Action As Int, X As Float, Y As Float)
    If Action = 1 Then
        lastAction = 0
    Else if lastAction = 0 Then
        inPanelY =  Y
        lastAction = Action
    Else
        If busy = True Then Return
        busy = True
        Dim change As Float = Y - inPanelY
        If touchPanel.top = 80dip Then
            If change < 0 Then
                CustomListView1.sv.ScrollViewOffsetY = - change
            Else
                touchPanel.top = 80dip + change
            End If
        Else
            touchPanel.Top = touchPanel.Top  + change
            If change < 0 And touchPanel.top < 80dip Then
                touchPanel.top = 80dip
            Else If change > 0 And touchPanel.top > origHeight Then
                    touchPanel.top = origHeight
            End If
            CustomListView1.GetBase.SetLayoutAnimated(0, 0, touchPanel.Top, touchPanel.Width, Activity.Height - touchPanel.Top)
            CustomListView1.Base_resize(touchPanel.Width, Activity.Height - touchPanel.Top)
            pnlTop.Height = touchPanel.Top
            ImageView1.Height = touchPanel.Top
            lblHeader.Top = pnlTop.Height/2 - lblHeader.height/2
            lblHeader.TextSize = origTextSize - (1 - pnlTop.Height / origHeight) * 30
            Activity.Invalidate
        End If
    End If
    busy = False
End Sub


Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub
 
Last edited:
Upvote 0

wimpie3

Well-Known Member
Licensed User
Longtime User
I will test it out, thanks for your help! It does 'seem' easy to do at first but it's quite a challenge, isn't it?

EDIT: tested it out, and it's not the same effect as in the clip I first posted... I've played around with it myself for a few hours, and I don't think it is possible to recreate that effect.
 
Last edited:
Upvote 0
Top