Drawees 具有極大的可定制性。
下面的例子給出了可以配置的各種選項(xiàng):
<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"
/>
如果沒有在XML中聲明這兩個(gè)屬性,將無(wú)法正確加載圖像。
Drawees 不支持 wrap_content
屬性。
所下載的圖像可能和占位圖尺寸不一致,如果設(shè)置出錯(cuò)圖或者重試圖的話,這些圖的尺寸也可能和所下載的圖尺寸不一致。
如果大小不一致,圖像下載完之后,假設(shè)如果是wrap_content
,View將會(huì)重新layout,改變大小和位置。這將會(huì)導(dǎo)致界面跳躍。
只有希望顯示的固定寬高比時(shí),可以使用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);
mSimpleDraweeView.setImageURI(uri);
如果要更加復(fù)雜的配置,可使用ControllerBuilder;
一般情況下,在XML設(shè)置顯示效果即可, 如果想更多定制化,可以這樣:
創(chuàng)建一個(gè) builder 然后設(shè)置給 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);
對(duì)于同一個(gè)View,請(qǐng)不要多次調(diào)用setHierarchy
,即使這個(gè)View是可回收的。創(chuàng)建 DraweeHierarchy 的較為耗時(shí)的一個(gè)過(guò)程,應(yīng)該多次利用。
如果要改變所要顯示的圖片可使用setController
或者 setImageURI
。
DraweeHierarchy 的一些屬性可以在運(yùn)行時(shí)改變。
要改變這些屬性,首先獲取一個(gè)引用:
GenericDraweeHierarchy hierarchy = mSimpleDraweeView.getHierarchy();
修改占位圖為資源id:
hierarchy.setPlaceholderImage(R.drawable.placeholderId);
或者修改為一個(gè) Drawable:
Drawable drawable;
// 創(chuàng)建一個(gè)drawable
hierarchy.setPlaceholderImage(drawable);
修改縮放類型:
hierarchy.setActualImageScaleType(ScalingUtils.ScaleType.CENTER_INSIDE);
當(dāng)然,如果修改為 focusCrop,
需要指定一個(gè)居中點(diǎn):
hierarchy.setActualImageFocusPoint(point);
或者設(shè)置一個(gè)color filter:
ColorFilter filter;
// 創(chuàng)建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:
除了圓角顯示方式(原來(lái)為圓角的不能修改為圓圈,反之亦然),其他圓角相關(guān)的呈現(xiàn)參數(shù), 具體參見這里 是可以動(dòng)態(tài)修改的。
如下: 獲取DraweeHierarchy的圓角顯示參數(shù),修改圓角半徑為10。
RoundingParams roundingParams = hierarchy.getRoundingParams();
roundingParams.setCornersRadius(10);
hierarchy.setRoundingParams(roundingParams);
本頁(yè)說(shuō)明如何設(shè)置實(shí)現(xiàn)不同的圖片呈現(xiàn)效果。
除了要加載的圖片,其他各個(gè)設(shè)置都可以在xml中指定。在xml中指定的時(shí)候,可以是 drawable/
下的資源,也可以顏色。
在Java 代碼中也可以指定。如果需要 通過(guò)程序設(shè)定 的話會(huì)接觸到這個(gè)類: GenericDraweeHierarchyBuilder
通過(guò)代碼設(shè)置是,設(shè)置的值可以是資源id,也可以是 Drawable 的子類。
創(chuàng)建完 GenericDraweeHierarchy 之后,也可以通過(guò)該類的相關(guān)方法,重新設(shè)置一些效果。
大多數(shù)的用戶呈現(xiàn)不同效果的drawables都是可以縮放的.
除了需要加載的圖片是真正必須的,其他的都是可選的。如前所述,圖片可以來(lái)自多個(gè)地方。
所需加載的圖片實(shí)際是DraweeController的一個(gè)屬性,而不是 DraweeHierarchy 的屬性。
可使用setImageURI
方法或者通過(guò)設(shè)置 DraweeController 來(lái)進(jìn)行設(shè)置。
對(duì)于要加載的圖片,除了可以設(shè)置縮放類型外,DraweeHierarchy 還公開出一些其他方法用來(lái)控制顯示效果:
默認(rèn)的縮放類型是: centerCrop
在調(diào)用setController
或者 setImageURI
之后,占位圖開始顯示,直到圖片加載完成。
對(duì)于漸進(jìn)式格式的JPEG圖片,占位圖會(huì)顯示直到滿足已加載的圖片解析度到達(dá)設(shè)定值。
XML 中屬性值: placeholderImage
Hierarchy builder中的方法: setPlaceholderImage
Hierarchy method: setPlaceholderImage
默認(rèn)值: a transparent ColorDrawable
默認(rèn)縮放類型: centerInside
如果URI是無(wú)效的,或者下載過(guò)程中網(wǎng)絡(luò)不可用,將會(huì)導(dǎo)致加載失敗。當(dāng)加載圖片出錯(cuò)時(shí),你可以設(shè)置一個(gè)出錯(cuò)提示圖片。
XML 中屬性值: failureImage
Hierarchy builder中的方法: setFailureImage
默認(rèn)值: The placeholder image
默認(rèn)縮放類型: centerInside
在加載失敗時(shí),可以設(shè)置點(diǎn)擊重新加載。這時(shí)提供一個(gè)圖片,加載失敗時(shí),會(huì)顯示這個(gè)圖片(而不是失敗提示圖片),提示用戶點(diǎn)擊重試。
在ControllerBuilder 中如下設(shè)置:
.setTapToRetryEnabled(true)
加載失敗時(shí),image pipeline 會(huì)重試四次;如果還是加載失敗,則顯示加載失敗提示圖片。
XML 中屬性值: retryImage
Hierarchy builder中的方法: setRetryImage
默認(rèn)值: The placeholder image
默認(rèn)縮放類型: centerInside
設(shè)置一個(gè)進(jìn)度條圖片,提示用戶正在加載。目前,進(jìn)度條僅僅是提示正在loading,和加載進(jìn)度無(wú)關(guān)。
XML 中屬性值: progressBarImage
Hierarchy builder中的方法: setProgressBarImage
默認(rèn)值: None
默認(rèn)縮放類型: centerInside
背景圖會(huì)最先繪制,在XML中只可以指定一個(gè)背景圖,但是在JAVA代碼中,可以指定多個(gè)背景圖。
當(dāng)指定一個(gè)背景圖列表的時(shí)候,列表中的第一項(xiàng)會(huì)被首先繪制,繪制在最下層,然后依次往上繪制。
背景圖片不支持縮放類型,會(huì)被強(qiáng)制到Drawee
尺寸大小。
XML 中屬性值: backgroundImage
Hierarchy builder中的方法: setBackground,``setBackgrounds
默認(rèn)值: None
默認(rèn)縮放類型: N/A
疊加圖會(huì)最后被繪制。
和背景圖一樣,XML中只可以指定一個(gè),如果想指定多個(gè),可以通過(guò)JAVA代碼實(shí)現(xiàn)。
當(dāng)指定的疊加圖是一個(gè)列表的時(shí)候,列表第一個(gè)元素會(huì)被先繪制,最后一個(gè)元素最后被繪制到最上層。
同樣的,不支持各種縮放類型。
XML 中屬性值: overlayImage
Hierarchy builder中的方法: setOverlay,``setOverlays
默認(rèn)值: None
默認(rèn)縮放類型: N/A
同樣不支持縮放,用戶按壓DraweeView時(shí)呈現(xiàn)。
XML 中屬性值: pressedStateOverlayImage
Hierarchy builder中的方法: setPressedStateOverlay
默認(rèn)值: None
默認(rèn)縮放類型: N/A
對(duì)于 Drawee 的各種效果配置,其中一些是支持縮放類型的。
類型 | 描述 |
---|---|
center | 居中,無(wú)縮放 |
centerCrop | 保持寬高比縮小或放大,使得兩邊都大于或等于顯示邊界。居中顯示。 |
focusCrop | 同centerCrop, 但居中點(diǎn)不是中點(diǎn),而是指定的某個(gè)點(diǎn) |
centerInside | 使兩邊都在顯示邊界內(nèi),居中顯示。 如果圖尺寸大于顯示邊界,則保持長(zhǎng)寬比縮小圖片。 |
fitCenter | 保持寬高比,縮小或者放大,使得圖片完全顯示在顯示邊界內(nèi)。居中顯示 |
fitStart | 同上。但不居中,和顯示邊界左上對(duì)齊 |
fitEnd | 同fitCenter, 但不居中,和顯示邊界右下對(duì)齊 |
fitXY | 不保存寬高比,填充滿顯示邊界 |
none | 如要使用tile mode顯示, 需要設(shè)置為none |
這些縮放類型和Android ImageView 支持的縮放類型幾乎一樣.
唯一不支持的縮放類型是matrix.
Fresco 提供了focusCrop
作為補(bǔ)充。通常這個(gè)縮放效果更佳。
centerCrop
縮放模式會(huì)保持長(zhǎng)寬比,縮放圖片,填充滿顯示邊界,居中顯示。這個(gè)縮放模式在通常情況下很有用。
但是對(duì)于人臉等圖片時(shí),一味地居中顯示,這個(gè)模式可能會(huì)裁剪掉一些有用的信息。
以人臉圖片為例,借助一些類庫(kù),我們可以識(shí)別出人臉?biāo)谖恢?。如果可以設(shè)置以人臉位置居中裁剪顯示,那么效果會(huì)好很多。
Fresco的focusCrop縮放模式正是為此而設(shè)計(jì)。只要提供一個(gè)居中聚焦點(diǎn),顯示時(shí)就會(huì)盡量以此點(diǎn)為中心。
居中點(diǎn)是以相對(duì)方式給出的,比如(0.5f, 0.5f)就是居中顯示,(0f, 0f)就是左上對(duì)齊顯示。
如果要使用此縮放模式,首先指定縮放模式。在XML:
fresco:actualImageScaleType="focusCrop"
在Java代碼中
PointF focusPoint;
// your app populates the focus point
mSimpleDraweeView
.getHierarchy()
.setActualImageFocusPoint(focusPoint);
如果你要使用tile mode進(jìn)行顯示,那么需要將scale type 設(shè)置為none.
Drawee 輕松支持圓角顯示,并且顯示圓角時(shí),并不復(fù)制和修改Bitmap對(duì)象,那樣太耗費(fèi)內(nèi)存。
圓角實(shí)際有2中呈現(xiàn)方式:
roundAsCircle
為trueroundedCornerRadius
設(shè)置圓角時(shí),支持4個(gè)角不同的半徑。XML中無(wú)法配置,但可在Java代碼中配置。
可使用以下兩種方式:
solid color
來(lái)繪制圓角。但是背景需要固定成指定的顏色。在XML中指定 roundWithOverlayColor
, 或者通過(guò)調(diào)用setOverlayColor
來(lái)完成此設(shè)定。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"
在創(chuàng)建 DraweeHierarchy 時(shí),可以給GenericDraweeHierarchyBuilder
指定一個(gè) RoundingParams 用來(lái)繪制圓角效果。
RoundingParams roundingParams = RoundingParams.fromCornersRadius(7f);
roundingParams.setOverlayColor(R.color.green);
// 或用 fromCornersRadii 以及 asCircle 方法
genericDraweeHierarchyBuilder
.setRoundingParams(roundingParams);
你也可以在運(yùn)行時(shí),改變圓角效果
RoundingParams roundingParams =
mSimpleDraweeView.getHierarchy().getRoundingParams();
roundingParams.setBorder(R.color.red, 1.0);
roundingParams.setRoundAsCircle(true);
mSimpleDraweeView.getHierarchy().setRoundingParams(roundingParams);
在運(yùn)行時(shí),不能改變呈現(xiàn)方式: 原本是圓角,不能改為圓圈。
SimpleDraweeView
有兩個(gè)方法可以設(shè)置所要加載顯示圖片,簡(jiǎn)單的方法就是setImageURI
。
如果你需要對(duì)加載顯示的圖片做更多的控制和定制,那就需要用到 DraweeController,本頁(yè)說(shuō)明如何使用。
首先,創(chuàng)建一個(gè)DraweeController, 然后傳遞圖片加載請(qǐng)求給 PipelineDraweeControllerBuilder
隨后,你可以控制controller的其他選項(xiàng)了:
ControllerListener listener = new BaseControllerListener() {...}
?
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(uri)
.setTapToRetryEnabled(true)
.setOldController(mSimpleDraweeView.getController())
.setControllerListener(listener)
.build();
?
mSimpleDraweeView.setController(controller);
在指定一個(gè)新的controller的時(shí)候,使用setOldController
,這可節(jié)省不必要的內(nèi)存分配。
在更進(jìn)一步的用法中,你需要給Image pipeline 發(fā)送一個(gè)ImageRequest。下面是一個(gè)圖片加載后,使用后處理器(postprocessor) 進(jìn)行圖片后處理的例子.
Uri uri;
Postprocessor myPostprocessor = new Postprocessor() { ... }
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
.setPostprocessor(myPostprocessor)
.build();
?
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setImageRequest(request)
.setOldController(mSimpleDraweeView.getController())
// 其他設(shè)置
.build();
注意: 本頁(yè)提及的API僅是初步設(shè)計(jì),后續(xù)可能變動(dòng)
Fresco 支持漸進(jìn)式的網(wǎng)絡(luò)JPEG圖。在開始加載之后,圖會(huì)從模糊到清晰漸漸呈現(xiàn)。
你可以設(shè)置一個(gè)清晰度標(biāo)準(zhǔn),在未達(dá)到這個(gè)清晰度之前,會(huì)一直顯示占位圖。
漸進(jìn)式JPEG圖僅僅支持網(wǎng)絡(luò)圖。
配置Image pipeline時(shí) 需要傳遞一個(gè) ProgressiveJpegConfig 的實(shí)例。
這個(gè)實(shí)例需要完成兩個(gè)事情:1. 返回下一個(gè)需要解碼的掃描次數(shù)2. 確定多少個(gè)掃描次數(shù)之后的圖片才能開始顯示。
下面的實(shí)例中,為了實(shí)現(xiàn)節(jié)省CPU,并不是每個(gè)掃描都進(jìn)行解碼。
注意:
getNextScanNumberToDecode
, 等待掃描值大于返回值,才有可能進(jìn)行解碼。假設(shè),隨著下載的進(jìn)行,下載完的掃描序列如下: 1, 4, 5, 10
。那么:
getNextScanNumberToDecode
返回為2, 因?yàn)槌跏紩r(shí),解碼的掃描數(shù)為0。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();
除了自己實(shí)現(xiàn)ProgressiveJpegConfig, 也可以直接使用 SimpleProgressiveJpegConfig
目前,我們必須顯式地在加載時(shí),允許漸進(jìn)式JPEG圖片加載。
Uri uri;
ImageRequest request = ImageRequestBuilder
.newBuilderWithSource(uri)
.setProgressiveRenderingEnabled(true)
.build();
PipelineDraweeController controller = Fresco.newControllerBuilder()
.setImageRequest(requests)
.setOldController(mSimpleDraweeView.getController())
.build();
?
mSimpleDraweeView.setController(controller);
我們希望在后續(xù)的版本中,在setImageURI
方法中可以直接支持漸進(jìn)式圖片加載。
Fresco 支持GIF和WebP 格式圖片;支持WebP 格式的動(dòng)畫圖也支持(包括擴(kuò)展WebP 格式),支持2.3及其以后那些沒有原生WebP支持的系統(tǒng)。
如果你希望圖片下載完之后自動(dòng)播放,同時(shí),當(dāng)View從屏幕移除時(shí),停止播放,只需要在image request 中簡(jiǎn)單設(shè)置,如下:
Uri uri;
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
.setAutoPlayAnimation(true)
. // other setters
.build();
?
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setImageRequest(request)
. // other setters
.build();
mSimpleDraweeView.setController(controller);
也許,你希望在圖片加載完之后,手動(dòng)控制動(dòng)畫的播放,那么這樣做:
ControllerListener controllerListener = new BaseControllerListener() {
@Override
public void onFinalImageSet(
String id,
@Nullable ImageInfo imageInfo,
@Nullable Animatable anim) {
if (anim != null) {
// 根據(jù)業(yè)務(wù)邏輯,在合適的時(shí)機(jī)播放動(dòng)畫。
}
};
?
Uri uri;
PipelineDraweeController controller = Fresco.newControllerBuilder()
.setControllerListener(controllerListener)
.setUri(uri);
// other setters
.build();
mSimpleDraweeView.setController(controller);
另外,controller提供對(duì)Animatable 的訪問。
如果有可用動(dòng)畫的話,可對(duì)動(dòng)畫進(jìn)行靈活的控制:
Animatable animation = mSimpleDraweeView.getController().getAnimatable();
if (animation != null) {
// 開始播放
animation.start();
// 一段時(shí)間之后,根據(jù)業(yè)務(wù)邏輯,停止播放
animation.stop();
}
多圖請(qǐng)求需 自定義ImageRequest.
如果你要顯示一張高分辨率的圖,但是這張圖下載比較耗時(shí)。你可以在下載前,先提供一張很快能下載完的小縮略圖。這比一直顯示占位圖,用戶體驗(yàn)會(huì)好很多。
這時(shí),你可以設(shè)置兩個(gè)圖片的URI,一個(gè)是低分辨率的縮略圖,一個(gè)是高分辨率的圖。
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 會(huì)立刻返回一個(gè)縮略圖。完整的清晰大圖,在decode完之后再顯示。
Uri uri;
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
.setLocalThumbnailPreviewsEnabled(true)
.build();
?
PipelineDraweeController controller = Fresco.newControllerBuilder()
.setImageRequest(request)
.setOldController(mSimpleDraweeView.getController())
.build();
mSimpleDraweeView.setController(controller);
大部分的時(shí)候,一個(gè)圖片可能會(huì)對(duì)應(yīng)有多個(gè)URI,比如:
對(duì)于一個(gè)URI,image pipeline 會(huì)依次檢查內(nèi)存,磁盤,如果沒有從網(wǎng)絡(luò)下載。
而對(duì)于一個(gè)圖片的多個(gè)URI,image pipeline 會(huì)先檢查他們是否在內(nèi)存中。如果沒有任何一個(gè)是在內(nèi)存中的,會(huì)檢查是否在本地存儲(chǔ)中。如果也沒有,才會(huì)執(zhí)行網(wǎng)絡(luò)下載。
但凡有任何一個(gè)檢查發(fā)現(xiàn)在內(nèi)存或者在本地存儲(chǔ)中,都會(huì)進(jìn)行復(fù)用。列表順序就是要顯示的圖片的優(yōu)先順序。
使用時(shí),創(chuàng)建一個(gè)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);
你也許想在圖片下載完成或者下載失敗之后,做一些其他事情。
圖片是后臺(tái)線程異步加載的,我們可以使用一個(gè)ControllerListener
實(shí)現(xiàn)事件的監(jiān)聽。
_在監(jiān)聽事件回調(diào)時(shí),無(wú)法修改圖片,如果需要修改圖片,可使用后處理器(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);
對(duì)所有的圖片加載,`onFinalImageSet` 或者 `onFailure` 都會(huì)被觸發(fā)。前者在成功時(shí),后者在失敗時(shí)。
如果允許呈現(xiàn)[漸進(jìn)式JPEG](#),同時(shí)圖片也是漸進(jìn)式圖片,`onIntermediateImageSet`會(huì)在每個(gè)掃描被解碼后回調(diào)。具體圖片的那個(gè)掃描會(huì)被解碼,參見[漸進(jìn)式JPEG圖](#)
### 縮放和旋轉(zhuǎn)圖片
使用這個(gè)功能需要直接[創(chuàng)建 image request](#)。
### 縮放圖片
#### 什么時(shí)候該修改圖片尺寸
一般地,當(dāng)所要顯示的圖片和顯示區(qū)域大小不一致時(shí),會(huì)按以下方式進(jìn)行處理。
1. 從服務(wù)器下載小一些的圖片
1. 顯示時(shí)縮放圖片
1. 調(diào)整圖片尺寸大小
對(duì)于一個(gè)圖片,如果服務(wù)器支持不同尺寸的縮略圖,那么每次下載都選擇尺寸最匹配的圖片,這個(gè)不僅節(jié)省數(shù)據(jù)流量也節(jié)約本地儲(chǔ)存和CPU。
如果服務(wù)器不支持,或者處理本地圖片的話,第二個(gè)選擇是[使用縮放類型](#)??s放是用Androi內(nèi)置的功能使圖像和顯示邊界相符。在4.0之后,支持硬件加速。這在大部分情況下是最快,同時(shí)也是最高效的顯示一張和顯示邊界大小相符的圖片的方式。首先指定`layout_width`和`layout_width`為指定值,然后指定[縮放類型](#)
但當(dāng)所要顯示的圖片比顯示區(qū)域大許多的時(shí)候,不推薦這樣做,縮放過(guò)程會(huì)導(dǎo)致大量的內(nèi)存消耗。
這時(shí),需要改變圖片尺寸。
#### 修改圖片尺寸
調(diào)整大小并不是修改原來(lái)的文件,而是在解碼之前,在native內(nèi)存中修改。
這個(gè)縮放方法,比Android內(nèi)置的縮放范圍更大。Android相機(jī)生成的照片一般尺寸都很大,需要調(diào)整大小之后才能被顯示。
目前,僅僅支持JPEG格式的圖片,同時(shí),大部分的Android系統(tǒng)相機(jī)圖片都是JPEG的。
如果要修改圖片尺寸,創(chuàng)建`ImageRequest`時(shí),提供一個(gè) 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);
如果看到的圖片是側(cè)著的,用戶是難受的。許多設(shè)備會(huì)在JPEG文件的metadata中記錄下照片的方向。如果你想圖片呈現(xiàn)的方向和設(shè)備屏幕的方向一致,你可以簡(jiǎn)單地這樣做到:
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
.setAutoRotateEnabled(true)
.build();
// as above
有時(shí),我們想對(duì)從服務(wù)器下載,或者本地的圖片做些修改,比如在某個(gè)坐標(biāo)統(tǒng)一加個(gè)網(wǎng)格什么的。這時(shí)使用后處理器(Postprocessor)便可達(dá)到目的。
給圖片加個(gè)網(wǎng)格:
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);
圖片在進(jìn)入后處理器(postprocessor)的圖片是原圖的一個(gè)完整拷貝,原來(lái)的圖片不受修改的影響。在5.0以前的機(jī)器上,拷貝后的圖片也在native內(nèi)存中。
在開始一個(gè)圖片顯示時(shí),即使是反復(fù)顯示同一個(gè)圖片,在每次進(jìn)行顯示時(shí),都需要指定后處理器。
對(duì)于同一個(gè)圖片,每次顯示,可以使用不同的后處理器。
如果想對(duì)同一個(gè)圖片進(jìn)行多次后處理,那么繼承 BaseRepeatedPostprocessor 即可。該類有一個(gè)update
方法,需要執(zhí)行后處理時(shí),調(diào)用該方法即可。
下面的例子展示了在運(yùn)行時(shí),后處理改變圖片網(wǎng)格的顏色:
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);
每個(gè)image request, 仍舊只有一個(gè)Postprocessor
,但是這個(gè)后處理器是狀態(tài)相關(guān)了。
如果你需要的ImageRequest
僅僅是一個(gè)URI,那么ImageRequest.fromURI
就足夠了,在多圖請(qǐng)求及圖片復(fù)用中,有這樣的用法。
否則,你需要ImageRequestBuilder
來(lái)做更多的事情。
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();
uri
- 唯一的必選的成員. 參考 支持的URIsautoRotateEnabled
- 是否支持自動(dòng)旋轉(zhuǎn).progressiveEnabled
- 是否支持漸進(jìn)式加載.postprocessor
- 后處理器(postprocess).resizeOptions
- 圖片縮放選項(xiàng),用前請(qǐng)先閱讀縮放和旋轉(zhuǎn).Image pipeline 加載圖片時(shí)有一套明確的請(qǐng)求流程
setLowestPermittedRequestLevel
允許設(shè)置一個(gè)最低請(qǐng)求級(jí)別,請(qǐng)求級(jí)別和上面對(duì)應(yīng)地有以下幾個(gè)取值:
BITMAP_MEMORY_CACHE
ENCODED_MEMORY_CACHE
DISK_CACHE
FULL_FETCH
如果你需要立即取到一個(gè)圖片,或者在相對(duì)比較短時(shí)間內(nèi)取到圖片,否則就不顯示的情況下,這非常有用。
總有一些時(shí)候,DraweeViews
是滿足不了需求的,在展示圖片的時(shí)候,我們還需要展示一些其他的內(nèi)容,或者支持一些其他的操作。在同一個(gè)View里,我們可能會(huì)想顯示一張或者多張圖。
在自定義View中,F(xiàn)resco 提供了兩個(gè)類來(lái)負(fù)責(zé)圖片的展現(xiàn):
DraweeHolder
單圖情況下用。MultiDraweeHolder
多圖情況下用。
更多建議: