Alpha Cross Fading OnPageChangeListener

There are many questions regarding crossfading in Android, but they all include animation. My crossfade question is using OnPageChangeListener from ViewPager.

I have a ViewPager that can 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 that needs to be locked and focused with the background of the next (or previous) view instead of scrolling along with the rest of the view.

To do this, I separated the backgrounds and added them to the ArrayList and assigned them ImageViews later. But since I do not want to risk that my activity will end with numerous ImageViews, I thought about 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 for 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 great if I just wanted to change the backgrounds. I want the backgrounds to intersect with each other while the user views the ViewPager. I have an extinction for working with forward scrolling, but I don’t understand why the disappearance of scrolling backwards somehow does not give a good result. During backward scrolling, the middle background should disappear in the background.

I'm afraid I missed something. I never change the background alpha, but the log results always show the 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 is one more thing that I really cannot figure out how to fix. Although the direct scroll scroll works. A very short flicker flashed in the background. I assume this is due to the way I configured the onPageSelected method.

Is there any other way I can create / fix this behavior?

+8
android scroll cross-fade
source share
1 answer

ViewPager.PageTransformer is your friend. I am going to use a different approach to what you tried, but this leads to what I understand, to sleep with your desired result - left / right scrolling through the content, but disappears between two background images that don't move.

Each Fragment in the ViewPager will have this layout:

 <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/image_view" android:layout_height="match_parent" android:layout_width="match_parent" android:scaleType="center" /> <LinearLayout android:id="@+id/content_area" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- content goes here --> </LinearLayout> </FrameLayout> 

And you will create a PageTransformer that manipulates the layout, depending on the position it held:

 public class CustomPageTransformer implements ViewPager.PageTransformer { public void transformPage(View view, float position) { int pageWidth = view.getWidth(); View imageView = view.findViewById(R.id.image_view); View contentView = view.findViewById(R.id.content_area); if (position < -1) { // [-Infinity,-1) // This page is way off-screen to the left } else if (position <= 0) { // [-1,0] // This page is moving out to the left // Counteract the default swipe view.setTranslationX(pageWidth * -position); if (contentView != null) { // But swipe the contentView contentView.setTranslationX(pageWidth * position); } if (imageView != null) { // Fade the image in imageView.setAlpha(1 + position); } } else if (position <= 1) { // (0,1] // This page is moving in from the right // Counteract the default swipe view.setTranslationX(pageWidth * -position); if (contentView != null) { // But swipe the contentView contentView.setTranslationX(pageWidth * position); } if (imageView != null) { // Fade the image out imageView.setAlpha(1 - position); } } else { // (1,+Infinity] // This page is way off-screen to the right } } } 

And finally plug this PageTransformer into your ViewPager :

 mViewPager.setPageTransformer(true, new CustomPageTransformer()); 

I tested it in an existing application and it works well as long as the fragment layouts have a transparent background.

+25
source share

All Articles