Android Fresco图片处理库用法API英文原文文档2-2(Facebook开源Android图片库)

Android Fresco图片处理库用法API英文原文文档2-2(Facebook开源Android图片库)

这是英文文档的第二部分(2):DRAWEE GUIDE

由于第二部分内容多一些,所以分为2个文章发。方便大家查看。

Using the ControllerBuilder

SimpleDraweeView has two methods for specifying an image. The easy way is to just callsetImageURI.

If you want more control over how the Drawee displays your image, you can use aDraweeController. This page explains
how to build and use one.

Building a DraweeController

Then pass the image request to a PipelineDraweeControllerBuilder.
You then specify additional options for the controller:

ControllerListener listener = new BaseControllerListener() {...}

DraweeController controller = Fresco.newDraweeControllerBuilder()
    .setUri(uri)
    .setTapToRetryEnabled(true)
    .setOldController(mSimpleDraweeView.getController())
    .setControllerListener(listener)
    .build();

mSimpleDraweeView.setController(controller);

You should always call setOldController when building a new controller. This prevents an unneeded memory allocation.

More details:

Customizing the ImageRequest

For still more advanced usage, you might need to send an ImageRequest to
the pipeline, instead of merely a URI. An example of this is using a postprocessor.

Uri uri;
Postprocessor myPostprocessor = new Postprocessor() { ... }
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
    .setPostprocessor(myPostprocessor)
    .build();

DraweeController controller = Fresco.newDraweeControllerBuilder()
    .setImageRequest(request)
    .setOldController(mSimpleDraweeView.getController())
    // other setters as you need
    .build();

More details:

Progressive JPEGs

Note: the API in this page is still preliminary and subject to change.

Fresco supports the streaming of progressive JPEG images over the network.

Scans of the image will be shown in the view as you download them. Users will see the quality of the image start out low and gradually become clearer.

This is only supported for the network images. Local images are decoded at once.

Initialization

When you configure the image pipeline, you must pass in an instance ofProgressiveJpegConfig.
We plan to remove this requirement.

This example will decode no more than every other scan of the image, using less CPU than decoding every scan.

ProgressiveJpegConfig pjpegConfig = new ProgressiveJpegConfig() {
  @Override
  public int getNextScanNumberToDecode(int scanNumber) {
    return scanNumber + 2;
  }    

  public QualityInfo getQualityInfo(int scanNumber) {
    boolean isGoodEnough = (scanNumber >= 5);
    return ImmutableQualityInfo.of(scanNumber, isGoodEnough, false);
  }
}

ImagePipelineConfig config = ImagePipelineConfig.newBuilder()
    .setProgressiveJpegConfig(pjpeg)
    .build();

Instead of implementing this interface yourself, you can also instantiate theSimpleProgressiveJpegConfig class.

At Request Time

Currently, you must explicitly request progressive rendering while building the image request:

Uri uri;
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
    .setProgressiveRenderingEnabled(true)
    .build();
DraweeController controller = Fresco.newDraweeControllerBuilder()
    .setImageRequest(request)
    .setOldController(mSimpleDraweeView.getController())
    .build();
mSimpleDraweeView.setController(controller);

We hope to add support for using progressive images with setImageURI in a future release.

Animated Images

Fresco supports animated GIF and WebP images.

We support WebP animations, even in the extended WebP format, on versions of Android going back to 2.3, even those that don‘t have built-in native support.

Playing animations automatically

If you want your animated image to start playing automatically when it comes on-screen, and stop when it goes off, just say so in your image
request
:

Uri uri;
DraweeController controller = Fresco.newDraweeControllerBuilder()
    .setUri(uri)
    .setAutoPlayAnimations(true)
    . // other setters
    .build();
mSimpleDraweeView.setController(controller);

Playing animations manually

You may prefer to directly control the animation in your own code. In that case you‘ll need to listen for when the image has loaded, so it‘s even possible to do that.

ControllerListener controllerListener = new BaseControllerListener<ImageInfo>() {
    @Override
    public void onFinalImageSet(
        String id,
        @Nullable ImageInfo imageInfo,
        @Nullable Animatable anim) {
    if (anim != null) {
      // app-specific logic to enable animation starting
      anim.start();
    }
};

Uri uri;
DraweeController controller = Fresco.newDraweeControllerBuilder()
    .setUri(uri)
    .setControllerListener(controllerListener)
    // other setters
    .build();
mSimpleDraweeView.setController(controller);

The controller exposes an instance of the Animatable interface. If non-null,
you can drive your animation with it:

Animatable animatable = mSimpleDraweeView.getController().getAnimatable();
if (animatable != null) {
  animatable.start();
  // later
  animatable.stop();
}

Limitations

Animations do not currently support postprocessors.

Requesting Multiple Images (Multi-URI)

The methods on this page require setting your own image request.

Going from low to high resolution

Suppose you want to show users a high-resolution, slow-to-download image. Rather than let them stare a placeholder for a while, you might want to quickly download a smaller thumbnail first.

You can set two URIs, one for the low-res image, one for the high one:

Uri lowResUri, highResUri;
DraweeController controller = Fresco.newDraweeControllerBuilder()
    .setLowResImageRequest(ImageRequest.fromUri(lowResUri))
    .setImageRequest(ImageRequest.fromUri(highResUri))
    .setOldController(mSimpleDraweeView.getController())
    .build();
mSimpleDraweeView.setController(controller);

Using thumbnail previews

This option is supported only for local URIs, and only for images in the JPEG format.

If your JPEG has a thumbnail stored in its EXIF metadata, the image pipeline can return that as an intermediate result. Your Drawee will first show the thumbnail preview, then the full image when it has finished loading and decoding.

Uri uri;
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
    .setLocalThumbnailPreviewsEnabled(true)
    .build();

DraweeController controller = Fresco.newDraweeControllerBuilder()
    .setImageRequest(request)
    .setOldController(mSimpleDraweeView.getController())
    .build();
mSimpleDraweeView.setController(controller);

Loading the first available image

Most of the time, an image has no more than one URI. Load it, and you‘re done.

But suppose you have multiple URIs for the same image. For instance, you might have uploaded an image taken from the camera. Original image would be too big to upload, so the image is downscaled first. In such case, it would be beneficial to first try to get
the local-downscaled-uri, then if that fails, try to get the local-original-uri, and if even that fails, try to get the network-uploaded-uri. It would be a shame to download the image that we may have already locally.

The image pipeline normally searches for images in the memory cache first, then the disk cache, and only then goes out to the network or other source. Rather than doing this one by one for each image, we can have the pipeline check for all the
images in the memory cache. Only if none were found would disk cache be searched in. Only if none were found there either would an external request be made.

Just create an array of image requests, and pass it to the builder.

Uri uri1, uri2;
ImageRequest request = ImageRequest.fromUri(uri1);
ImageRequest request2 = ImageRequest.fromUri(uri2);
ImageRequest[] requests = { request1, request2 };

DraweeController controller = Fresco.newDraweeControllerBuilder()
    .setFirstAvailableImageRequests(requests)
    .setOldController(mSimpleDraweeView.getController())
    .build();
mSimpleDraweeView.setController(controller);

Only one of the requests will be displayed. The first one found, whether at memory, disk, or network level, will be the one returned. The pipeline will assume the order of requests in the array is the preference order.

Listening to Download Events

Motivation

Your app may want to execute actions of its own when an image arrives - perhaps make another view visible, or show a caption. You may also want to do something in case of a network failure, like showing an error message to the user.

Loading images is, of course, asynchronous. So you need some way of listening to events posted by the DraweeController. The mechanism for doing this is a controller listener.

Note: this does not allow you to modify the image itself. To do that, use a Postprocessor.

Usage

To use it, you merely define an instance of the ControllerListener interface. We recommend subclassing BaseControllerListener:

ControllerListener controllerListener = new BaseControllerListener<ImageInfo>() {
    @Override
    public void onFinalImageSet(
        String id,
        @Nullable ImageInfo imageInfo,
        @Nullable Animatable anim) {
      if (imageInfo == null) {
        return;
      }
      QualityInfo qualityInfo = imageInfo.getQualityInfo();
      FLog.d("Final image received! " +
          "Size %d x %d",
          "Quality level %d, good enough: %s, full quality: %s",
          imageInfo.getWidth(),
          imageInfo.getHeight(),
          qualityInfo.getQuality(),
          qualityInfo.isOfGoodEnoughQuality(),
          qualityInfo.isOfFullQuality());
    }

    @Override
    public void onIntermediateImageSet(String id, @Nullable ImageInfo imageInfo) {
      FLog.d("Intermediate image received");
    }

    @Override
    public void onFailure(String id, Throwable throwable) {
      FLog.e(getClass(), throwable, "Error loading %s", id)
    }
};

Uri uri;
DraweeController controller = Fresco.newControllerBuilder()
    .setControllerListener(controllerListener)
    .setUri(uri);
    // other setters
    .build();
mSimpleDraweeView.setController(controller);

onFinalImageSet or onFailure is called for all image loads.

If progressive decoding is enabled, and the image supports it, onIntermediateImageSet is
called in response to each scan that gets decoded. Which scans get decoded is determined by yourconfiguration.

Resizing and Rotating

These features require you to construct an image request directly.

Resizing Images

Terminology: resizing vs scaling

  • Resizing is a pipeline operation executed in software. It returns a completely new bitmap, of a different size.
  • Scaling is a canvas operation and is usually hardware accelerated. The bitmap itself is always the same size. It just gets drawn upscaled or downscaled.

Should you resize or scale?

Resizing is rarely necessary. Scaling is almost always preferred, even with resizing.

There are several limitations with resizing:

  • Resize is restricted so that it never returns a bigger image. It can only make the image smaller.
  • At the moment, only JPEG images can be resized.
  • There is only a rough control over the resulting image dimensions. Image cannot be resized to the exact size, but will be reduced by one of the supported resize factors. That means that even resized images need
    to be scaled before displaying.
  • Only the following resize factors are supported: N/8 with 1
    <= N <= 8
    .
  • Resize is performed in software, which is much slower than hardware-accelerated scaling.

Scaling, on the other hand, doesn‘t suffer any of these limitations. Scaling uses Android‘s own built-in facilities to match the image to the view size. On Android 4.0 and later, this is hardware-accelerated on devices with a GPU. Most of the time, it is the
fastest and most effective way to display the image in the size you want. The only downside is if the image is much bigger than the view, then the memory gets wasted.

Why should you ever use resizing then? It‘s a trade-off. You should only ever use resize if you need to display an image that is much bigger than the view in order to save memory. One valid example is when you want to display an 8MP photo taken by the camera
in a 1280x720 (roughly 1MP) view. An 8MP image would occupy 32MB of memory when decoded to 4 bytes-per-pixel ARGB bitmap. If resized to the view dimensions, it would occupy less than 4 MB.

When it comes to network images, before thinking about resizing, try requesting the image of the proper size first. Don‘t request an 8MP high-resolution photo from a server if it can return a smaller version. Your users pay for their data plans and you should
be considerate of that. Besides, fetching a smaller image saves internal storage and CPU time in your app.

Only if the server doesn‘t provide an alternate URI with the smaller image, or if you are using local photos, should you resort to resizing. In all other cases, including upscaling the image, scaling should be used. To scale, simply specify the layout_width and layout_height of
yourSimpleDraweeView, as you would for any Android view. Then specify a scale
type
.

Resizing

Resizing does not modify the original file. Resizing just resizes an encoded image in memory, prior to being decoded.

This can carry out a much greater range of resizing than is possible with Android‘s facilities. Images taken with the device‘s camera, in particular, are often much too large to scale and need to be resized before display on the device.

We currently only support resizing for images in the JPEG format, but this is the most widely used image format anyway and most Android devices with cameras store files in the JPEG format.

To resize pass a ResizeOptions object when constructing an ImageRequest:

Uri uri = "file:///mnt/sdcard/MyApp/myfile.jpg";
int width = 50, height = 50;
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
    .setResizeOptions(new ResizeOptions(width, height))
    .build();
PipelineDraweeController controller = Fresco.newDraweeControllerBuilder()
    .setOldController(mDraweeView.getController())
    .setImageRequest(request)
    .build();
mSimpleDraweeView.setController(controller);

Auto-rotation

It‘s very annoying to users to see their images show up sideways! Many devices store the orientation of the image in metadata in the JPEG file. If you want images to be automatically rotated to match the device‘s orientation, you can say so in the image request:

ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
    .setAutoRotateEnabled(true)
    .build();
// as above

Modifying the Image

Motivation

Sometimes the image downloaded from the server, or fetched from local storage, is not exactly what you want to display on the screen. If you want to apply custom code to the image in-place, use a Postprocessor.

Example

The following example applies a red mesh to the image:

Uri uri;
Postprocessor redMeshPostprocessor = new Postprocessor() {
  @Override
  public String getName() {
    return "redMeshPostprocessor";
  }

  @Override
  public void process(Bitmap bitmap) {
    for (int x = 0; x < bitmap.getWidth(); x+=2) {
      for (int y = 0; y < bitmap.getHeight(); y+=2) {
        bitmap.setPixel(x, y, Color.RED);
      }
    }
  }
}

ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
    .setPostprocessor(redMeshPostprocessor)
    .build();

PipelineDraweeController controller = Fresco.newDraweeControllerBuilder()
    .setImageRequest(request)
    .setOldController(mSimpleDraweeView.getOldController())
    // other setters as you need
    .build();
mSimpleDraweeView.setController(controller);

Things to Know

The image is copied before it enters your postprocessor. The copy of the image in cache isnot affected by any changes you make in your postprocessor. On Android 4.x and lower, the copy is stored outside the Java
heap, just as the original image was.

If you show the same image repeatedly, you must specify the postprocessor each time it is requested. You are free to use different postprocessors on different requests for the same image.

Postprocessors are not currently supported for animated images.

Repeated Postprocessors

What if you want to post-process the same image more than once? No problem at all. Just subclass BaseRepeatedPostprocessor.
This class has a method update which can be invoked at any time to run the postprocessor again.

The example below allows you to change the color of the mesh at any time.

public class MeshPostprocessor extends BaseRepeatedPostprocessor {
  private int mColor = Color.TRANSPARENT;

  public void setColor(int color) {
    mColor = color;
    update();
  }

  @Override
  public String getName() {
    return "meshPostprocessor";
  }

  @Override
  public void process(Bitmap bitmap) {
    for (int x = 0; x < bitmap.getWidth(); x+=2) {
      for (int y = 0; y < bitmap.getHeight(); y+=2) {
        bitmap.setPixel(x, y, mColor);
      }
    }
  }
}
MeshPostprocessor meshPostprocessor = new MeshPostprocessor();

///&#16; setPostprocessor as in above example

meshPostprocessor.setColor(Color.RED);
meshPostprocessor.setColor(Color.BLUE);

You should have still have one Postprocessor instance per image request, as internally the class is stateful.

Image Requests

If you need an ImageRequest that consists only of a URI, you can use the helper methodImageRequest.fromURI.
Loading multiple-images is a common case of this.

If you need to tell the image pipeline anything more than a simple URI, you need to useImageRequestBuilder:

Uri uri;

ImageDecodeOptions decodeOptions = ImageDecodeOptions.newBuilder()
    .setBackgroundColor(Color.GREEN)
    .build();

ImageRequest request = ImageRequestBuilder
    .newBuilderWithSource(uri)
    .setAutoRotateEnabled(true)
    .setLocalThumbnailPreviewsEnabled(true)
    .setLowestPermittedRequestLevel(RequestLevel.FULL_FETCH)
    .setProgressiveRenderingEnabled(false)
    .setResizeOptions(new ResizeOptions(width, height))
    .build();

Fields in ImageRequest

Lowest Permitted Request Level

The image pipeline follows a definite sequence in where it looks for the image.

  1. Check the bitmap cache. This is nearly instant. If found, return.
  2. Check the encoded memory cache. If found, decode the image and return.
  3. Check the "disk" (local storage) cache. If found, load from disk, decode, and return.
  4. Go to the original file on network or local file. Download, resize and/or rotate if requested, decode, and return. For network images in particular, this will be the slowest by a long shot.

The setLowestPermittedRequestLevel field lets you control how far down this list the pipeline will go. Possible values are:

  • BITMAP_MEMORY_CACHE
  • ENCODED_MEMORY_CACHE
  • DISK_CACHE
  • FULL_FETCH

This is useful in situations where you need an instant, or at least relatively fast, image or none at all.

Writing Custom Views

DraweeHolders

There will always be times when DraweeViews won‘t fit your needs. You may need to show additional content inside the same view as your image. You might to show multiple images inside
a single view.

We provide two alternate classes you can use to host your Drawee:

  • DraweeHolder for a single image
  • MultiDraweeHolder for multiple images

Responsibilities of custom views

Android lays out View objects, and only they get told of system events. DraweeViews handle these events and use them to manage memory effectively. When using the holders, you must
implement some of this functionality yourself.

Handling attach/detach events

Your app may leak memory if this steps are not followed.

There is no point in images staying in memory when Android is no longer displaying the view - it may have scrolled off-screen, or otherwise not be drawing. Drawees listen for detaches and release memory when they occur. They will automatically restore the image
when it comes back on-screen.

All this is automatic in a DraweeView, but won‘t happen in a custom view unless you handle four system events. These must be passed to the DraweeHolder.
Here‘s how:

DraweeHolder mDraweeHolder;

@Override
public void onDetachedFromWindow() {
  super.onDetachedFromWindow();
  mDraweeHolder.onDetach();
}

@Override
public void onStartTemporaryDetach() {
  super.onStartTemporaryDetach();
  mDraweeHolder.onDetach();
}

@Override
public void onAttachedToWindow() {
  super.onAttachedToWindow();
  mDraweeHolder.onAttach();
}

@Override
public void onFinishTemporaryDetach() {
  super.onFinishTemporaryDetach();
  mDraweeHolder.onAttach();
}

Handling touch events

If you have enabled tap to retry in your Drawee, it will not work unless you tell it that the user
has touched the screen. Like this:

@Override
public boolean onTouchEvent(MotionEvent event) {
  return mDraweeHolder.onTouchEvent(event) || super.onTouchEvent(event);
}

Your custom onDraw

You must call

Drawable drawable = mDraweeHolder.getHierarchy().getTopLevelDrawable();
drawable.setBounds(...);

or the Drawee won‘t appear at all.

  • Do not downcast this Drawable.
  • Do not translate it.

Other responsibilities

  • Override verifyDrawable:
@Override
protected boolean verifyDrawable(Drawable who) {
  if (who == mDraweeHolder.getHierarchy().getTopLevelDrawable()) {
    return true;
  }
  // other logic for other Drawables in your view, if any
}
  • Make sure invalidateDrawable invalidates the region occupied by your Drawee.

Constructing a DraweeHolder

This should be done carefully.

Arranging your Constructors

We recommend the following pattern for constructors:

  • Override all three of the three View constructors.
  • Each constructor calls its superclass counterpart and then a private init method.
  • All of your initialization happens in init.

That is, do not use the this operator to call one constructor from another.

This approach guarantees that the correct initialization is called no matter what constructor is used. It is in the init method that your holder is created.

Creating the Holder

If possible, always create Drawees when your view gets created. Creating a hierarchy is not cheap so it‘s best to do it only once.

class CustomView extends View {
  DraweeHolder<GenericDraweeHierarchy> mDraweeHolder;

  // constructors following above pattern

  private void init() {
    GenericDraweeHierarchy hierarchy = new GenericDraweeHierarchyBuilder(getResources());
      .set...
      .set...
      .build();
    mDraweeHolder = DraweeHolder.create(hierarchy, context);
  }
}

Setting an image

Use a controller builder, but call setController on
the holder instead of a View:

DraweeController controller = Fresco.newControllerBuilder()
    .setUri(uri)
    .setOldController(mDraweeHolder.getController())
    .build();
mDraweeHolder.setController(controller);

MultiDraweeHolder

Instead of using a DraweeHolder, use a MultiDraweeHolder. There are addremove,
and clearmethods for dealing with Drawees:

MultiDraweeHolder<GenericDraweeHierarchy> mMultiDraweeHolder;

private void init() {
  GenericDraweeHierarchy hierarchy = new GenericDraweeHierarchyBuilder(getResources());
    .set...
    .build();
  mMultiDraweeHolder = new MultiDraweeHolder<GenericDraweeHierarchy>();
  mMultiDraweeHolder.add(new DraweeHolder<GenericDraweeHierarchy>(hierarchy, context));
  // repeat for more hierarchies
}

You must override system events, set bounds, and do all the same responsibilities as for a single DraweeHolder.

Gotchas

Don‘t downcast

It is tempting to downcast objects returns by Fresco classes into actual objects that appear to give you greater control. At best, this will result in fragile code that gets broken next release; at worst, it will lead to very subtle bugs.

Don‘t use getTopLevelDrawable

DraweeHierarchy.getTopLevelDrawable() should only be used by DraweeViews. Client code should almost never interact with it.

The sole exception is custom views. Even there, the top-level drawable should never be downcast. We
may change the actual type of the drawable in future releases.

Don‘t re-use DraweeHierarchies

Never call DraweeView.setHierarchy with the same argument on two different views. Hierarchies are made up of Drawables, and Drawables on Android cannot be shared among multiple
views.

Don‘t use Drawables in more than one DraweeHierarchy

This is for the same reason as the above. Drawables cannot be shared in multiple views.

You are completely free, of course, to use the same resourceID in multiple hierarchies and views. Android will create a separate instance of each Drawable for each view.

Don‘t set images directly on a DraweeView

Currently DraweeView is a subclass of Android‘s ImageView. This has various methods to set an image (such as setImageBitmap, setImageDrawable)

If you set an image directly, you will completely lose your DraweeHierarchy, and will not get any results from the image pipeline.

Don‘t use ImageView attributes or methods with DraweeView

Any XML attribute or method of ImageView not found in View will not work on a DraweeView.
Typical cases are scaleTypesrc, etc. Don‘t use those. DraweeView has its own counterparts as explained
in the other sections of this documentation. Any ImageView attrribute or method will be removed in the upcoming release, so please don‘t use those.

时间: 2024-11-05 18:48:10

Android Fresco图片处理库用法API英文原文文档2-2(Facebook开源Android图片库)的相关文章

Android Fresco图片处理库用法API英文原文文档1(Facebook开源Android图片库)

Fresco是Facebook最新推出的一款用于Android应用中展示图片的强大图片库,可以从网络.本地存储和本地资源中加载图片.其中的Drawees可以显示占位符,直到图片加载完成.而当图片从屏幕上消失时,会自动释放内存. 功能很强大,为了大家学习方便,我将英文原文文档给大家迁移过来,供参考学习. 这是英文文档的第一部分:QUICK START QUICK START Adding Fresco to your Project Here's how to add Fresco to your

Android Fresco图片处理库用法API英文原文文档3(Facebook开源Android图片库)

这是英文文档的第三部分:IMAGE PIPELINE GUIDE Introduction to the Image Pipeline The image pipeline does everything necessary to get an image into a form where it can be rendered into an Android device. The pipeline goes through the following steps when given an

Android Fresco图片处理库用法API英文原文文档4(Facebook开源Android图片库)

这是英文文档的第三部分:THIRD PARTY LIBRARIES Using Other Network Layers By default, the image pipeline uses the HttpURLConnection networking library bundled with Android. Apps may have their own network layer they may wish to use instead. Using OkHttp OkHttp is

Android Fresco图片处理库用法API英文原文文档2-1(Facebook开源Android图片库)

这是英文文档的第二部分(1):DRAWEE GUIDE 由于第二部分内容多一些,所以分为2个文章发.方便大家查看. Using Drawees in XML Drawees have very extensive customization facilities. The best way to customize your Drawee is to do so in the XML. Here is an example that sets nearly all possible option

Android图片剪裁库

最近利用一周左右的业余时间,终于完成了一个Android图片剪裁库,核心功能是根据自己的理解实现的,部分代码参考了Android源码的图片剪裁应用.现在将该代码开源在Github上以供大家学习和使用,地址:https://github.com/Jhuster/ImageCropper,效果如下所示: 我的大致计划是首先介绍一下这个库的用法,然后再写几篇文章介绍一下其中的一些原理和关键技术,希望对Android开发新手有所帮助. [特性] 支持通过手势移动和缩放剪裁窗口 支持固定剪裁窗口大小.固定

Android之图片加载框架Fresco基本使用(一)

PS:Fresco这个框架出的有一阵子了,也是现在非常火的一款图片加载框架.听说内部实现的挺牛逼的,虽然自己还没研究原理.不过先学了一下基本的功能,感受了一下这个框架的强大之处.本篇只说一下在xml中设置属性的相关用法. 0.引入Fresco以及相关注意事项. 1.PlaceHolderImage占位图 2.FailureImage加载失败时显示的图片 3.RetryImage重新加载的图片 4.ProgressBarImage加载时显示的进度图片 5.BackgroundImage背景图 6.

Android 一起来看看知乎开源的图片选择库

前言 在实际开发中,图片选择器一直都是必不可少的一个部分,不管是 QQ 头像的设置,还是发送一条装逼的微信朋友圈,都要用到图片选择器来给用户选择他们想要上传的图片,最近知乎开源了一款图片选择库 Matisse 简直美哭了,而且完全遵循 Android 交互设计规范,实在是很良心. 在开始正文之前,先欣赏一下这个图片选择器的效果 是不是感觉相当的简洁好看,反正我是这么认为的. 一.基本使用 1.导入相应的依赖库 Gradle: repositories { jcenter() } dependen

Android压缩图片和libjpeg库

前言 Fjpeg使用 Fjpeg 注意 如何使用 如何压缩图片只改变在硬盘的存储大小 如何改变图片分辨率让其Bitmap对象可以加载到内存中 关于重载版本 开始学习之旅 补充知识的结论 修改图片分辨率 防止在Android加载Bitmap的时候oom内存溢出 解决方案1 解决方案2 希望压缩图片方便网络传输 第一种方案利用Bitmapcompress方法压缩 第二种利用libjpeg压缩 在Android50测试两个 图片压缩 在Android60测试两个 图片压缩 解释Android50和60

Android # 图片自动适配屏幕,APK反编译详解,Google Maps Android API,Keytool

本文主题:(图片缩放)自动适配屏幕,APK反编译详解,Google Maps Android API,Keytool  (图片缩放)自动适配屏幕支持缩放旋转,自动居中的imageview http://deanandbai-gmail-com.iteye.com/blog/1850329 apk反编译工具 http://pan.baidu.com/s/1qWFcueC Android APK反编译详解 http://blog.csdn.net/ithomer/article/details/67