页面滑动监听器 alpha 交叉淡入淡出

9
在Android中,关于交叉淡入淡出有很多问题,但它们都包括动画。我的问题是关于使用ViewPager的OnPageChangeListener进行交叉淡入淡出。
我有一个ViewPager,它可以拥有无限数量的视图,但在实际使用中只使用了大约6或7个视图。没有太多的事情发生。
ViewPager中的每个视图都有一个背景位图,应该固定并与下一个(或前一个)视图的背景进行交叉淡入淡出,而不是随着其余视图一起滚动。
为了实现这一点,我将背景解耦并添加到ArrayList中,稍后再将它们分配给ImageViews。但是,由于我不想冒险让我的Activity最终拥有众多的ImageViews,因此我考虑了以下结构:
<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>

然后,将一个 OnPageChangeListener 分配给 ViewPager,以将背景分配给 ImageView。
@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;
}

这个方案可以很好地实现背景交换。我希望在用户滑动ViewPager时,背景可以淡入淡出。我已经成功实现了向前滚动的淡入效果,但是我不明白为什么向后滚动的淡入效果总是不理想。在向后滚动期间,中间的背景应该淡入到底部的背景中。
我担心我漏掉了什么。我从未改变底部背景的alpha值,但Log结果始终显示与中间背景相同的getAlpha()值。
@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());
}

等等!还有一件事情我真的无法解决。虽然前向滚动淡出效果可以实现,但是背景会出现极短暂的闪烁。我推测这是由于我设置的onPageSelected方法造成的。

是否有其他方法来创建/修复这种行为?

1个回答

30

ViewPager.PageTransformer 是你的好伙伴。我将采用不同的方法来实现你所尝试过的效果,但它将得到你想要的结果 - 左右滑动可切换内容,但两个背景图像之间会淡出而不会移动。

ViewPager 中的每个 Fragment 将具有以下布局:

<?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>

你将会创建一个PageTransformer,根据滑动的位置来操作布局:

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
        }
    }
}

最后将这个PageTransformer与您的ViewPager连接起来:

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

我已在现有应用程序中进行了测试,并且只要片段布局具有透明背景,它就可以正常工作。


你让我的一天都变得美好了!我已经在独立模式下测试通过了,现在将把它应用到我的项目中。谢谢! - StingRay5
太好了,很高兴能帮到你。感谢你的慷慨奖励。 - myanimal
你帮我省了很多时间。客户催得紧啊!谢谢,伙计! - andrea.rinaldi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接