Android- How to perform image scaling based on the scroll direction of the NestedScrollView?

35 views Asked by At

I'm new at android app development and trying to get the image scalling animation/effect based on the direction of the scroll like in this video.Please provide kotlin code if needed.Thanks in advance[Here is the effect I want:](https://i.stack.imgur.com/XFEhv.gif)

Here is my xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:fitsSystemWindows="true">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appBarLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/black">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsingToolbarLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:contentScrim="@color/transparent"
            app:layout_scrollFlags="scroll|enterAlwaysCollapsed">

            <ImageView
                android:id="@+id/scrollingImageView"
                android:layout_width="match_parent"
                android:layout_height="360dp"
                android:alpha="0.7"
                android:src="@drawable/live_events_category_img"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <androidx.appcompat.widget.Toolbar
                android:layout_width="match_parent"
                android:layout_height="70dp"
                android:background="@color/transparent"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="1"
                app:layout_scrollFlags="exitUntilCollapsed">

            </androidx.appcompat.widget.Toolbar>
        </com.google.android.material.appbar.CollapsingToolbarLayout>
    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView
        android:id="@+id/nestedScrollView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:animateLayoutChanges="true"
        android:background="@color/black"
        android:isScrollContainer="true"
        android:paddingStart="10dp"
        android:paddingEnd="10dp"
        android:scrollbars="none"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
    </androidx.core.widget.NestedScrollView>

</androidx.coordinatorlayout.widget.CoordinatorLayout>
1

There are 1 answers

0
Smit Patel On

After long research I figure out that we can achieve this effect by calling addOnOffsetChangedListener on the appBarLayout which will give us the offset value for each scrollposition based on which we can perform calculation on scaling parameter of the imageview as need. Here is what I added in the kotlin file whereas the xml remain the same:

var isCollapsed = false
var scaleFactor = 1.0f // Initialize the scale factor
var lastVerticalOffset = 0
binding.appBarLayout.addOnOffsetChangedListener { appBarLayout, verticalOffset ->
// Calculate the total scroll range of the CollapsingToolbarLayout
val totalScrollRange = appBarLayout.totalScrollRange

// Calculate the percentage of collapse (0 to 1)
val collapseRatio = -verticalOffset.toFloat() / totalScrollRange.toFloat()

// Calculate the target scale factor based on the collapse ratio
// Adjust the scaleFactor range as needed
val targetScaleFactor = 1.0f - collapseRatio * 0.5f

// Use ValueAnimator to smoothly interpolate the scale factor
val animator = ValueAnimator.ofFloat(scaleFactor, targetScaleFactor)
animator.duration = 100 // Adjust the duration as needed
animator.addUpdateListener { animation ->
    val animatedValue = animation.animatedValue as Float

    // Apply the interpolated scale factor to the ImageView
    binding.scrollingImageView.scaleX = animatedValue
    binding.scrollingImageView.scaleY = animatedValue
}
animator.start()

// Update the scale factor
scaleFactor = targetScaleFactor

// Check if the CollapsingToolbarLayout is fully collapsed
if (verticalOffset == -totalScrollRange) {
    if (!isCollapsed) {
        // The CollapsingToolbarLayout is now fully collapsed
        // Perform actions or call methods here
        isCollapsed = true
    }
} else {
    // The CollapsingToolbarLayout is not fully collapsed
    isCollapsed = false
}

// Update the last vertical offset
lastVerticalOffset = verticalOffset
}