- 版权声明:转载必须注明本文转自严振杰的博客:http://blog.yanzhenjie.com
参考Yw_Ambition的博客https://blog.csdn.net/yw59792649/article/details/78921025
参考博客:https://blog.csdn.net/xiaoqiang_0719/article/details/52437780
Fresco图片加载的方法在网上有各种各样的方式,我自己看着写了一个自己的方法,包括了自己找的的和用到的总结的一下
Fresco开源地址:https://github.com/facebook/fresco
Fresco文档地址:https://www.fresco-cn.org
依赖Fresco
// 一般依赖:
implementation 'com.facebook.fresco:fresco:1.11.0'
// 如果需要支持gif,再添加:
implementation 'com.facebook.fresco:animated-gif:1.10.0'
权限
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
初始化
建议在App启动就初始化,记得在清单文件注册Application。
一般初始化:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
Fresco.initialize(this);
}
}
高级初始化-配置缓存文件夹
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
//设置磁盘缓存
DiskCacheConfig image = DiskCacheConfig.newBuilder(this)
.setBaseDirectoryName("images")
.setBaseDirectoryPath(Environment.getExternalStorageDirectory())
.build();
//设置磁盘缓存的配置,生成配置文件
ImagePipelineConfig config = ImagePipelineConfig.newBuilder(this)
.setMainDiskCacheConfig(image)
.build();
//不设置默认传一个参数既可
Fresco.initialize(this,config);
}
}
配置缓存SD卡路径,这里涉及到Android6.0运行时权限,有解决方案,我使用的权限管理库是AndPermission(https://github.com/yanzhenjie/AndPermission):
首先在Application中判断是否有SD卡权限,如果有则初始化到SD卡,如果没有则采用默认配置:
public class App extends Application {
private static App app;
@Override
public void onCreate() {
super.onCreate();
app = this;
// 如果有SD卡权限则直接初始化到SD卡。
if (AndPermission.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE))
initFresco();
else { // 没有权限,暂时使用默认配置。
Fresco.initialize(this);
}
}
/**
* 高级初始话Fresco。
*/
public void initFresco() {
// 高级初始化:
Fresco.initialize(this, ImagePipelineConfig.newBuilder(App.this)
.setMainDiskCacheConfig(
DiskCacheConfig.newBuilder(this)
.setBaseDirectoryPath(new File("SD卡的路径..."))
.build()
)
.build()
);
}
public static App get() {
return app;
}
}
然后在SplashActivity申请SD卡权限,已被下次进入App时初始化Fresco时拥有SD卡权限:
public class SplashActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 申请权限。
AndPermission.with(this)
.requestCode(100)
.permission(Manifest.permission.READ_CALENDAR)
.send();
}
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions, @NonNull int[] grantResults) {
AndPermission.onRequestPermissionsResult(requestCode, permissions, grantResults, listener);
}
/**
* 权限监听。
*/
private PermissionListener listener = new PermissionListener() {
@Override
public void onSucceed(int requestCode, List<String> grantPermissions) {
if(requestCode == 100)
// 启动app:
startActivity(new Intent(SplashActivity.this, MainActivity.class));
}
@Override
public void onFailed(int requestCode, List<String> deniedPermissions) {
if(requestCode == 100)
// 用户不授权,则退出app:
finish();
}
};
}
高级初始化-配置网络层为OkHttp
Fresco默认使用HttpURLConnection作为网络层,当然也可以配置OkHttp作为它的网络层,配置OkHttp为它的网络层需要依赖下面的库:
compile "com.facebook.fresco:imagepipeline-okhttp3:0.12.0+"
然后在Application中初始化的时候注意:
/**
* 初始话Fresco。
*/
public void initFresco() {
// 你的OkHttpClient根据你的设计来,建议是单例:
OkHttpClient okHttpClient = new OkHttpClient();
Fresco.initialize(this, OkHttpImagePipelineConfigFactory.newBuilder(App.this, okHttpClient)
.setMainDiskCacheConfig(
DiskCacheConfig.newBuilder(this)
.setBaseDirectoryPath(new File("SD卡的路径..."))
.build()
)
.build()
);
}
这里只需要注意原来的ImagePipelineConfig换成了OkHttpImagePipelineConfigFactory,并且需要一个OkHttpClient的对象。
加载网络图片、url、assets、res、本地File图片
先给出支持的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
在使用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"/>
把它当成我们平常使用的ImageView即可,不过我们要注意Fresco不支持wrap_content,需要使用match_parent或者显示指定view宽高,不过可以设置宽高比
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/simple_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
fresco:viewAspectRatio="2.0"/>
加载http/https远程gif图片
AbstractDraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(Uri.parse(urlgit))
.setAutoPlayAnimations(true)//是否可以加载动态图
.setOldController(simpleImage.getController())
.build();
simpleImage.setController(controller);
一、加载http/https远程图片
//直接加载
try {
simpleImage.setImageURI(Uri.parse(url));
} catch (Exception e) {
e.printStackTrace();
}
/**
* 显示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();
}
}
二、显示本地图片
这里就有个坑了,先看一下下面我写了两个方法,一个需要传入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();
}
}
三、显示res中图片
这里要注意,我们在为res中的图片生成Uri的时候:
Uri uri = Uri.parse("res://包名(任何字符串或者留空)/" + R.drawable.ic_launcher);
所以我们一般留空,因此我们的代码看起来是下面的样子:
/**
* 显示一个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();
}
}
四、显示ContentProvider图片
/**
* 显示content provider图片。
*
* @param draweeView image view。
* @param path 路径。
*/
public static void showContentProvider(SimpleDraweeView draweeView, String path) {
try {
draweeView.setImageURI(Uri.parse("content://" + path));
} catch (Exception e) {
e.printStackTrace();
}
}
五、显示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();
}
}
一些默认属性的设置
simpleImage.setAspectRatio(1.2f);//改变宽高比
<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" 描边的颜色。
/>
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);
圆形图片带白色的边:
<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"/> // 描边宽度。
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();
}
}
//参考博客:https://blog.csdn.net/xiaoqiang_0719/article/details/52437780
Fresco-Java代码实现圆形圆角效果
圆角图—setRoundingParams:
设置圆角图只有一种方式,但它有六种方法:
限定符和类型 | 方法 | 说明 |
static RoundingParams | fromCornersRadius(float radius) | 设置圆角半径 |
static RoundingParams | fromCornersRadii(float[] radii) | 分别设置左上角、右上角、左下角、右下角圆角半径 |
static RoundingParams | fromCornersRadii(float topLeft, float topRight, float bottomRight, float bottomLeft) | 分别设置左上角、右上角、左下角、右下角圆角半径 |
RoundingParams | setCornersRadius(float radius) | 设置圆角半径 |
RoundingParams | setCornersRadii(float[] radii) | 分别设置左上角、右上角、左下角、右下角圆角半径 |
RoundingParams | setCornersRadii(float topLeft, float topRight, float bottomRight, float bottomLeft) | 分别设置左上角、右上角、左下角、右下角圆角半径 |
//圆形
RoundingParams roundingParams = new RoundingParams();
roundingParams.setRoundAsCircle(true);
GenericDraweeHierarchy hierarchy = GenericDraweeHierarchyBuilder.newInstance(getResources())
.setRoundingParams(roundingParams)
.build();
simpleImage.setHierarchy(hierarchy);
//圆角
RoundingParams roundingParams1 = new RoundingParams();
roundingParams1.setRoundAsCircle(false);
roundingParams1.setCornersRadius(20);
GenericDraweeHierarchy hierarchy1 = GenericDraweeHierarchyBuilder.newInstance(getResources())
.setRoundingParams(roundingParams1)
.build();
simpleImage.setHierarchy(hierarchy1);
总结:
限定符和类型 | 方法 | 说明 |
static RoundingParams | asCircle() | 将图像设置成圆形 |
static RoundingParams | fromCornersRadii(float[] radii) | 分别设置(前2个)左上角、(3、4)右上角、(5、6)左下角、(7、8)右下角的圆角半径 |
static RoundingParams | fromCornersRadii(float topLeft, float topRight, float bottomRight, float bottomLeft) | 分别设置左上角、右上角、左下角、右下角的圆角半径 |
static RoundingParams | fromCornersRadius(float radius) | 设置圆角半径 |
int | getBorderColor() | 获取边框颜色 |
float | getBorderWidth() | 获取边框宽度 |
float[] | getCornersRadii() | 获取圆角半径 |
int | getOverlayColor() | 获取叠加颜色 |
boolean | getRoundAsCircle() | 获取图像是否是圆形 |
RoundingParams.RoundingMethod | getRoundingMethod() | 获取当前圆形圆角模式 |
RoundingParams | setBorder(int color, float width) | 设置边框颜色及其宽度 |
RoundingParams | setCornersRadii(float[] radii) | 分别设置(前2个)左上角、(3、4)右上角、(5、6)左下角、(7、8)右下角的圆角半径 |
RoundingParams | setCornersRadii(float topLeft, float topRight, float bottomRight, float bottomLeft) | 分别设置左上角、右上角、左下角、右下角的圆角半径 |
RoundingParams | setCornersRadius(float radius) | 设置圆角半径 |
RoundingParams | setOverlayColor(int overlayColor) | 设置叠加颜色并将设置圆形圆角的方法改为RoundingMethod.COLOR_OVERLAY |
RoundingParams | setRoundAsCircle(boolean roundAsCircle) | 设置图像是否为圆形 |
RoundingParams | setRoundingMethod(RoundingParams.RoundingMethod roundingMethod) | 设置圆形圆角模式 |