写点什么

Fresco 实践总结,阿里 P7 大牛亲自教你

用户头像
Android架构
关注
发布于: 23 分钟前


先给出支持的 URI 格式列表(列表来自 fresco-cn.org):


| Type | Scheme | Sample |


| --- | --- | --- |


| http 远程图片 | http://或者 https:// | HttpURLConnection 或者 OkHttp |


| 本地文件 | file:// | FileInputStream |


| Content provider | content:// | ContentResolver |


| res 目录下的资源 | res:// | Resources.openRawResource |


| asset 目录下的资源 | asset:// | AssetManager |


| Uri 中指定图片数据 | data:mime/type;base64, | 数据类型必须符合[rfc2397](


)规定 (仅支持 UTF-8) |

SimpleDraweeView

实际开发中,如果没有特殊需求,我们一般使用SimpleDraweeView来占位,传统的图片加载框架一般是使用ImageView,例如:


`<ImageView


.../>`


  • 1

  • 2


在使用Fresco时我们一般使用SimpleDraweeView,它也是继承ImageView的:


`<com.facebook.drawee.view.SimpleDraweeView


android:id="@+id/iv_head_background"


android:layout_width="match_parent"


android:layout_height="@dimen/dp_200"/>`


  • 1

  • 2

  • 3

  • 4


把它当成我们平常使用的ImageView即可,不过我们要注意Fresco不支持wrap_content(具体原因[看这里](


)),需要使用match_parent或者显示指定 view 宽高,有些同学看到这个就很头疼了,但是这真的不是什么问题,下面给出解决方案:


一、由服务器返回 URL 时返回图片的宽高信息?


平常我们服务器这样返回图片 url 的:


`{


"name":"严振杰",


"head":"http://www.yanzhenjie.com/images/main/yzj_head.png" }`


  • 1

  • 2

  • 3

  • 4


使用 Fresco 我们可以把一个图片 url 当成一个对象包裹起来:


`{


"name":"严振杰",


"head":


{


"url":"http://www.yanzhenjie.com/images/main/yzj_head.png",


"width":"500",


"height":"500" } }`


  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9


或者在 URL 后面跟一个宽高的参数:


`{


"name":"严振杰",


"head":"http://www.yanzhenjie.com/images/main/yzj_head.png?width=500&height=500" }`


  • 1

  • 2

  • 3

  • 4


二、根据设计师的给的尺寸,预先设置图片宽高?


设计师设计 UI 的时候肯定会用一个屏幕作为标准,比如 iOS 的750*1340,或者 Android 的720*1280,我们可以根据设计图和手机实际宽高计算出 View 在手机中应有的宽高,见下面的代码。


最后:我们在解析出来宽高后,我们可以动态的设置SimpleDraweeView的宽高:


`/**


  • 设置 view 大小。

  • @param view View。

  • @param width 指定宽。

  • @param width 指定高。


*/


public static void requestLayout(View view, int width, int height) {


ViewGroup.LayoutParams layoutParams = view.getLayoutParams();


if (layoutParams == null) {


layoutParams = new ViewGroup.LayoutParams(width, height);


view.setLayoutParams(layoutParams);


} else {


view.getLayoutParams().width = width;


view.getLayoutParams().height = height;


view.requestLayout();


}


}


/**


  • 根据设计图宽高,计算出 View 在该屏幕上的实际宽高。

  • @param width 设计图中 View 宽。

  • @param height 设计图中 View 高。


*/


public static void calcRealSizeByDesign(View view, int width, int height) {


int realWidth, realHeight;


realWidth = 设备屏幕宽度 * width / 设计图屏幕宽度;


realHeight = measure[0] * height / width;


requestLayout(view, realWidth, realHeight);


}`


  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

  • 29

  • 30

  • 31


基础配置和注意的地方讲完了,那么下面就是重头戏了,如何加载图片。

一、加载 http/https 远程图片

`/**


  • 显示 http 或者 https 远程图片。

  • @param draweeView imageView。

  • @param url 连接地址。


*/


public static void showUrl(SimpleDraweeView draweeView, String url) {


try {


draweeView.setImageURI(Uri.parse(url));


} catch (Exception e) {


e.printStackTrace();


}


}`


  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

二、显示本地图片

这里就有个坑了,先看一下下面我写了两个方法,一个需要传入 View 的实际宽高,一个不需要。上面已经说了,SimpleDraweeView需要在 xml 中、java 中指定它的宽高,或者是使用match_parent


这里需要注意,1. 如果 view 指定的宽高不是match_parent则直接调用第二个不需要传入宽高的发那个发,如果为SimpleDraweeView写的宽高是match_parent时,加载图片需要告诉Fresco你的 View 在屏幕上的实际宽高是多少,否则是不能加载出来的。


比如,你的SimpleDraweeView是全屏的,那么你就填入屏幕的宽高,如果不是全屏,就利用上面讲的方法测量出 View 的实际宽高后传入。


`/**


  • 显示一个本地图片。

  • @param draweeView imageView。

  • @param path 路径。

  • @param width 实际宽。

  • @param height 实际高度。


*/


public static void showFile(SimpleDraweeView draweeView, String path, int width, int height) {


try {


Uri uri = Uri.parse("file://" + path);


ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)


.setResizeOptions(new ResizeOptions(width, height))


.build();


AbstractDraweeController controller = Fresco.newDraweeControllerBuilder()


.setOldController(draweeView.getController())


.setImageRequest(request)


.build();


draweeView.setController(controller);


} catch (Exception e) {


e.printStackTrace();


}


}


/**


  • 显示本地图片。

  • @param draweeView imageView。

  • @param path 路径。


*/


public static void showFile(SimpleDraweeView draweeView, String path) {


try {


Uri uri = Uri.parse("file://" + path);


draweeView.setImageURI(uri);


} catch (Exception e) {


e.printStackTrace();


}


}`


  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25

  • 26

  • 27

  • 28

  • 29

  • 30

  • 31

  • 32

  • 33

  • 34

  • 35

  • 36

  • 37

  • 38

三、显示 res 中图片

这里要注意,我们在为 res 中的图片生成 Uri 的时候:


Uri uri = Uri.parse("res://包名(任何字符串或者留空)/" + R.drawable.ic_launcher);


  • 1


所以我们一般留空,因此我们的代码看起来是下面的样子:


`/**


  • 显示一个 Res 中的图片。

  • @param draweeView ImageView。

  • @param resId 资源 ID。


*/


public static void showRes(SimpleDraweeView draweeView, @DrawableRes int resId) {


try {


// 你没看错,这里是三个///。


draweeView.setImageURI(Uri.parse("res:///" + resId));


} catch (Exception e) {


e.printStackTrace();


}


}`


  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

四、显示 ContentProvider 图片

`/**


  • 显示 content provider 图片。

  • @param draweeView image view。

  • @param path 路径。


*/


public static void showContentProvider(SimpleDraweeView draweeView, String path) {


try {


draweeView.setImageU


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


RI(Uri.parse("content://" + path));


} catch (Exception e) {


e.printStackTrace();


}


}`


  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

五、显示 assets 中的图片

`/**


  • 显示 Assets 中的图片。

  • @param draweeView ImageView.

  • @param path 路径。


*/


public static void showAsset(SimpleDraweeView draweeView, String path) {


try {


draweeView.setImageURI(Uri.parse("asset://" + path));


} catch (Exception e) {


e.printStackTrace();


}


}`


  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13


你以为到这里就完了吗?并没有,继续看。


一些默认属性的设置




`<com.facebook.drawee.view.SimpleDraweeView


android:layout_width="20dp"


android:layout_height="20dp"


fresco:fadeDuration="300" // 淡出时间,毫秒。


fresco:actualImageScaleType="focusCrop" // 等同于 android:scaleType。


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" // 背景图,不会被 View 遮挡。


fresco:roundAsCircle="false" // 是否是圆形图片。


fresco:roundedCornerRadius="1dp" // 四角圆角度数,如果是圆形图片,这个属性被忽略。


fresco:roundTopLeft="true" // 左上角是否圆角。


fresco:roundTopRight="false" // 右上角是否圆角。


fresco:roundBottomLeft="false" // 左下角是否圆角。


fresco:roundBottomRight="true" // 左下角是否圆角。


fresco:roundingBorderWidth="2dp" // 描边的宽度。


fresco:roundingBorderColor="@color/border_color" 描边的颜色。


/>`


  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 22

  • 23

  • 24

  • 25


xml 中可以配置,在 Java 代码中也是可以配置的,我这里列出一部分 API:


`SimpleDraweeView simpleDraweeView = new SimpleDraweeView(context);


simpleDraweeView.setLayoutParams(new ViewGroup.LayoutParams(-1, -1));


GenericDraweeHierarchy hierarchy = new GenericDraweeHierarchyBuilder(context.getResources())


.setActualImageScaleType(ScalingUtils.ScaleType.FIT_CENTER)


.setPlaceholderImage(R.drawable.fresco_failed)


.setPlaceholderImageScaleType(ScalingUtils.ScaleType.FIT_XY)


.setFailureImage(R.drawable.fresco_failed)


.setPressedStateOverlay(ResCompat.getDrawable(R.drawable.transparent_half_1))


.setFailureImageScaleType(ScalingUtils.ScaleType.FIT_XY)


.build();


simpleDraweeView.setHierarchy(hierarchy);


// load image from ...`


  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14


一些特殊效果




第一个,先来一个圆形图片带白色的边:



综合上面的属性这里就不多解释了:


`<com.facebook.drawee.view.SimpleDraweeView


android:id="@+id/iv_user_fund_user_head"


android:layout_width="80dp"


android:layout_height="80dp"


fresco:roundAsCircle="true" // 圆形图片。


fresco:roundingBorderColor="@color/white" // 白色描边。


fresco:roundingBorderWidth="2dp"/> // 描边宽度。`


  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7


第二个,Fresco 高斯模糊:



`/**


  • 以高斯模糊显示。

  • @param draweeView View。

  • @param url url.

  • @param iterations 迭代次数,越大越魔化。

  • @param blurRadius 模糊图半径,必须大于 0,越大越模糊。


*/


public static void showUrlBlur(SimpleDraweeView draweeView, String url, int iterations, int blurRadius) {


try {


Uri uri = Uri.parse(url);


ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)


.setPostprocessor(new IterativeBoxBlurPostProcessor(iterations, blurRadius))


.build();


AbstractDraweeController controller = Fresco.newDraweeControllerBuilder()


.setOldController(draweeView.getController())


.setImageRequest(request)


.build();


draweeView.setController(controller);


} catch (Exception e) {


e.printStackTrace();


}


}`


  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Fresco实践总结,阿里P7大牛亲自教你