屏幕上有一个 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 稳定后将其设置回可见。这是我在看到其他几个链接作为不同研究的副产品后得出的当前结论。
似乎 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/