Пользовательский вид изображения теряет состояние на Зефир - PullRequest
0 голосов
/ 10 марта 2019

Я использую библиотеку PhotoView в своем проекте Android. Проект содержит SaveStatePhotoView , который используется для сохранения состояния (уровень масштабирования, положение) представления изображения при изменениях конфигурации (поворот, ...).

// SaveStatePhotoView.java

@Override
protected void onRestoreInstanceState(Parcelable state) {
    if (!(state instanceof SavedState)) {
        super.onRestoreInstanceState(state);
        return;
    }

    final SavedState ss = (SavedState) state;
    super.onRestoreInstanceState(ss.getSuperState());

    getViewTreeObserver().addOnGlobalLayoutListener(
        new ViewTreeObserver.OnGlobalLayoutListener() {

        @Override
        public void onGlobalLayout() {
            restoreSavedState(ss);
            getViewTreeObserver().removeGlobalOnLayoutListener(this);
        }
    });
}

Вид работает должным образом на Android 7.1.1 и Android 9.
На Android 6.0.1 состояние потеряно : при повороте устройства представление изображения сбрасывается в исходное состояние.

Я подготовил простой проект , чтобы продемонстрировать проблему. Обратите внимание, что я специально использую PhotoView 1.3.1 , потому что в настоящее время я не могу включить транзитивные androidx зависимости.

1 Ответ

1 голос
/ 14 марта 2019

NB Похоже, что это не проблема с PhotoView версии 2.3.0.

PhotoView подвергается двум разметкам при воссоздании дляAPI 23 и ниже.Для API 24+ существует только один проход макета.Что происходит при двух проходах, так это то, что масштаб (матрица), который восстанавливается в onRestoreInstanceState() из SaveStatePhotoView, сбрасывается.В вашем коде вы удаляете прослушиватель глобального макета после первого прохода, поэтому, когда матрица сбрасывается на втором проходе макета, вы не перехватываете его.Для API 24+ проходит только один проход, и масштаб восстанавливается и не сбрасывается.Вот почему вы видите проблему для API 23, а не для 24.

Я думаю, что реальное исправление в PhotoView .Ваниль ImageView также проходит два прохода макета, поэтому я не думаю, что дополнительный проход макета - это то, что PhotoView вызывает.Однако я считаю, что PhotoView неправильно обрабатывает матрицу масштабирования для определенных API.

Вы можете решить эту проблему, установив масштаб на втором проходе для API 24+, выполнив что-то подобное:

@Override
protected void onRestoreInstanceState(Parcelable state) {
    if (!(state instanceof SavedState)) {
        super.onRestoreInstanceState(state);
        return;
    }

    final SavedState ss = (SavedState) state;
    super.onRestoreInstanceState(ss.getSuperState());

    getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        private int invocationCount = 0;

        // Only one layout pass for M and up. Otherwise, we'll see two and the
        // scale set in the first pass is reset during the second pass, so the scale we
        // set doesn't stick until the 2nd pass.
        @Override
        public void onGlobalLayout() {
            setScale(Math.min(ss.scale, getMaximumScale()), getWidth() * ss.pivotX,
                    getHeight() * ss.pivotY, false);

            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M || ++invocationCount > 1) {
                getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
        }
    });
}

Предыдущее основано на прилагаемом демонстрационном приложении, работающем PhotoView версия 1.3.1.

...