Search code examples
android-fragmentsandroid-viewpagerandroid-toolbar

Animate Toolbar Logo / Title changes when using with ViewPager Fragments


I am using ViewPager to host two fragments in my main activity. One fragment is intended to show app logo and other one just title on the Toolbar. I am able to do that without any issue.

However, I want to animate these changes when I swipe from one fragment to another using swipe on ViewPager, like Fade out the logo and fade in the title.

Any clue or idea how can I do it.

Ok, as per Amir's suggestion I tried it using the below layout:

    <?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="wrap_content"
    android:layout_height="wrap_content">
<RelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:id="@+id/toolbar_logo_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:alpha="1"
        >
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/logo"
        android:id="@+id/toolbar_logo_image"
        android:alpha="1"
       />
    </RelativeLayout>

    <RelativeLayout
        android:layout_toRightOf="@id/toolbar_log_container"
        android:layout_alignWithParentIfMissing="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/toolbar_info_container"
        >
    <ImageView
        android:id="@+id/toolbar_profile_pic"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/one"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginRight="@dimen/value_12"
        />

    <android.support.v7.widget.AppCompatTextView
        android:id="@+id/toolbar_user_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="TextInfoName"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@+id/toolbar_profile_pic"
        android:layout_toEndOf="@+id/toolbar_profile_pic"
        android:layout_marginTop="@dimen/value_8"
        />
    <android.support.v7.widget.AppCompatTextView
        android:id="@+id/toolbar_user_detail"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="TextInfoWork"
        android:layout_below="@+id/toolbar_user_name"
        android:layout_toRightOf="@+id/toolbar_profile_pic"
        android:layout_toEndOf="@+id/toolbar_profile_pic"
        android:layout_alignBottom="@id/toolbar_profile_pic"
        />
    </RelativeLayout>

</RelativeLayout>
</android.support.v7.widget.Toolbar>

And it works ! But what if I would have to do it as per scroll position of the ViewPager. I tried placing the animation in

public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}

part of the code, but the animation runs uncontrollably, since this callback is called everytime once the scroll is started, irrespective of it is actually scrolled or not.


Solution

  • Finally, here's what I did to achieve the desired effect:

    mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
                private float prevPosition = 0.0f;
                @Override
                public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                    ///hold current position
                    if(prevPosition == 0) {
                        prevPosition = positionOffset;
                        return;
                    }
                    
                    ///check if prev position is equal to current one, avoid multiple calls
                    if(prevPosition == positionOffset) {
                        return;
                    }
                    
                    /// zero position check
                    if(prevPosition >= 0.9) {
                        if(positionOffset == 0.0f) {
                            Logger.log_error("Do not hide infoHolder");
                            return;
                        }
                    }
                    //update previous position
                    prevPosition = positionOffset;
                    
                    ///animate title text and logoholder accordingly
                    logoHolder.animate().translationX(logoHolder.getWidth() -positionOffset * logoHolder.getWidth()) .alpha(positionOffset).setDuration(0).start();
                    mTitleText.animate().translationX(- positionOffset * mTitleText.getWidth()).alpha(1.0f - logoHolder.getAlpha()).setDuration(0).start();
    
                }
    
                @Override
                public void onPageSelected(int position) {
                }
    
                @Override
                public void onPageScrollStateChanged(int state) {
                }
    });
    

    The above code resulted in a smooth transition b/w Logo and title text when fragments are scrolled inside viewpager.

    Posting the answer hoping this may help someone else.

    Thanks Amir for the guidance.