第 2 章 DRAWEE 指南
在XML中使用Drawees
Drawees 具有极大的可定制性。
下面的例子给出了可以配置的各种选项:
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/my_image_view"
android:layout_width="20dp"
android:layout_height="20dp"
fresco:fadeDuration="300"
fresco:actualImageScaleType="focusCrop"
fresco:placeholderImage="@color/wait_color"
fresco:placeholderImageScaleType="fitCenter"
fresco:failureImage="@drawable/error"
fresco:failureImageScaleType="centerInside"
fresco:retryImage="@drawable/retrying"
fresco:retryImageScaleType="centerCrop"
fresco:progressBarImage="@drawable/progress_bar"
fresco:progressBarImageScaleType="centerInside"
fresco:progressBarAutoRotateInterval="1000"
fresco:backgroundImage="@color/blue"
fresco:overlayImage="@drawable/watermark"
fresco:pressedStateOverlayImage="@color/red"
fresco:roundAsCircle="false"
fresco:roundedCornerRadius="1dp"
fresco:roundTopLeft="true"
fresco:roundTopRight="false"
fresco:roundBottomLeft="false"
fresco:roundBottomRight="true"
fresco:roundWithOverlayColor="@color/corner_color"
fresco:roundingBorderWidth="2dp"
fresco:roundingBorderColor="@color/border_color"
/>
必须设置layout_width和layout_height
如果没有在XML中声明这两个属性,将无法正确加载图像。
wrap_content
Drawees 不支持 wrap_content
属性。
所下载的图像可能和占位图尺寸不一致,如果设置出错图或者重试图的话,这些图的尺寸也可能和所下载的图尺寸不一致。
如果大小不一致,图像下载完之后,假设如果是wrap_content
,View将会重新layout,改变大小和位置。这将会导致界面跳跃。
固定宽高比
只有希望显示的固定宽高比时,可以使用wrap_content
。
如果希望显示的图片保持一定宽高比例,如果 4:3,则在XML中:
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/my_image_view"
android:layout_width="20dp"
android:layout_height="wrap_content"
<!-- other attributes -->
然后在代码中指定显示比例:
mSimpleDraweeView.setAspectRatio(1.33f);
在JAVA代码中使用Drawees
设置或更改要显示的图片
mSimpleDraweeView.setImageURI(uri);
如果要更加复杂的配置,可使用ControllerBuilder;
自定义显示图
一般情况下,在XML设置显示效果即可, 如果想更多定制化,可以这样:
创建一个 builder 然后设置给 DraweeView:
List<Drawable> backgroundsList;
List<Drawable> overlaysList;
GenericDraweeHierarchyBuilder builder =
new GenericDraweeHierarchyBuilder(getResources());
GenericDraweeHierarchy hierarchy = builder
.setFadeDuration(300)
.setPlaceholderImage(new MyCustomDrawable())
.setBackgrounds(backgroundList)
.setOverlays(overlaysList)
.build();
mSimpleDraweeView.setHierarchy(hierarchy);
对于同一个View,请不要多次调用setHierarchy
,即使这个View是可回收的。创建 DraweeHierarchy 的较为耗时的一个过程,应该多次利用。
如果要改变所要显示的图片可使用setController
或者 setImageURI
。
修改 DraweeHierarchy
DraweeHierarchy 的一些属性可以在运行时改变。
要改变这些属性,首先获取一个引用:
GenericDraweeHierarchy hierarchy = mSimpleDraweeView.getHierarchy();
修改占位图
修改占位图为资源id:
hierarchy.setPlaceholderImage(R.drawable.placeholderId);
或者修改为一个 Drawable:
Drawable drawable;
// 创建一个drawable
hierarchy.setPlaceholderImage(drawable);
修改显示的图像
修改缩放类型:
hierarchy.setActualImageScaleType(ScalingUtils.ScaleType.CENTER_INSIDE);
当然,如果修改为 focusCrop,
需要指定一个居中点:
hierarchy.setActualImageFocusPoint(point);
或者设置一个color filter:
ColorFilter filter;
// 创建filter
hierarchy.setActualImageColorFilter(filter);
圆角
All of the rounding related params, except the rounding method, can be modified. You get a RoundingParams
object from the hierarchy, modify it, and set it back again:
除了圆角显示方式(原来为圆角的不能修改为圆圈,反之亦然),其他圆角相关的呈现参数, 具体参见这里 是可以动态修改的。
如下: 获取DraweeHierarchy的圆角显示参数,修改圆角半径为10。
RoundingParams roundingParams = hierarchy.getRoundingParams();
roundingParams.setCornersRadius(10);
hierarchy.setRoundingParams(roundingParams);
Drawee的各种效果配置
内容导航
定义
本页说明如何设置实现不同的图片呈现效果。
除了要加载的图片,其他各个设置都可以在xml中指定。在xml中指定的时候,可以是 drawable/
下的资源,也可以颜色。
在Java 代码中也可以指定。如果需要 通过程序设定 的话会接触到这个类: GenericDraweeHierarchyBuilder
通过代码设置是,设置的值可以是资源id,也可以是 Drawable 的子类。
创建完 GenericDraweeHierarchy 之后,也可以通过该类的相关方法,重新设置一些效果。
大多数的用户呈现不同效果的drawables都是可以缩放的.
设置要加载的图
除了需要加载的图片是真正必须的,其他的都是可选的。如前所述,图片可以来自多个地方。
所需加载的图片实际是DraweeController的一个属性,而不是 DraweeHierarchy 的属性。
可使用setImageURI
方法或者通过设置 DraweeController 来进行设置。
对于要加载的图片,除了可以设置缩放类型外,DraweeHierarchy 还公开出一些其他方法用来控制显示效果:
- focus point (居中焦点, 用于 focusCrop 缩放模式)
- color filter
默认的缩放类型是: centerCrop
占位图(Placeholder)
在调用setController
或者 setImageURI
之后,占位图开始显示,直到图片加载完成。
对于渐进式格式的JPEG图片,占位图会显示直到满足已加载的图片解析度到达设定值。
XML 中属性值: placeholderImage
Hierarchy builder中的方法: setPlaceholderImage
Hierarchy method: setPlaceholderImage
默认值: a transparent ColorDrawable
默认缩放类型: centerInside
设置加载失败占位图
如果URI是无效的,或者下载过程中网络不可用,将会导致加载失败。当加载图片出错时,你可以设置一个出错提示图片。
XML 中属性值: failureImage
Hierarchy builder中的方法: setFailureImage
默认值: The placeholder image
默认缩放类型: centerInside
点击重新加载图
在加载失败时,可以设置点击重新加载。这时提供一个图片,加载失败时,会显示这个图片(而不是失败提示图片),提示用户点击重试。
在ControllerBuilder 中如下设置:
.setTapToRetryEnabled(true)
加载失败时,image pipeline 会重试四次;如果还是加载失败,则显示加载失败提示图片。
XML 中属性值: retryImage
Hierarchy builder中的方法: setRetryImage
默认值: The placeholder image
默认缩放类型: centerInside
显示一个进度条
设置一个进度条图片,提示用户正在加载。目前,进度条仅仅是提示正在loading,和加载进度无关。
XML 中属性值: progressBarImage
Hierarchy builder中的方法: setProgressBarImage
默认值: None
默认缩放类型: centerInside
背景
背景图会最先绘制,在XML中只可以指定一个背景图,但是在JAVA代码中,可以指定多个背景图。
当指定一个背景图列表的时候,列表中的第一项会被首先绘制,绘制在最下层,然后依次往上绘制。
背景图片不支持缩放类型,会被强制到Drawee
尺寸大小。
XML 中属性值: backgroundImage
Hierarchy builder中的方法: setBackground,``setBackgrounds
默认值: None
默认缩放类型: N/A
设置叠加图(Overlay)
叠加图会最后被绘制。
和背景图一样,XML中只可以指定一个,如果想指定多个,可以通过JAVA代码实现。
当指定的叠加图是一个列表的时候,列表第一个元素会被先绘制,最后一个元素最后被绘制到最上层。
同样的,不支持各种缩放类型。
XML 中属性值: overlayImage
Hierarchy builder中的方法: setOverlay,``setOverlays
默认值: None
默认缩放类型: N/A
设置按压状态下的叠加图
同样不支持缩放,用户按压DraweeView时呈现。
XML 中属性值: pressedStateOverlayImage
Hierarchy builder中的方法: setPressedStateOverlay
默认值: None
默认缩放类型: N/A
缩放
对于 Drawee 的各种效果配置,其中一些是支持缩放类型的。
可用的缩放类型
类型 | 描述 |
---|---|
center | 居中,无缩放 |
centerCrop | 保持宽高比缩小或放大,使得两边都大于或等于显示边界。居中显示。 |
focusCrop | 同centerCrop, 但居中点不是中点,而是指定的某个点 |
centerInside | 使两边都在显示边界内,居中显示。 如果图尺寸大于显示边界,则保持长宽比缩小图片。 |
fitCenter | 保持宽高比,缩小或者放大,使得图片完全显示在显示边界内。居中显示 |
fitStart | 同上。但不居中,和显示边界左上对齐 |
fitEnd | 同fitCenter, 但不居中,和显示边界右下对齐 |
fitXY | 不保存宽高比,填充满显示边界 |
none | 如要使用tile mode显示, 需要设置为none |
这些缩放类型和Android ImageView 支持的缩放类型几乎一样.
唯一不支持的缩放类型是matrix.
Fresco 提供了focusCrop
作为补充。通常这个缩放效果更佳。
focusCrop
centerCrop
缩放模式会保持长宽比,缩放图片,填充满显示边界,居中显示。这个缩放模式在通常情况下很有用。
但是对于人脸等图片时,一味地居中显示,这个模式可能会裁剪掉一些有用的信息。
以人脸图片为例,借助一些类库,我们可以识别出人脸所在位置。如果可以设置以人脸位置居中裁剪显示,那么效果会好很多。
Fresco的focusCrop缩放模式正是为此而设计。只要提供一个居中聚焦点,显示时就会尽量以此点为中心。
居中点是以相对方式给出的,比如(0.5f, 0.5f)就是居中显示,(0f, 0f)就是左上对齐显示。
如果要使用此缩放模式,首先指定缩放模式。在XML:
fresco:actualImageScaleType="focusCrop"
在Java代码中
PointF focusPoint;
// your app populates the focus point
mSimpleDraweeView
.getHierarchy()
.setActualImageFocusPoint(focusPoint);
none
如果你要使用tile mode进行显示,那么需要将scale type 设置为none.
圆角和圆圈
Drawee 轻松支持圆角显示,并且显示圆角时,并不复制和修改Bitmap对象,那样太耗费内存。
圆角
圆角实际有2中呈现方式:
- 圆圈 - 设置
roundAsCircle
为true - 圆角 - 设置
roundedCornerRadius
设置圆角时,支持4个角不同的半径。XML中无法配置,但可在Java代码中配置。
设置圆角
可使用以下两种方式:
- 默认使用一个shader绘制圆角,但是仅仅占位图所要显示的图有圆角效果。失败示意图和重下载示意图无圆角效果。
- 叠加一个
solid color
来绘制圆角。但是背景需要固定成指定的颜色。在XML中指定roundWithOverlayColor
, 或者通过调用setOverlayColor
来完成此设定。
XML中配置
SimpleDraweeView
支持如下几种圆角配置:
<com.facebook.drawee.view.SimpleDraweeView
...
fresco:roundedCornerRadius="5dp"
fresco:roundBottomLeft="false"
fresco:roundBottomRight="false"
fresco:roundWithOverlayColor="@color/blue"
fresco:roundingBorderWidth="1dp"
fresco:roundingBorderColor="@color/red"
代码中配置
在创建 DraweeHierarchy 时,可以给GenericDraweeHierarchyBuilder
指定一个 RoundingParams 用来绘制圆角效果。
RoundingParams roundingParams = RoundingParams.fromCornersRadius(7f);
roundingParams.setOverlayColor(R.color.green);
// 或用 fromCornersRadii 以及 asCircle 方法
genericDraweeHierarchyBuilder
.setRoundingParams(roundingParams);
你也可以在运行时,改变圆角效果
RoundingParams roundingParams =
mSimpleDraweeView.getHierarchy().getRoundingParams();
roundingParams.setBorder(R.color.red, 1.0);
roundingParams.setRoundAsCircle(true);
mSimpleDraweeView.getHierarchy().setRoundingParams(roundingParams);
在运行时,不能改变呈现方式: 原本是圆角,不能改为圆圈。
使用ControllerBuilder
SimpleDraweeView
有两个方法可以设置所要加载显示图片,简单的方法就是setImageURI
。
如果你需要对加载显示的图片做更多的控制和定制,那就需要用到 DraweeController,本页说明如何使用。
DraweeController
首先,创建一个DraweeController, 然后传递图片加载请求给 PipelineDraweeControllerBuilder
随后,你可以控制controller的其他选项了:
ControllerListener listener = new BaseControllerListener() {...}
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(uri)
.setTapToRetryEnabled(true)
.setOldController(mSimpleDraweeView.getController())
.setControllerListener(listener)
.build();
mSimpleDraweeView.setController(controller);
在指定一个新的controller的时候,使用setOldController
,这可节省不必要的内存分配。
自定义图片加载请求
在更进一步的用法中,你需要给Image pipeline 发送一个ImageRequest。下面是一个图片加载后,使用后处理器(postprocessor) 进行图片后处理的例子.
Uri uri;
Postprocessor myPostprocessor = new Postprocessor() { ... }
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
.setPostprocessor(myPostprocessor)
.build();
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setImageRequest(request)
.setOldController(mSimpleDraweeView.getController())
// 其他设置
.build();
渐进式JPEG图
注意: 本页提及的API仅是初步设计,后续可能变动
Fresco 支持渐进式的网络JPEG图。在开始加载之后,图会从模糊到清晰渐渐呈现。
你可以设置一个清晰度标准,在未达到这个清晰度之前,会一直显示占位图。
渐进式JPEG图仅仅支持网络图。
初始化
配置Image pipeline时 需要传递一个 ProgressiveJpegConfig 的实例。
这个实例需要完成两个事情:1. 返回下一个需要解码的扫描次数2. 确定多少个扫描次数之后的图片才能开始显示。
下面的实例中,为了实现节省CPU,并不是每个扫描都进行解码。
注意:
- 每次解码完之后,调用
getNextScanNumberToDecode
, 等待扫描值大于返回值,才有可能进行解码。
假设,随着下载的进行,下载完的扫描序列如下: 1, 4, 5, 10
。那么:
- 首次调用
getNextScanNumberToDecode
返回为2, 因为初始时,解码的扫描数为0。 - 那么1将不会解码,下载完成4个扫描时,解码一次。下个解码为扫描数为6
- 5不会解码,10才会解码
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();
除了自己实现ProgressiveJpegConfig, 也可以直接使用 SimpleProgressiveJpegConfig
At Request Time
目前,我们必须显式地在加载时,允许渐进式JPEG图片加载。
Uri uri;
ImageRequest request = ImageRequestBuilder
.newBuilderWithSource(uri)
.setProgressiveRenderingEnabled(true)
.build();
PipelineDraweeController controller = Fresco.newControllerBuilder()
.setImageRequest(requests)
.setOldController(mSimpleDraweeView.getController())
.build();
mSimpleDraweeView.setController(controller);
我们希望在后续的版本中,在setImageURI
方法中可以直接支持渐进式图片加载。
动画图(gif)
Fresco 支持GIF和WebP 格式图片;支持WebP 格式的动画图也支持(包括扩展WebP 格式),支持2.3及其以后那些没有原生WebP支持的系统。
设置动画图自动播放
如果你希望图片下载完之后自动播放,同时,当View从屏幕移除时,停止播放,只需要在image request 中简单设置,如下:
Uri uri;
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
.setAutoPlayAnimation(true)
. // other setters
.build();
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setImageRequest(request)
. // other setters
.build();
mSimpleDraweeView.setController(controller);
手动控制动画图播放
也许,你希望在图片加载完之后,手动控制动画的播放,那么这样做:
ControllerListener controllerListener = new BaseControllerListener() {
@Override
public void onFinalImageSet(
String id,
@Nullable ImageInfo imageInfo,
@Nullable Animatable anim) {
if (anim != null) {
// 根据业务逻辑,在合适的时机播放动画。
}
};
Uri uri;
PipelineDraweeController controller = Fresco.newControllerBuilder()
.setControllerListener(controllerListener)
.setUri(uri);
// other setters
.build();
mSimpleDraweeView.setController(controller);
另外,controller提供对Animatable 的访问。
如果有可用动画的话,可对动画进行灵活的控制:
Animatable animation = mSimpleDraweeView.getController().getAnimatable();
if (animation != null) {
// 开始播放
animation.start();
// 一段时间之后,根据业务逻辑,停止播放
animation.stop();
}
多图请求及图片复用
多图请求需 自定义ImageRequest.
先显示低分辨率的图,然后是高分辨率的图
如果你要显示一张高分辨率的图,但是这张图下载比较耗时。你可以在下载前,先提供一张很快能下载完的小缩略图。这比一直显示占位图,用户体验会好很多。
这时,你可以设置两个图片的URI,一个是低分辨率的缩略图,一个是高分辨率的图。
Uri lowResUri, highResUri;
PipelineDraweeController controller = Fresco.newControllerBuilder()
.setLowResImageRequest(ImageRequest.fromUri(lowResUri))
.setImageRequest(ImageRequest.fromUri(highResUri))
.setOldController(mSimpleDraweeView.getController())
.build();
mSimpleDraweeView.setController(controller);
缩略图预览
本功能仅支持本地URI,并且是JPEG图片格式
如果本地JPEG图,有EXIF的缩略图,image pipeline 会立刻返回一个缩略图。完整的清晰大图,在decode完之后再显示。
Uri uri;
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
.setLocalThumbnailPreviewsEnabled(true)
.build();
PipelineDraweeController controller = Fresco.newControllerBuilder()
.setImageRequest(request)
.setOldController(mSimpleDraweeView.getController())
.build();
mSimpleDraweeView.setController(controller);
本地图片复用
大部分的时候,一个图片可能会对应有多个URI,比如:
- 拍照上传。本地图片较大,上传的图片较小。上传完成之后的图片,有一个url,如果要加载这个url,可直接加载本地图片。
- 本地已经有600x600尺寸的大图了,需要显示100x100的小图
对于一个URI,image pipeline 会依次检查内存,磁盘,如果没有从网络下载。
而对于一个图片的多个URI,image pipeline 会先检查他们是否在内存中。如果没有任何一个是在内存中的,会检查是否在本地存储中。如果也没有,才会执行网络下载。
但凡有任何一个检查发现在内存或者在本地存储中,都会进行复用。列表顺序就是要显示的图片的优先顺序。
使用时,创建一个image request 列表,然后传给ControllerBuilder:
Uri uri1, uri2;
ImageRequest request = ImageRequest.fromUri(uri1);
ImageRequest request2 = ImageRequest.fromUri(uri2);
ImageRequest[] requests = { request1, request2 };
PipelineDraweeController controller = Fresco.newControllerBuilder()
.setFirstAvailableImageRequests(requests)
.setOldController(mSimpleDraweeView.getController())
.build();
mSimpleDraweeView.setController(controller);
监听下载事件
你也许想在图片下载完成或者下载失败之后,做一些其他事情。
图片是后台线程异步加载的,我们可以使用一个ControllerListener
实现事件的监听。
_在监听事件回调时,无法修改图片,如果需要修改图片,可使用后处理器(Postprocessor)
~~~ ControllerListener controllerListener = new BaseControllerListener() {
@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` 或者 `onFailure` 都会被触发。前者在成功时,后者在失败时。
如果允许呈现[渐进式JPEG](#),同时图片也是渐进式图片,`onIntermediateImageSet`会在每个扫描被解码后回调。具体图片的那个扫描会被解码,参见[渐进式JPEG图](#)
### 缩放和旋转图片
使用这个功能需要直接[创建 image request](#)。
### 缩放图片
#### 什么时候该修改图片尺寸
一般地,当所要显示的图片和显示区域大小不一致时,会按以下方式进行处理。
1. 从服务器下载小一些的图片
1. 显示时缩放图片
1. 调整图片尺寸大小
对于一个图片,如果服务器支持不同尺寸的缩略图,那么每次下载都选择尺寸最匹配的图片,这个不仅节省数据流量也节约本地储存和CPU。
如果服务器不支持,或者处理本地图片的话,第二个选择是[使用缩放类型](#)。缩放是用Androi内置的功能使图像和显示边界相符。在4.0之后,支持硬件加速。这在大部分情况下是最快,同时也是最高效的显示一张和显示边界大小相符的图片的方式。首先指定`layout_width`和`layout_width`为指定值,然后指定[缩放类型](#)
但当所要显示的图片比显示区域大许多的时候,不推荐这样做,缩放过程会导致大量的内存消耗。
这时,需要改变图片尺寸。
#### 修改图片尺寸
调整大小并不是修改原来的文件,而是在解码之前,在native内存中修改。
这个缩放方法,比Android内置的缩放范围更大。Android相机生成的照片一般尺寸都很大,需要调整大小之后才能被显示。
目前,仅仅支持JPEG格式的图片,同时,大部分的Android系统相机图片都是JPEG的。
如果要修改图片尺寸,创建`ImageRequest`时,提供一个 ResizeOptions:
~~~java
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);
自动旋转
如果看到的图片是侧着的,用户是难受的。许多设备会在JPEG文件的metadata中记录下照片的方向。如果你想图片呈现的方向和设备屏幕的方向一致,你可以简单地这样做到:
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
.setAutoRotateEnabled(true)
.build();
// as above
修改图片
有时,我们想对从服务器下载,或者本地的图片做些修改,比如在某个坐标统一加个网格什么的。这时使用后处理器(Postprocessor)便可达到目的。
例子:
给图片加个网格:
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);
注意点
图片在进入后处理器(postprocessor)的图片是原图的一个完整拷贝,原来的图片不受修改的影响。在5.0以前的机器上,拷贝后的图片也在native内存中。
在开始一个图片显示时,即使是反复显示同一个图片,在每次进行显示时,都需要指定后处理器。
对于同一个图片,每次显示,可以使用不同的后处理器。
Repeated Postprocessors
如果想对同一个图片进行多次后处理,那么继承 BaseRepeatedPostprocessor 即可。该类有一个update
方法,需要执行后处理时,调用该方法即可。
下面的例子展示了在运行时,后处理改变图片网格的颜色:
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();
// setPostprocessor as in above example
// 改变颜色
meshPostprocessor.setColor(Color.RED);
meshPostprocessor.setColor(Color.BLUE);
每个image request, 仍旧只有一个Postprocessor
,但是这个后处理器是状态相关了。
图片请求
如果你需要的ImageRequest
仅仅是一个URI,那么ImageRequest.fromURI
就足够了,在多图请求及图片复用中,有这样的用法。
否则,你需要ImageRequestBuilder
来做更多的事情。
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();
ImageRequest 的属性和成员
uri
- 唯一的必选的成员. 参考 支持的URIsautoRotateEnabled
- 是否支持自动旋转.progressiveEnabled
- 是否支持渐进式加载.postprocessor
- 后处理器(postprocess).resizeOptions
- 图片缩放选项,用前请先阅读缩放和旋转.
最低请求级别
Image pipeline 加载图片时有一套明确的请求流程
- 检查内存缓存,有如,立刻返回。这个操作是实时的。
- 检查未解码的图片缓存,如有,解码并返回。
- 检查磁盘缓存,如果有加载,解码,返回。
- 下载或者加载本地文件。调整大小和旋转(如有),解码并返回。对于网络图来说,这一套流程下来是最耗时的。
setLowestPermittedRequestLevel
允许设置一个最低请求级别,请求级别和上面对应地有以下几个取值:
BITMAP_MEMORY_CACHE
ENCODED_MEMORY_CACHE
DISK_CACHE
FULL_FETCH
如果你需要立即取到一个图片,或者在相对比较短时间内取到图片,否则就不显示的情况下,这非常有用。
自定义View
DraweeHolders
总有一些时候,DraweeViews
是满足不了需求的,在展示图片的时候,我们还需要展示一些其他的内容,或者支持一些其他的操作。在同一个View里,我们可能会想显示一张或者多张图。
在自定义View中,Fresco 提供了两个类来负责图片的展现:
DraweeHolder
单图情况下用。MultiDraweeHolder
多图情况下用。
更多建议: