代码之家  ›  专栏  ›  技术社区  ›  JJD

Android 6上的自定义图像视图释放状态

  •  0
  • JJD  · 技术社区  · 7 年前

    我用的是 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);
            }
        });
    }
    

    该视图在安卓7.1.1和安卓9上运行正常。
    在…上 安卓6.0.1 这个 国家失去了 :当设备旋转时,图像视图重置为其初始状态。

    我准备了一份 simple project 来证明这个问题。我用的是请注意 PhotoView 1.3.1 故意的,因为我不能包括及物动词 androidx 目前的依赖性。

    0 回复  |  直到 7 年前
        1
  •  1
  •   Cheticamp    7 年前

    请注意 这似乎不是我的问题 照片视图 版本2.3.0。

    照片视图 在为API 23及以下版本重新创建时,将经历两种布局。对于API 24+,只有一个布局过程。当有两次传递时,会发生的情况是,在中恢复的比例(矩阵) onRestoreInstanceState() 属于 SaveStatePhotoView 重置了。在您的代码中,您将在第一次传递后删除全局布局侦听器,因此,当矩阵在第二次布局传递时重置时,您无法捕获它。对于API 24+,只有一次通过,刻度恢复且不重置。这就是为什么API 23会出现问题,而不是24。

    我认为真正的解决办法是 照片视图 .香草 ImageView 也经历了两次布局通行证,所以我不认为额外的布局通行证 照片视图 原因。然而,我确实认为 照片视图 对某些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);
                }
            }
        });
    }
    

    以上内容基于提供的演示应用程序 照片视图 版本1.3.1。