【问题标题】:Viewpager with large bitmaps带有大位图的 Viewpager
【发布时间】:2013-01-17 19:38:09
【问题描述】:

您好,我正在尝试构建类似水平画廊的东西,我可以在其中使用画廊/相机中的图像添加或删除页面。

我正在尝试使其适用于大型位图,因此我使用一种算法来缩放位图并将其设置为每个页面的图像视图。 该算法需要 ImageView 的宽度/高度(按比例缩小)。

我遇到的问题是,当我的自定义PagerAdapter方法执行时,ImageView的宽度/高度还不知道(getWidth/getHeight返回0),所以它不起作用:

public Object instantiateItem(ViewGroup collection, int position) {
        LayoutInflater inflater = (LayoutInflater) collection.getContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(R.layout.document_page, null);
        ((ViewPager) collection).addView(view, 0);

        ImageView imageView = (ImageView) view.findViewById(R.id.imageView);

        // Obtain the image file URI
        // Call algorithm to get scaled bitmap using ImageView width and height --> PROBLEM: imageView.getWidth()/Height() return 0!!
        // Set ImageView with scaled bitmap to avoid OutOfMemory Exception

        return view;
}

你有什么建议?

谢谢。

【问题讨论】:

  • 在观看 Chet Haase 的两个小教程时,我再次想到了这个问题。它们刚刚被上传并涵盖了inSampleSize (youtube.com/watch?v=12cB7gnL6po) 和一般的位图加载性能 (youtube.com/watch?v=rsQet4nBVi8)。请务必检查您是否可以使用一些知识来优化您的代码并避免异常。
  • 最后,你解决了吗?我也有同样的问题

标签: android android-viewpager android-imageview


【解决方案1】:

缩放图像客户端:

如果图像已经在您的设备上,您不需要自己的算法来缩放图像。 ImageView 有一个 ScaleType,您可以这样设置:

imageView.setScaleType(ImageView.ScaleType.CENTER_CROP)

(或在带有android:scaleType 属性的XML 中)。

剩下的问题是如何从您的 URL 中获取图像以显示在 ImageView 中。使用诸如 SmartImageViewAndroid-Query(更强大)之类的库以异步方式实现这一点(即不阻塞您的 UI 线程)。

例如,使用 SmartImageView,您可以使用以下内容:

myImageView.setImageUrl("http://www.awesomeimages.com/myawesomeimage.jpg");

只需阅读该页面上的示例,还有更多选择。

扩展服务器端

如果您有某种触发的调整大小算法,例如通过某些 URL 参数,使用 this solution 并根据需要传递宽度和高度(可能使用上述库之一)。

正如您所说的 getWidth()getHeight() 返回 0,请查看您为 ImageView 设置的 layout_widthlayout_height。如果是fill_parent,应该没有问题,但如果必须wrap_content,请考虑使用与最终图像具有相同纵横比的本地透明虚拟图像(直到“真实图像”已设置)。

【讨论】:

  • 谢谢,但我使用的是 SDCard 中的图像,因此必须使用 BitmapFactory.decodeFile 对文件进行解码。 decodeFile 接收一个参数来指示一些选项,其中之一是 inSampleSize 用于缩小。如果我不使用它,我可能会得到 OutOfMemoryException。我正在使用的算法在这里解释:developer.android.com/training/displaying-bitmaps/…
  • 好的,那您尝试我的第二个解决方案了吗?宽度或高度设置为 fill_parent 的 imageView 通常会在 getWidth()getHeight() 上返回正确的像素大小。否则,这种虚拟图像方法可能会有所帮助?
【解决方案2】:

使用带有 justInbounds 选项的位图工厂。所以它只会返回位图的尺寸,而不会将位图加载到内存中。

  options.inJustDecodeBounds = true;

【讨论】:

  • 对不起,这与我的问题无关。我需要知道图像视图的宽度和高度,而不是位图。
  • 对不起,我误解了。你可以试试 getMeasuredHeight() 或者你可以通过覆盖 imageview 的 onLayout() 方法来获得这个值。
【解决方案3】:

尝试将位图采样到屏幕大小(使用inJustDecodeBounds获取位图分辨率,displayMatrics获取屏幕分辨率)。

如果没有透明度,您可能还希望使用位图解码的RGB 565 format 而不是 8888。这将节省大约 1/4 的正在使用的内存。

无论如何,我建议reading this tutorial 处理位图。

【讨论】:

  • 我读过那个教程,我提到的算法就是那个。如您所见,“calculateInSampleSize”中解释的方法具有 reqWidth 和 reqHeight 参数。那些必须是图像视图的宽度和高度,这就是问题所在。我的 imageview 没有固定的宽度/高度,它使用 fill_parent。并且图像视图的 getWidth/getHeight 返回 0。
【解决方案4】:

我遇到了同样的问题,但我想出了一个解决方案:创建一个函数并从“public Object instantiateItem(ViewGroup collection, int position)”中调用它。

诀窍是:创建的函数将设置为在几毫秒后执行(为此,您将使用 Handler 对象)

这样做,“instantiateItem”已经完成,视图元素将设置宽度和高度值。

下面是一些关于如何进行的示例代码:

@Override
public Object instantiateItem(ViewGroup container, int position)
{
    View view =  inflater.inflate(R.layout.pager_list_item,container,false);

    TextView textView= (TextView) view.findViewById(R.id.pagerTextView);
    ImageView imageView = (ImageView)view.findViewById(R.id.pagerImageView);

    ... //stuff that don't need the width and height

    Handler handle = new Handler();
    handle.postDelayed(new Runnable()
    {
        //here the widths and heights values should be already set
       //now you can test the view.getWidth() and view.getHeight()

       if(view.getWidth()!=0 && view.getHeight()!=0)
       {
          //now you sare safe to call the android algorithm for scaling large bitmaps
       }

    }, 100); //it will wait 100 miliseconds to execute

  return view;
}

100 毫秒是一个任意数字,可能太多了!!

我建议您使用循环或递归函数来保证“if”语句中的块将被执行,这样您可以使用更小的毫秒。

在我的项目中,我使用了一个递归函数,它在执行“if”块之前调用自身,我设置为 5 毫秒。

它应该可以在没有循环或递归方法的情况下工作,只需设置一个像 100 这样的任意数字并稍后进行测试,但你不能保证应用程序在所有设备上的行为都相同,因为一个可以快速而其他设备可能需要更长的时间才能准备好视图,您永远不会知道。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-09
    • 2015-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多