Fresco 实践总结,阿里 P7 大牛亲自教你
先给出支持的 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
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
评论