2013-04-11 151 views
1

在屏幕上有一个ImageView和一个带有'match_parent'参数的GLSurfaceView设置。 ImageView会快速填充并显示在屏幕上。然后,GLSurfaceView通过对图像的修改而被填充到顶部。到现在为止还挺好。GLSurfaceView隐藏ImageView不需要

但是,这些视图也位于ViewPager的内部,并且图像位于其左侧和右侧。在ImageView顶部引入OpenGL表面视图之前,视图会按预期向左和向右转移。但在将GLSurfaceView引入其上之后,只要用户开始滑动手指移动到下一个图像,SurfaceView就变得透明,从而导致图像消失。它甚至强制它下面的图像在ImageView中消失。显示父视图的背景。

我不清楚如何解决这个问题。如果纹理滑到像ImageView那样的边上,或者甚至是透明的,但将ImageView放在它后面可见,那将会很好。

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

回答

1

这似乎是,我不能让我试图达到的效果的原因是因为GLSurfaceView总是放在背后对前景的看法引起透明度等意见。因此,GLSurfaceView将优先于绘制。为了达到我想要的效果,我可能需要确保在滑动时使用View.setVisibility()隐藏,并在ViewPager稳定后将其设置为可见。这是我在看到其他一些链接作为不同研究的副产品后遇到的最新结论。

z-order for GLSurfaceViews

scrolling in 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; 
    } 

编辑:按照要求,我想提供一些额外的输入至于如何调整纹理一个OpenGL SurfaceView将使用一个Bitmap输入。

以下是一些代码可用于在过程中的第一步在针对当前位图的纹理尺寸是否会在单个纹理内适合检查快速片段。如果你想平铺纹理以保持图像更大,那么这会变得更加复杂,而这不是我的解决方案所需要的。

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

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的目标是在没有内存不足的情况下简单加载我所能够加载的内容。为此,我简单地修改了我即将加载的Bitmap的Options,并尝试在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."); 
} 

有很多方法可以做到这一点,但这是采取一个办法,我想补充的清晰度和附加信息,这个以前的职位的要求,因为它没有包含在我接受的答案为尽可能多的信息我会喜欢任何一个。

+0

你解决了你的问题吗?我有同样的问题,但无法修复它... – 2015-01-30 14:18:33

+0

@alexlodoss我提供的上述代码最终为我工作。我在SurfaceView后面的ImageView中有一张低分辨率照片。所以,当ViewPager被交互时,会显示低分辨率的“位图”,当它结束时,我会将“SurfaceView”带回可视范围。 – 2015-01-30 20:21:23

+0

请告诉我,当你获得类BitmapFactoryUtils?我没有注意到它在第一次... – 2015-02-02 11:23:16