Background scrollview with image in a viewpager with parallax effect

from the CommonsWare Community archives

At September 23, 2021, 6:28pm, ivano_trocchietto asked:

Hi everyone, I am busy since one week to try to implement a four pages ViewPager2, that outside the classic implementation with some images and text, should have for design needs a background rectangular image on the background, that scrolls with a velocity different(slower) than the icons. I cannot achieve that in anyway with any approach.

My first approach was to creating a ScrollView that contains an image

this is the root layout(not the adapter):
>  <ScrollView
>         android:id="@+id/scrollView"
>         android:layout_width="match_parent"
>         android:layout_height="wrap_content"
>         android:scrollbars="none"
>         android:orientation="vertical"
>         app:layout_constraintStart_toStartOf="parent"
>         app:layout_constraintTop_toTopOf="parent">
> 
>         <ImageView
>             android:id="@+id/onboarding_background_iv"
>             android:layout_width="800dp"
>             android:layout_height="328dp"
>             android:scaleType="centerCrop"
>             android:scaleX="1"
>             android:scaleY="1"
>             android:adjustViewBounds="false"
>             android:src="@drawable/onboarding_background" />
>     </ScrollView>
> 
>     <androidx.viewpager2.widget.ViewPager2
>         android:id="@+id/onboarding_view_pager"
>         android:layout_width="match_parent"
>         android:layout_height="match_parent" 

And this is the Transformer where imageBackground tries to connect with the root layout
>  class PageTransformer : ViewPager2.PageTransformer {
>     private lateinit var iconIntoRectangle: View
>     private lateinit var rectangle: View
>     private lateinit var imageBackground: View
>     override fun transformPage(page: View, position: Float) {
>         iconIntoRectangle = page.onboarding_icon_inside_rectangle
>         rectangle = page.onboarding_rectangle_image_view
>         imageBackground =page.rootView.scrollView
>         page.apply {
> 
>             if (position <= 1 && position >= -1) {
>                 imageBackground.left =(position* (width / 4f)).toInt()
>                 iconIntoRectangle.translationX = position * (width / 2f)
>                 rectangle.translationX = position * (width / 2f)
>                // iconIntoRectangle.translationX = -position * (width / 4f)
>             }
>         }
>     }
> }
It does not work: althought he image is bigger than the screen,  when I scroll to the next viewpager view(from position 0 to 1 for instance) the background image restore to the initial part, instead to keep scrolling.

I have also tried to override the callback onScrollChanged but does not work properly , it scrolls but jumps after the scrollOffsetPixel reaches zero at the end of the page neither and to be honest I am  able to understand the mathematics behind the snippet i have literally copied because looks really esoteric for my level of knowledge, I tried to tweek it a bit changing some numbers, but cannot find documentation to understand the logic behind

Do you maybe know if there is a simple way to have a background image behiind a viewpager that scrolls with a different velocity than the icons on top? 

override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels)
Timber.i(“IVOXXX position :$position positionOffset:$positionOffset positionsOffsetPixels:$positionOffsetPixels”)
fun computeFactor(): Float =
(onboarding_background_iv.width/2 - onboarding_view_pager.width) / (onboarding_view_pager.width *
4).toFloat()//TODO 6-1
val x = ((onboarding_view_pager.width * position + positionOffsetPixels) * computeFactor())
val horizontalScroll = x.toInt() + onboarding_background_iv.width / 3
Timber.v(“IVOZZ horizontalView:$horizontalScroll”)

            scrollView.scrollTo(horizontalScroll, 0)
              //  onboarding_background_iv.left =horizontalScroll
        }
    })

At September 23, 2021, 10:54pm, mmurphy replied:

That sounds like a parallax effect, which I have never implemented. I know a bunch of people have done work in that area, though, so perhaps you can find something that will help. For example, several libraries in the Android Arsenal refer to parallax in their descriptions, including a (somewhat outdated) parallax pager.


At September 24, 2021, 7:44am, ivano_trocchietto replied:

thanks Mark, I looked into the library before to go and was decided to not go in the spike time, it means design will have to wait a bit;) I guess this could be an hack android - Sync Two ScrollView - Stack Overflow but never mind, is great opportunity to familiarize with math of the view, that i like although the time constraints.


At September 24, 2021, 9:27am, ivano_trocchietto replied:

is working now, had just to tweek the formula in onChangeScrolled with a minus in the coefficient, and change the number at the divisor and using scrollTo to the scrollView instead of the imageView.left. Sometimes taking a bit of distance from a problem with fresh mind the day before it helps.Was a nice experience