Search code examples
androidxmlscrollviewparallax

How can i change the scroll speed of elements in a scroll view


I currently have a basic xml file which structure is as follows:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#EDEDED"
    tools:context=".firstFragment">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/logoHome"
            android:layout_width="match_parent"
            android:layout_height="420dp"
            android:background="@drawable/baywatchstandard"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <ImageView
            android:id="@+id/waveHome"
            android:layout_width="match_parent"
            android:layout_height="420dp"
            android:background="@drawable/wave"
            android:layout_marginTop="180dp"
            app:layout_constraintTop_toTopOf="@id/logoHome"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintStart_toEndOf="parent"/>

    </androidx.constraintlayout.widget.ConstraintLayout>

</ScrollView>

I want to create a prallax effect where the "logoHome" ImageView moves slower than the "waveHome" ImageView when scrolled down. Is that possible? Any help would be appreciated :)


Solution

  • This literally took me 5 hours but i finally figured it out. It somehow is really hard to find a viable answer for this simple question so if someone stumbles across this, here you go :D

    private String event = "UP";
        private float mouseY = 0;
        private float lastY = 0;
        private Handler handler = new Handler();
    
        private ImageView element;  //ImageView can be replaced with everything that has setTranslation
    
        @SuppressLint("ClickableViewAccessibility")
        @Override
        public void onViewCreated(View view, Bundle savedInstanceState) {
    
            super.onViewCreated(view, savedInstanceState);
    
            element = view.findViewById(R.id.logoHome);
    
            Scroll scroll = new Scroll();
            scroll.run();
    
            ConstraintLayout page = view.findViewById(R.id.page);
            page.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent e) {
                    if(e.getAction() == MotionEvent.ACTION_MOVE) {
                        event = "MOVE";
                        mouseY = e.getY();
                    } else if (e.getAction() == MotionEvent.ACTION_DOWN) {
                        event = "DOWN";
                        lastY = e.getY();
                    } else {
                        event = "UP";
                    }
                    return true;
                }
            });
    
        }
    
        private class Scroll extends Thread{
            @Override
            public void run() {
                super.run();
                element.setTranslationY(scrollY(logoHome.getTranslationY(), -700, 0, (float) 0.15));
                lastY = lerp(lastY, mouseY, (float) 0.2);
                handler.postDelayed(this, 10);
            }
        }
    
    
    
        private float scrollY(float currentY, float min, float max, float scalar) {
    
            if(event.equals("MOVE") || event.equals("UP")){
    
                if((currentY + (mouseY - lastY)) < min) {
                    return lerp(currentY, min, (float) 0.2);
                }
                if((currentY + (mouseY - lastY)) > max){
                    return lerp(currentY, max, (float) 0.2);
                }
                return currentY + (mouseY - lastY) * scalar;
            } else {
                return currentY;
            }
        }
    
        float lerp(float a, float b, float f) {
            return a + f * (b - a);
        }
    

    Im sure this code could be improved quite a bit but im happy for now.