0

我在我的 Android 项目中使用PhotoView库。该项目包含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依赖项。

4

1 回答 1

1

注意这似乎不是PhotoView 2.3.0 版的问题。

为 API 23 及更低版本重新创建PhotoView时会经历两种布局。对于 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 版的演示应用程序。

于 2019-03-14T13:42:41.470 回答