Android 自定义图像视图释放棉花糖上的状态

Android 自定义图像视图释放棉花糖上的状态,android,imageview,orientation-changes,onsaveinstancestate,onrestoreinstancestate,Android,Imageview,Orientation Changes,Onsaveinstancestate,Onrestoreinstancestate,我正在Android项目中使用这个库。项目包含用于在配置更改(旋转…)时保持图像视图状态(缩放级别、位置)的 在安卓7.1.1和安卓9上,该视图可以根据需要工作。 在Android 6.0.1上,状态丢失:当设备旋转时,图像视图重置为初始状态 我准备了一份报告来说明这个问题。请注意,我是故意使用的,因为我目前无法包含可传递的androidx依赖项。N.B这似乎不是PhotoView 2.3.0版的问题 PhotoView在为API 23及以下版本重新创建时,将经历两种布局。对于API 24+,只

我正在Android项目中使用这个库。项目包含用于在配置更改(旋转…)时保持图像视图状态(缩放级别、位置)的

在安卓7.1.1和安卓9上,该视图可以根据需要工作。
在Android 6.0.1上,状态丢失:当设备旋转时,图像视图重置为初始状态


我准备了一份报告来说明这个问题。请注意,我是故意使用的,因为我目前无法包含可传递的
androidx
依赖项。

N.B这似乎不是PhotoView 2.3.0版的问题

PhotoView在为API 23及以下版本重新创建时,将经历两种布局。对于API 24+,只有一个布局过程。当有两个过程时,在
SaveStatePhotoView
onrestoreinnstancestate()
中恢复的比例(矩阵)被重置。在您的代码中,您将在第一次传递之后删除全局布局侦听器,因此,当矩阵在第二次布局传递上重置时,您将无法捕获它。对于API 24+,只有一次通过,刻度恢复且不重置。这就是为什么您会看到API 23的问题,而不是API 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。

我找到了这个答案,它很好地解释了如何处理设备旋转时的实例状态丢失:,我认为您可以尝试在onCreate中处理imageview的恢复,如上面的答案所示,如果有帮助,请告诉我!伟大的分析!谢谢你到底在哪里看到
PhotoView
在棉花糖上经历了两次布局过程?@JJD只需在自定义视图中覆盖
onLayout()
,旋转设备并计算调用次数。对于API 24+,它只调用一次,而对于较低的API,则调用两次。我做了一个快速测试,对于直接的
ImageView
,也一样。再次感谢您。解决办法似乎是成功的。谢谢。
@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);
            }
        }
    });
}