【问题标题】:Detecting the Image Size to be displayed and use it by the Lazy Loading Image检测要显示的图像大小并由延迟加载图像使用
【发布时间】:2013-08-17 09:21:36
【问题描述】:

我想自定义用于覆盖要显示的真实图像的图像大小。在 UIL(Universal-Image-Loader) 配置中,我们可以将 .showStubImage(R.drawable.temp_drawable) 作为显示选项。

我的问题是,我正在实现类似 pinterest 的视图。当我从图像滚动时,图像的位置不稳定,因为它们仍在被下载并被临时可绘制对象覆盖。例如,临时可绘制对象为 45 X 45,则要显示的图像为 100 x 50。当显示真实图像时,由于临时图像被真实图像替换,因此滚动时图像会出现这种位移效果.有没有什么方法可以在下载的时候检测到要显示的真实图像高度和宽度,并使用临时图像可以使用的宽度和高度来临时显示图像大小?

    options = new DisplayImageOptions.Builder()
    .showStubImage(R.drawable.ic_stub)
    .showImageForEmptyUri(R.drawable.ic_empty)
    .showImageOnFail(R.drawable.ic_error)
    .cacheInMemory(true)
    .cacheOnDisc(true)

  imageLoader.displayImage(imageUrls[position], hold.image, options);


更新 Universal-Image-Loader.jar 中的代码

public void displayImage(String uri, ImageView imageView, DisplayImageOptions options, ImageLoadingListener listener) {
    checkConfiguration();
    if (imageView == null) {
        throw new IllegalArgumentException(ERROR_WRONG_ARGUMENTS);
    }
    if (listener == null) {
        listener = emptyListener;
    }
    if (options == null) {
        options = configuration.defaultDisplayImageOptions;
    }

    if (TextUtils.isEmpty(uri)) {
        engine.cancelDisplayTaskFor(imageView);
        listener.onLoadingStarted(uri, imageView);
        if (options.shouldShowImageForEmptyUri()) {
            imageView.setImageResource(options.getImageForEmptyUri());
        } else {
            imageView.setImageDrawable(null);
        }
        listener.onLoadingComplete(uri, imageView, null);
        return;
    }

    ImageSize targetSize = ImageSizeUtils.defineTargetSizeForView(imageView, configuration.maxImageWidthForMemoryCache, configuration.maxImageHeightForMemoryCache);
    String memoryCacheKey = MemoryCacheUtil.generateKey(uri, targetSize);
    engine.prepareDisplayTaskFor(imageView, memoryCacheKey);

    listener.onLoadingStarted(uri, imageView);
    Bitmap bmp = configuration.memoryCache.get(memoryCacheKey);
    if (bmp != null && !bmp.isRecycled()) {
        if (configuration.writeLogs) L.d(LOG_LOAD_IMAGE_FROM_MEMORY_CACHE, memoryCacheKey);

        if (options.shouldPostProcess()) {
            ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageView, targetSize, memoryCacheKey, options, listener, engine.getLockForUri(uri));
            ProcessAndDisplayImageTask displayTask = new ProcessAndDisplayImageTask(engine, bmp, imageLoadingInfo, options.getHandler());
            engine.submit(displayTask);
        } else {
            options.getDisplayer().display(bmp, imageView, LoadedFrom.MEMORY_CACHE);
            listener.onLoadingComplete(uri, imageView, bmp);
        }
    } else {
        if (options.shouldShowStubImage()) {
            imageView.setImageResource(options.getStubImage());
        } else {
            if (options.isResetViewBeforeLoading()) {
                imageView.setImageDrawable(null);
            }
        }

        ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageView, targetSize, memoryCacheKey, options, listener, engine.getLockForUri(uri));
        LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(engine, imageLoadingInfo, options.getHandler());
        engine.submit(displayTask);
    }
}

我喜欢 `.showStubImage(getImageDimension())'

附加

new DownloadFilesTask().execute(imageUrls[position]);

private class DownloadFilesTask extends AsyncTask<String, String, String> {

    @Override
    protected String doInBackground(String... params) {
        // TODO Auto-generated method stub


        URL uri = null;
        try {
            uri = new URL(params[0].toString());
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

         InputStream in=null;
      try
        {
          //URL oracle = new URL(url);
        URLConnection urlConnection = uri.openConnection();
        in = new BufferedInputStream(urlConnection.getInputStream());
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(in , null, options);
        //return options;
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
      finally
        {
        if(in!=null)
             IoUtils.closeSilently(in);

        }
        return null;
    }
}

【问题讨论】:

  • 如果您正在从服务器下载图像和与图像相关的数据,那么您可以在服务器中维护图像高度和宽度,首先从服务器中提取所有图像的高度和宽度信息并创建根据您拥有的高度和宽度信息查看图像。
  • hhhm。不知道我是否可以这样做。图像也会自动调整到设备屏幕,例如,如果有一个小屏幕,图像也会调整到那个,这样它们也可以适应。所以在这种情况下,我需要图像的大小为displayed 并将其用于临时图像。
  • 查看answer

标签: java android bitmap universal-image-loader


【解决方案1】:

这实际上与 Android 无关。这是关于您的应用程序的设计。

如果是您的服务器,您应该确定图像的大小以及如何管理它们,并相应地放置正确的占位符。

如果不是您的服务器,您无法在不以任何方式联系服务器的情况下知道图像的大小,因此您要么必须设置图像适合的静态大小,要么获取图像的大小甚至在显示占位符之前。

获取图像分辨率是通过服务器文件与其他文件相同的方式完成的,在解码时使用inJustDecodeBounds

编辑:这是如何从互联网上获取位图大小的示例代码:

public static BitmapFactory.Options getBitmapOptions(final String url) 
  {
  InputStream in=null;
  try
    {
    URLConnection urlConnection = url.openConnection();
    in = new BufferedInputStream(urlConnection.getInputStream());
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(in , null, options);
    return options;
    }
  finally
    {
    if(in!=null)
      IOUtils.closeQuietly(in);        
    }
  return null;
  }

【讨论】:

  • 我宁愿选择在显示占位符之前获取图像的大小,但我的问题是,我使用 Universal-Image-Loader 库来处理显示,所以我不知道如何处理尺寸的获取。我从 .jar 库中添加了代码。
  • 这很简单。我现在将放一些代码来向您展示如何获取尺寸。
  • url 不起作用,先生,因为它是一个字符串。我在上面为我的进度添加了更新,showStubImage 只接受int
  • @lordzden 它与我所写的内容无关。您首先需要获取尺寸,然后放置正确的图像。如果 showStubImage 不允许您设置位图而不仅仅是可绘制资源,那么您不应该使用它。您可以改用 volley 库。
【解决方案2】:

通常,您可以根据以下库仅提供资源 ID。

options = new DisplayImageOptions.Builder().showStubImage(R.drawable.stubImage)....

如果您需要放置动态更改大小的存根图像,则需要在源代码中进行调整,以便您的选项应该接受大小位图而不是 int。为此,我刚刚查看了源代码。步骤如下:

  1. 您需要做的第一件事是将其作为库项目包含在内,而不是在 libs 文件夹中添加 .jar。

  2. 在 ImageLoader 类中,然后在 public void displayImage(String uri, ImageView imageView, DisplayImageOptions options, ImageLoadingListener listener) 方法中,替换这行 imageView.setImageResource(options.getImageForEmptyUri());imageView.setImageBitmap(sizedBitmap);

  3. 在 DisplayImageOptions 类的showStubImage(int stubImageRes) 中,将参数更改为 Bitmap 并在该类中进行必要的更改。

  4. 注意所有需要更改的地方,该功能反映在不同的部分。

更改位图大小:

 Bitmap icon = BitmapFactory.decodeResource(context.getResources(),
                               R.drawable.stub_image);
  bitmap = Bitmap.createScaledBitmap(stub, width, height, false);

【讨论】:

  • 除了上面的答案,我建议再做一件事。根据您的要求,您每次都需要创建缩放位图。所以我建议您缓存原始位图而不是每次都获取它。然后根据需要对缓存的位图进行缩放。
猜你喜欢
  • 2019-02-04
  • 2019-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多