android - GLSurfaceView 隐藏了不需要的 ImageView

标签 android opengl-es

屏幕上有一个 ImageView 和一个带有“match_parent”参数的 GLSurfaceView 设置。 ImageView 被快速填充并显示在屏幕上。然后,GLSurfaceView 通过对图像的修改在其顶部填充。到目前为止一切顺利。

但是,这些 View 也存在于 ViewPager 内部,其左右都有图像。在 ImageView 之上引入 OpenGL Surface View 之前, View 会按预期向左和向右过渡。但是在其上引入 GLSurfaceView 之后,只要用户开始滑动手指移动到下一张图像,SurfaceView 就会变得透明,导致图像消失。它甚至强制其下方的图像在 ImageView 中消失。显示父 View 的背景。

我不清楚如何处理这个问题。如果纹理像 ImageView 一样滑到一边,或者甚至是透明的,但让 ImageView 留在它后面可见,那就太好了。

即使是 GLSurfaceView.RENDERMODE_CONTINUOSLY 也不会在过渡期间保留纹理。

最佳答案

似乎我无法获得我想要达到的效果的原因是因为 GLSurfaceView 总是放置在其他 View 后面,导致前景 View 透明。因此,GLSurfaceView 将优先于绘制。为了达到我想要的效果,我可能需要确保在滑动时将 View.setVisibility( ) 用于不可见,并在 ViewPager 稳定后将其设置回可见。这是我在看到其他几个链接作为不同研究的副产品后得出的当前结论。

z-order for GLSurfaceViews

scrolling in GLSurfaceViews

似乎 GLSurfaceView 类的性能确实与我最初预期的 View 相似。因此,需要格外小心,以便进一步保持 ImageView 在 ViewPager 中图像之间的可见转换。

在 viewPager 中,我设法按照以下代码完成了一些事情。这当然还处于粗略状态,因为它处于测试过程中,但它完成了我正在寻找的东西。这是为了让纹理在我们开始停留在图像上时开始加载,然后在用户开始离开图像时消失并显示其下方的原始图像。这似乎在没有撕裂或闪烁的情况下工作,这是我期望它的行为方式。

@Override
public void onPageScrollStateChanged(int state)
{
    switch(state)
    {
        case ViewPager.SCROLL_STATE_DRAGGING:
            Log.i("photoViewer:","dragging ViewPager");
            if(photoSurfaceView_ != null  && photoViewFrameLayout != null)
            {
                photoSurfaceView_.setAlpha(0);
                photoSurfaceView_.invalidate();
            }
            break;
        case ViewPager.SCROLL_STATE_IDLE:
            photoSurfaceView_.setVisibility(View.VISIBLE);
            photoSurfaceView_.setAlpha(1);
            Log.i("photoViewer:","idle ViewPager");
            break;
        case ViewPager.SCROLL_STATE_SETTLING:
            int childCount = photoViewFrameLayout.getChildCount();
            if(childCount >= 2)
            {
                photoViewFrameLayout.removeViews(1, childCount-1);
            }
            new Thread(new Runnable() {
                @Override
                public void run()
                {
                    Looper.prepare();
                    final Bitmap openGlBitmap = BitmapFactoryUtils.resizeAsNecessaryForOpenGLtexture(photoPaths[photoViewPager_.getCurrentItem()], new BitmapFactory.Options());
                    Rect bounds = BitmapFactoryUtils.calculateBoundsForBitmap(activityContext, openGlBitmap);
                    int scaledHeight = bounds.height();
                    int scaledWidth = bounds.width();
                    photoSurfaceView_ = new PhotoViewSurfaceView(activityContext, openGlBitmap);
                    photoSurfaceView_.setLayoutParams(new LayoutParams(scaledWidth, scaledHeight, Gravity.CENTER));
                    photoSurfaceView_.setVisibility(View.VISIBLE);
                    photoSurfaceView_.setAlpha(0);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run()
                        {
                            photoViewFrameLayout.addView(photoSurfaceView_);
                        }
                    });
                }
            }).start();

            Log.i("photoViewer:","settling ViewPager");
            break;
    }

编辑: 根据要求,我想提供一些关于如何调整 OpenGL SurfaceView 纹理大小的额外输入,它将使用位图 用于输入。

以下是检查当前位图的纹理大小是否适合单个纹理的过程第一步可用的一些代码的快速 fragment 。如果您想平铺纹理以保持图像更大,那么这会变得更加复杂,这不是我的解决方案所需要的。

可以使用以下代码检索纹理大小:

private void assignTextureSize()
{
    /* The maximum texture size can be found within the OpenGL context and then shared amongst other applications. */
    int[] maxTextureSize = new int[1];

    GLES20.glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0);

    maxTextureSize = maxTextureSize[0];
}

但仅在 Renderer 类中,对于我的情况,我一直等到纹理的 onDrawFrame 中才进行分配;在将位图分配给它之前。

然后,为我加载的 Bitmap 的目标是在不耗尽内存的情况下简单地加载我能加载的内容。为此,我只是修改了我将要加载的位图的 Options 并尝试将其加载到 try catch block 中。如果内存不足,我会再试一次,但占用空间更小。

try
{
    final int sizeFactors[] = { 1, 2, 4, 8, 16, 32 };

    if (new File(bitmapFilePath).exists())
    {
        BitmapFactory.Options options = new BitmapFactory.Options();
        for (int i = 0; i < sizeFactors.length; ++i)
        {
            try
            {
                options.inSampleSize = sizeFactors[i];
                Bitmap bmp = BitmapFactory.decodeFile(bitmapFilePath, options);

                if(bmp.getHeight() > maximumTextureSize ||
                       bmp.getWidth() > maximumTextureSize)
                {
                    continue;
                }

                /*
                 * @category Check against EXIF data if the image needs to be rotated or not for viewing.
                 */
                Matrix matrix = new Matrix ();
                ExifInterface exif = new ExifInterface(bitmapFilePath); 
                int orientation = exif.getAttributeInt (ExifInterface.TAG_ORIENTATION, 1); 
                switch(orientation) 
                { 
                    case ExifInterface.ORIENTATION_NORMAL:
                        break; 
                    case ExifInterface.ORIENTATION_ROTATE_90: 
                        matrix.postRotate (90); 
                        break; 
                    case ExifInterface.ORIENTATION_ROTATE_180: 
                        matrix.postRotate (180);
                        break; 
                    case ExifInterface.ORIENTATION_ROTATE_270:
                        matrix.postRotate (270); 
                        break; 
                    default: 
                } 

                bmp = Bitmap.createBitmap (bmp, 0, 0, bmp.getWidth (), bmp.getHeight (), matrix, true);

                return bmp;
            } catch (OutOfMemoryError outOfMemory)
            {
                //Do nothing, it will return when one that doesn't run out of memory is loaded.  Or you could do additional checking to bail if needed, etc.
            }
        }
        throw new Exception("Not enough memory for loading image");
    }
} catch (Exception exception)
{
    Log.e("CustomLogTag", "Exception for loading the image that was selected for extraction.");
}

有很多方法可以做到这一点,但这是一种方法,我想按照要求为上一篇文章添加清晰度和其他信息,因为它没有包含我所接受的答案的尽可能多的信息要么。

关于android - GLSurfaceView 隐藏了不需要的 ImageView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15958814/

相关文章:

ios - Objective-c Opengl 内存泄漏

java - 重新调整 EditText 中的文本 (android)

android - 为什么我在运行 `NoClassDefFoundError: org/codehaus/groovy/runtime/typehandling/ShortTypeHandling` 时得到 `./gradlew tasks` ?

android - 在哪里存储用于 CirlceCi 构建的 Android KeyStore 文件?

Android OpenGL SurfaceTexture(外部图像)与普通纹理的结合

java - 如何在 Android 上使用 OpenGL ES 扩展

java - 在opengl es android中的随机位置绘制多个立方体

java - 如何获取枚举自定义属性的所有可能值?

java - 使用 Android Maps API V2 的 Android 应用程序拒绝启动

ios - 在openGL ES中检测距相机最近的顶点