1

屏幕上有一个带有“match_parent”参数的 ImageView 和 GLSurfaceView 设置。ImageView 快速填充并显示在屏幕上。然后,GLSurfaceView 被填充在它上面,并对图像进行修改。到目前为止,一切都很好。

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

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

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

4

1 回答 1

2

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

GLSurfaceViews 的 z 顺序

在 GLSurfaceViews 中滚动

看起来 GLSurfaceView 类的性能与我最初期望的视图并不一样。因此,需要格外小心,以便进一步保持 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;
    }

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

以下是该过程中第一步可用的一些代码的快速片段,用于检查当前位图的纹理大小是否适合单个纹理。如果你想平铺纹理以保持图像更大,那么这会变得更加复杂,这不是我的分辨率所需要的。

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

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我将要加载的 Bitmap 并尝试在 try catch 块中加载它。如果内存不足,我会再试一次,但占用空间更小。

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.");
}

有很多方法可以做到这一点,但这是一种可以采用的方法,我想根据要求在上一篇文章中添加清晰度和附加信息,因为它没有包含我所希望的关于我接受的答案的尽可能多的信息。

于 2013-04-12T13:40:35.040 回答