Centered View Pager со следующим и предыдущим предварительным просмотром и pagetransformer

Я реализую ViewPager, который показывает следующие и предыдущие элементы, а также анимирует переходы страниц с помощью ViewPager.PageTransformer. Он имеет эффект уменьшения и затухания. Для отображения следующего и предыдущего я использую отрицательный PageMargin, отступы на странице просмотра и clipToPadding как ложные. Вот как это выглядит

введите описание изображения здесь

Чего я и хочу. Проблема в том, что PageTransform использует левый край в качестве эталона, т.е. он показывает максимальное масштабирование, когда изображение касается левого края, а не когда оно находится в центре. Чтобы исправить это, я использовал смещение в коде следующим образом.

viewPager.setPageTransformer(false, new ViewPager.PageTransformer() {
        @Override
        public void transformPage(View page, float position) {
            if (position < -1) {
                page.setAlpha(0);
            } else if (position <= 1) {
                float scaleFactor = Math.max(0.7f, 1 - Math.abs(position - 0.14285715f));
                page.setScaleX(scaleFactor);
                page.setScaleY(scaleFactor);
                page.setAlpha(scaleFactor);
            } else {
                page.setAlpha(0);
            }
        }
    });

Я записал значение позиции, когда изображение находится в центре, и нашел смещение. Но это смещение работает только на устройствах xxhdpi. На xxxhdpi значение получается 0,12068965f. Кроме того, смещение изменяется, когда я меняю отступы в ViewPager. Кроме того, размер предварительного просмотра следующего и предыдущего изменений с dpi.

Вопрос

Как я могу рассчитать отступы, поля и особенно смещение, чтобы обеспечить согласованное поведение для разных точек на дюйм?

Код

Вот мой макет, где я добавляю viewpager и его дополнение

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        android:clipToPadding="false"
        android:paddingLeft="40dp"
        android:paddingRight="40dp">

    </android.support.v4.view.ViewPager>

    <Button
        android:id="@+id/swiper"
        android:text="Animate"
        android:layout_centerInParent="true"
        android:layout_below="@id/viewPager"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

Вот код инициализации вьюпейджера:

final ViewPager viewPager = ((ViewPager) findViewById(R.id.viewPager));
Resources r = getResources();
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 120, r.getDisplayMetrics());
viewPager.setPageMargin((int) (-1 * px));
viewPager.setOffscreenPageLimit(5);

person gitter    schedule 05.01.2016    source источник
comment
Вы получили какое-либо решение для этого   -  person Pallavi    schedule 08.09.2016
comment
@Паллави, да. Прошло несколько месяцев, а я не оставлял себе комментарий. Итак, хотя я не помню как, я обнаружил, что смещение равно paddingLeft / page.getMeasuredWidth(). Публикация полного кода трансформатора в качестве ответа.   -  person gitter    schedule 10.09.2016
comment
Спасибо за код..!   -  person Pallavi    schedule 10.09.2016
comment
Огромное спасибо @gitter   -  person Android    schedule 05.08.2018


Ответы (1)


Вот что у меня получилось:

public class ZoomFadeTransformer implements ViewPager.PageTransformer {

    private float offset = -1;
    private float paddingLeft;
    private float minScale;
    private float minAlpha;

    public ZoomFadeTransformer(float paddingLeft, float minScale, float minAlpha) {
        this.paddingLeft = paddingLeft;
        this.minAlpha = minAlpha;
        this.minScale = minScale;
    }

    @Override
    public void transformPage(View page, float position) {
        if (offset == -1) {
            offset = paddingLeft / page.getMeasuredWidth();
        }
        if (position < -1) {
            page.setAlpha(0);
        } else if (position <= 1) {
            float scaleFactor = Math.max(minScale, 1 - Math.abs(position - offset));
            page.setScaleX(scaleFactor);
            page.setScaleY(scaleFactor);
            float alphaFactor = Math.max(minAlpha, 1 - Math.abs(position - offset));
            page.setAlpha(alphaFactor);
        } else {
            page.setAlpha(0);
        }
    }
}

и я установил его как

viewPager.setPageTransformer(false, new ZoomFadeTransformer(viewPager.getPaddingLeft(), MIN_SCALE, MIN_ALPHA));
person gitter    schedule 10.09.2016
comment
Я только что попробовал ваше решение, но если я использую ZoomFadeTransformer, я больше не вижу предварительный просмотр следующей и предыдущей страницы. Вы столкнулись с той же проблемой? - person Katharina; 09.03.2017
comment
@gitter вам удалось сохранить предварительный просмотр предыдущей и следующей страниц? - person Raykud; 16.01.2018