There are a lot of questions with regard to crossfading in Android, but they all include animations. My question is about crossfading using the OnPageChangeListener of a ViewPager.
I have a ViewPager which could have an unlimited number of views, but in practice uses about 6 or 7 views. Not much going on there.
Each View in the ViewPager has a background Bitmap which should be fixed and crossfade with the background of the next (or previous) View instead of scrolling along with the rest of the View.
To achieve this I decoupled the backgrounds and add to an ArrayList and assign them to ImageViews later. But since I don't want to risk the chance that my Activity will end up with numerous ImageViews I thought of the following structure:
<FrameLayout
android:id="@+id/backgroundContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/bottomImage"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="center" />
<ImageView
android:id="@+id/middleImage"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="center" />
<ImageView
android:id="@+id/topImage"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="center" />
</FrameLayout>
Then a OnPageChangeListener
is assigned to the ViewPager to assign the backgrounds to the ImageViews.
@Override
public void onPageSelected(int position) {
MyLog.i(TAG, "PAGE SELECTED: " + position);
if(position == 0) {
_bottomBackground.setImageBitmap(null);
_topBackground.setImageBitmap(_backgroundStack.get(position+1));
} else if (position == NUM_ITEMS-1) {
_bottomBackground.setImageBitmap(_backgroundStack.get(position-1));
_topBackground.setImageBitmap(null);
} else {
_bottomBackground.setImageBitmap(_backgroundStack.get(position-1));
_topBackground.setImageBitmap(_backgroundStack.get(position+1));
}
_middleBackground.setImageBitmap(_backgroundStack.get(position));
// Make the top front background transparent
_topBackground.setAlpha(0f);
_currentBackgroundPosition = position;
}
This works fine if I would've liked to just swap the backgrounds. I want the backgrounds to cross fade into each other while the user swipes the ViewPager. I've got the fade for a forward scroll working, but I don't understand why the fade for the backward scroll somehow doesn't give a good result. During a backward scroll the middle background should fade into the bottom background.
I'm afraid I'm missing something. I'm never changing the alpha of the bottom background, but the Log results always show the exact same value for getAlpha()
as for the middle background.
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if(_currentBackgroundPosition == position) {
// scroll forward
_topBackground.setAlpha(positionOffset)
} else {
//scroll backward
_middleBackground.setAlpha(positionOffset);
}
MyLog.i(TAG, "Bottom BackgroundAlpha: " + _bottomBackground.getAlpha());
MyLog.i(TAG, "Middle BackgroundAlpha: " + _middleBackground.getAlpha());
MyLog.i(TAG, "Top BackgroundAlpha: " + _topBackground.getAlpha());
}
And wait! There's one more thing I really am not able to figure out how to fix. Although the forward scroll fade is working. There's a super short flickering in the background. I assume this is happening because of way I set up the onPageSelected
method.
Is there another way how I can create/fix this behavior?