OnPageChangeListener альфа-затенение

Есть много вопросов, касающихся плавного затухания в Android, но все они включают анимацию. Мой вопрос о кроссфейдинге с использованием OnPageChangeListener ViewPager.

У меня есть ViewPager, который может иметь неограниченное количество просмотров, но на практике использует около 6 или 7 просмотров. Не так много там происходит.

Каждый вид в ViewPager имеет фоновое растровое изображение, которое должно быть зафиксировано и затемнено с фоном следующего (или предыдущего) вида вместо прокрутки вместе с остальной частью вида.

Чтобы добиться этого, я отделил фоны и добавил их в ArrayList, а позже назначил их для ImageViews. Но так как я не хочу рисковать шансом, что моя активность закончится многочисленными 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 для назначения фонов для 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;
}

Это прекрасно работает, если бы я хотел просто поменять местами фон. Я хочу, чтобы фоны переходили друг в друга, пока пользователь перелистывает ViewPager. У меня затухание для прокрутки вперед, но я не понимаю, почему затухание обратной прокрутки как-то не дает хорошего результата. Во время обратной прокрутки средний фон должен исчезнуть на нижнем фоне.

Боюсь, я что-то упустил. Я никогда не меняю альфа нижнего фона, но результаты журнала всегда показывают одно и то же значение для 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 ответ

Решение

ViewPager.PageTransformer твой друг. Я собираюсь использовать другой подход к тому, что вы пытались, но это приводит к тому, что я понимаю, чтобы скрыть желаемый результат - смахивание влево / вправо смахивает контент, но затухает между двумя фоновыми изображениями, которые не перемещаются.

каждый Fragment в ViewPager будет иметь такой макет:

<?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());

Я проверил его в существующем приложении, и оно работает хорошо, пока макеты фрагментов имеют прозрачный фон.

Другие вопросы по тегам