0

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

我正在尝试使其与大型位图一起使用,因此我使用一种算法来缩放位图并将其设置为每个页面的图像视图。该算法需要 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;
}

你有什么建议?

谢谢。

4

4 回答 4

3

缩放图像客户端:

如果图像已经在您的设备上,您不需要自己的算法来缩放图像。AnImageView有一个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 参数触发的调整大小算法,请使用此解决方案并根据需要传递宽度和高度(可能使用上述库之一)。

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

于 2013-01-17T20:05:35.017 回答
0

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

  options.inJustDecodeBounds = true;
于 2013-01-17T23:09:08.650 回答
0

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

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

无论如何,我建议阅读处理位图的本教程。

于 2013-01-17T23:27:24.337 回答
0

我遇到了同样的问题,但我想出了一个解决方案:创建一个函数并从“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 这样的任意数字并稍后进行测试,但你不能保证应用程序在所有设备上的行为都相同,因为一个可能很快,而另一个可能需要一个等待视图准备好一点时间,你永远不会知道。

于 2019-04-06T10:50:41.540 回答