这几天研究了Fresco的用法,如果仅仅是加载图片的话,访问第一篇即可,本篇整理了其更多的知识点。
1. DraweeView 用来对图片的显示,就是一个ImageView,可在XML中直接使用,可设置属性
-- SimpleDraweeView
2. DraweeHierarchy -- 对图片属性的设置 上篇也讲到其使用方法 访问第一篇即可
-- GenericDraweeHierarchy 通过GenericDraweeHierarchyBuilder.build获得
3. DraweeController -- 对图片更多的控制,比如设置点击重试是否开启,设置图片下载的监听,设置URI
-- PipelineDraweeController 通过DraweeControllerBuilder.build() 获得 使用方式如下:
Uri uri = Uri.parse(url); ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri).build(); PipelineDraweeController draweeController = (PipelineDraweeController) Fresco.newDraweeControllerBuilder() .setImageRequest(request).setAutoPlayAnimations(true).setTapToRetryEnabled(true).build(); mDraweeView.setController(draweeController);
4. Listeners
-- ControllerListener 可监听图片的下载 使用方式如下:
ControllerListener controllerListener = new BaseControllerListener所有的图片加载,onFinalImageSet 或者 onFailure 都会被触发。前者在成功时,后者在失败时。(){ @Override public void onSubmit(String id, Object callerContext) { super.onSubmit(id, callerContext); } @Override public void onFinalImageSet(String id, ImageInfo imageInfo, Animatable animatable) { super.onFinalImageSet(id, imageInfo, animatable); Log.d("stormxz", "onFinalImageSet 成功"); } @Override public void onIntermediateImageSet(String id, ImageInfo imageInfo) { super.onIntermediateImageSet(id, imageInfo); } @Override public void onIntermediateImageFailed(String id, Throwable throwable) { super.onIntermediateImageFailed(id, throwable); } @Override public void onFailure(String id, Throwable throwable) { super.onFailure(id, throwable); Log.d("stormxz", "onFailure 失败"); } @Override public void onRelease(String id) { super.onRelease(id); } }; DraweeController draweeController = (DraweeController) Fresco.newDraweeControllerBuilder() .setUri(Uri.parse("http://img3.redocn.com/tupian/20150312/haixinghezhenzhubeikeshiliangbeijing_3937174.jpg")) //需要加载图片的uri .setTapToRetryEnabled(true) //设置点击重试是否开启 .setControllerListener(controllerListener) //设置监听 .setOldController(simpleDraweeView.getController()).build(); simpleDraweeView.setController(draweeController);
特别注意:Fresco 不支持 相对路径的URI. 所有的 URI 都必须是绝对路径,并且带上该 URI 的 scheme。
注意,只有图片资源才能使用在Image pipeline中,比如(PNG)。其他资源类型,比如字符串,或者XML Drawable在Image pipeline中没有意义。所以加载的资源不支持这些类型。
像ShapeDrawable这样声明在XML中的drawable可能引起困惑。注意到这毕竟不是图片。如果想把这样的drawable作为图像显示,那么把这个drawable设置为占位图,然后把URI设置为null。
上面官网的话,简单点说就是,1. URI中需传入真实图片的路径 2. 想直接使用Drawable,使用SimpleDraweeView中占位符图片属placeholderImage
ImageDecodeOptions decodeOptions = ImageDecodeOptions.newBuilder() .setBitmapConfig() //配置bitmapConfig .setUseLastFrameForPreview() //是否使用最后一帧作为显示 .setCustomImageDecoder() .setDecodePreviewFrame() .build();
ImageRequest request = ImageRequestBuilder .newBuilderWithSource(uri) //从那边访问 .setImageDecodeOptions(decodeOptions) //图片操作 .setAutoRotateEnabled(true) //是否支持旋转 .setLocalThumbnailPreviewsEnabled(true) //设置缩略图 .setLowestPermittedRequestLevel(ImageRequest.RequestLevel.FULL_FETCH) //设置最低请求级别,与Image pipeine相关 .setProgressiveRenderingEnabled(false) //是否支持渐进式加载 .setResizeOptions(new ResizeOptions(width, height)) //缩放,旋转 .setPostprocessor() //后处理器 .build();
最后将ImageRequest设置到DraweeController中
ps: 必选项,uri,其他为可选项
当网络或本地访问图片后,可对图片Bitmap进行修改操作,这是就要用到PostProcessor
采用官网demo 给图片加上红色网格
Postprocessor redMeshPostprocessor = new BasePostprocessor() { @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); } } } };
将对象redMeshPostProcessor 设置到ImageRuest中
效果如下:
ps: 图片在进入后处理器(postprocessor)的图片是原图的一个完整拷贝,原来的图片不受修改的影响。在5.0以前的机器上,拷贝后的图片也在native内存中。
在开始一个图片显示时,即使是反复显示同一个图片,在每次进行显示时,都需要指定后处理器。对于同一个图片,每次显示可以使用不同的后处理器。
后处理器现在不支持 动图加载 。
public void process(Bitmap destBitmap, Bitmap sourceBitmap) { for (int x = 0; x < destBitmap.getWidth(); x++) { for (int y = 0; y < destBitmap.getHeight(); y++) { destBitmap.setPixel(destBitmap.getWidth() - x, y, sourceBitmap.getPixel(x, y)); } } }ps:源图片和目标图片具有相同的大小。
@Override public CloseableReferenceps:process( Bitmap sourceBitmap, PlatformBitmapFactory bitmapFactory) { CloseableReference bitmapRef = bitmapFactory.createBitmap( sourceBitmap.getWidth() / 2, sourceBitmap.getHeight() / 2); try { Bitmap destBitmap = bitmapRef.get(); for (int x = 0; x < destBitmap.getWidth(); x+=2) { for (int y = 0; y < destBitmap.getHeight(); y+=2) { destBitmap.setPixel(x, y, sourceBitmap.getPixel(x, y)); } } return CloseableReference.cloneOrNull(bitmapRef); } finally { CloseableReference.closeSafely(bitmapRef); } }
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(); meshPostprocessor.setColor(Color.RED); meshPostprocessor.setColor(Color.BLUE);so 每个 image request, 应该只有一个Postprocessor,但是这个后处理器是可控制的。
public static abstract class AbstractScaleType implements ScaleType { @Override public Matrix getTransform(Matrix outTransform, Rect parentRect, int childWidth, int childHeight, float focusX, float focusY) { // 取宽度和高度需要缩放的倍数中最大的一个 final float sX = (float) parentRect.width() / (float) childWidth; final float sY = (float) parentRect.height() / (float) childHeight; float scale = Math.min(scaleX, scaleY); // 计算为了均分空白区域,需要偏移的x、y方向的距离 float dx = parentRect.left + (parentRect.width() - childWidth * scale) * 0.5f; float dy = parentRect.top + (parentRect.height() - childHeight * scale) * 0.5f; // 最后我们应用它 outTransform.setScale(scale, scale); outTransform.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f)); return outTransform; } }
Uri lowResUri, highResUri; DraweeController controller = Fresco.newDraweeControllerBuilder() .setLowResImageRequest(ImageRequest.fromUri(lowResUri)) .setImageRequest(ImageRequest.fromUri(highResUri)) .setOldController(mSimpleDraweeView.getController()) .build(); mSimpleDraweeView.setController(controller);ps: 动图无法在低分辨率那一层显示。
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);
Uri uri; ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri) .setProgressiveRenderingEnabled(true) .build(); DraweeController controller = Fresco.newDraweeControllerBuilder() .setImageRequest(request) .setOldController(mSimpleDraweeView.getController()) .build(); mSimpleDraweeView.setController(controller);
Uri uri; DraweeController controller = Fresco.newDraweeControllerBuilder() .setUri(uri) .setAutoPlayAnimations(true) . // 其他设置(如果有的话) .build(); mSimpleDraweeView.setController(controller);
ControllerListener controllerListener = new BaseControllerListener控制如下:() { @Override public void onFinalImageSet( String id, @Nullable ImageInfo imageInfo, @Nullable Animatable anim) { if (anim != null) { // 其他控制逻辑 anim.start(); } } }; Uri uri; DraweeController controller = Fresco.newDraweeControllerBuilder() .setUri(uri) .setControllerListener(controllerListener) // 其他设置(如果有的话) .build(); mSimpleDraweeView.setController(controller);
Animatable animatable = mSimpleDraweeView.getController().getAnimatable(); if (animatable != null) { animatable.start(); // later animatable.stop(); }