自定义图像视图在 Marshmallow 上丢失状态
Custom image view looses state on Marshmallow
我正在使用 PhotoView library in my Android project. The project contains the 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 上,状态丢失:旋转设备时图像视图重置为初始状态。
我特意准备了一个 simple project to demonstrate the issue. Please note that I am using PhotoView 1.3.1,因为我现在无法包含传递性 androidx
依赖项。
N.B 这似乎不是 PhotoView 2.3.0 版的问题。
PhotoView 在为 API 23 岁及以下重新创建时会经历两种布局。对于 API 24+,只有一个布局通道。当有两次通过时会发生什么是在 SaveStatePhotoView
的 onRestoreInstanceState()
中恢复的比例(矩阵)被重置。在您的代码中,您在第一次通过后删除了全局布局侦听器,因此,当在第二次布局通过时重置矩阵时,您没有捕捉到它。对于API24+,只有一次pass,比例恢复,不重置。这就是为什么您会看到 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。
我正在使用 PhotoView library in my Android project. The project contains the 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 上,状态丢失:旋转设备时图像视图重置为初始状态。
我特意准备了一个 simple project to demonstrate the issue. Please note that I am using PhotoView 1.3.1,因为我现在无法包含传递性 androidx
依赖项。
N.B 这似乎不是 PhotoView 2.3.0 版的问题。
PhotoView 在为 API 23 岁及以下重新创建时会经历两种布局。对于 API 24+,只有一个布局通道。当有两次通过时会发生什么是在 SaveStatePhotoView
的 onRestoreInstanceState()
中恢复的比例(矩阵)被重置。在您的代码中,您在第一次通过后删除了全局布局侦听器,因此,当在第二次布局通过时重置矩阵时,您没有捕捉到它。对于API24+,只有一次pass,比例恢复,不重置。这就是为什么您会看到 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。