Fresco 简单的使用—SimpleDraweeView

729 阅读6分钟

Fresco 简单的使用—SimpleDraweeView

  • 百学须先立志—学前须知:

    在我们平时加载图片 (不管是下载还是加载本地图片…..) 的时候,我们经常会遇到这样一个需求,那就是当图片正在加载时应该呈现正在加载时的图像,当图片加载失败时应该呈现图片加载时的图像,当我们重新加载这张图片时,应该呈现重试时图像,直到这张图片加载完成。这些繁琐并且重复的如果得不到简化的话,那将是一个开发人员的噩梦,现在好了,我们用 Facebook 出品的一个强大的图片加载组件 Fresco 几行代码就可以搞定以上问题了。

  • 尽信书,不如无书—能学到什么?

    1、SimpleDraweeView 最基本的使用
    2、SimpleDraweeView 的圆形图
    3、SimpleDraweeView 的圆角图
    4、SimpleDraweeView 的缩放类型

  • 工欲善其事必先利其器—下载 Fresco 并导入到项目

    Fresco 中文说明:www.fresco-cn.org/

    Fresco 项目 GitHub 地址:github.com/facebook/fr…

    第一步进入 Fresco 项目 GitHub 地址

    第二步添加 Fresco 到项目工程:

    第三步服务及权限:

    <!-- 访问网络的权限 -->
    <uses-permission android:/>
    

  • 常见问题:

    初次使用,我们就先简单书写我们的 activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/main_adv"
            android:layout_width="300dp"
            android:layout_height="300dp"
            android:layout_centerInParent="true"
            ></com.facebook.drawee.view.SimpleDraweeView>
    
    </RelativeLayout>
    

    代码分析:

    MainActivity 实现代码:

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    }
    

    简单的书写完布局和实现代码之后我们来运行一下。

            java.lang.RuntimeException: Unable to start activity ComponentInfo{scp.com.frescodemo/scp.com.frescodemo.MainActivity}: 
    
    android.view.InflateException: Binary XML file line #5: Error inflating class com.facebook.drawee.view.SimpleDraweeView
                    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2264)
                    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2313)
                    at android.app.ActivityThread.access$1100(ActivityThread.java:141)
                    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1238)
                    at android.os.Handler.dispatchMessage(Handler.java:102)
                    at android.os.Looper.loop(Looper.java:136)
                    at android.app.ActivityThread.main(ActivityThread.java:5336)
                    at java.lang.reflect.Method.invokeNative(Native Method)
                    at java.lang.reflect.Method.invoke(Method.java:515)
                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:871)
                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687)
                    at dalvik.system.NativeStart.main(Native Method)
             Caused by: android.view.InflateException: Binary XML file line #5: Error inflating class com.facebook.drawee.view.SimpleDraweeView
    

    运行报错了!怎么回事呢?这里啊,是因为我们没有在应用调用 setContentView() 之前进行初始化 Fresco 造成的;解决办法:

    修改我们的 MainActivity 里代码:

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Fresco.initialize(this);
            setContentView(R.layout.activity_main);
        }
    }
    

    再运行就没有错误发生了。

  • 占位图—placeholderImage:

    在此之前我们需要一张占位图 icon_placeholder.png 大家右键另存为即可:

    修改我们的 activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:fresco="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/main_adv"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_centerInParent="true"
            fresco:placeholderImage="@mipmap/icon_placeholder"
            fresco:placeholderImageScaleType="fitCenter"
            ></com.facebook.drawee.view.SimpleDraweeView>
    
    </RelativeLayout>
    

    代码说明:

    MainActivity 无需修改,运行一下:

  • 正在加载图—progressBarImage:

    在此之前我们需要一张正在加载图 icon_progress_bar.png 大家右键另存为即可:

    修改我们刚刚书写的 activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:fresco="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/main_sdv"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_centerInParent="true"
            fresco:actualImageScaleType="focusCrop"
            fresco:placeholderImage="@mipmap/icon_placeholder"
            fresco:placeholderImageScaleType="fitCenter"
            fresco:progressBarImage="@mipmap/icon_progress_bar"
            fresco:progressBarImageScaleType="centerInside"
            fresco:progressBarAutoRotateInterval="5000"
            ></com.facebook.drawee.view.SimpleDraweeView>
    
    </RelativeLayout>
    

    代码说明:

    更改我们的 MainActivity 里代码:

    public class MainActivity extends AppCompatActivity {
    
        private SimpleDraweeView simpleDraweeView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Fresco.initialize(this);
            setContentView(R.layout.activity_main);
            initView();
        }
    
        private void initView() {
            //创建SimpleDraweeView对象
            simpleDraweeView = (SimpleDraweeView) findViewById(R.id.main_sdv);
            //创建将要下载的图片的URI
            Uri imageUri = Uri.parse("https://img-my.csdn.net/uploads/avatar/4/E/8/1_y1scp.jpg");
            //开始下载
            simpleDraweeView.setImageURI(imageUri);
        }
    }
    

    代码分析:

    运行效果图:

    正在加载图本身是不可以转的,但是呢,加上了 fresco:progressBarAutoRotateInterval="5000" 属性,那么它就可以旋转了;可以看到,正在加载图一闪而过,这是因为我们加载的图片很小,网络也很好。

  • 失败图—failureImage:

    在此之前我们需要一张正在加载图 icon_failure.png 大家右键另存为即可:

    修改我们刚刚书写的 activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:fresco="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/main_sdv"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_centerInParent="true"
            fresco:actualImageScaleType="focusCrop"
            fresco:placeholderImage="@mipmap/icon_placeholder"
            fresco:placeholderImageScaleType="fitCenter"
            fresco:progressBarImage="@mipmap/icon_progress_bar"
            fresco:progressBarImageScaleType="centerInside"
            fresco:progressBarAutoRotateInterval="5000"
            fresco:failureImage="@mipmap/icon_failure"
            fresco:failureImageScaleType="centerInside"
            ></com.facebook.drawee.view.SimpleDraweeView>
    
    </RelativeLayout>
    

    代码分析:

    修改我们的 MainActivity 里代码:

    public class MainActivity extends AppCompatActivity {
    
        private SimpleDraweeView simpleDraweeView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Fresco.initialize(this);
            setContentView(R.layout.activity_main);
            initView();
        }
    
        private void initView() {
            //创建SimpleDraweeView对象
            simpleDraweeView = (SimpleDraweeView) findViewById(R.id.main_sdv);
            //创建将要下载的图片的URI
            Uri imageUri = Uri.parse("https://img-my.csdn.net/uploads/avatar_y1scp.jpg");
            //开始下载
            simpleDraweeView.setImageURI(imageUri);
        }
    }
    

    代码说明:

    运行效果:

  • 重试图—retryImage:

    在此之前我们需要一张正在加载图 icon_retry.png 大家右键另存为即可:

    修改我们刚刚书写的 activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:fresco="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/main_sdv"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_centerInParent="true"
            fresco:actualImageScaleType="focusCrop"
            fresco:placeholderImage="@mipmap/icon_placeholder"
            fresco:placeholderImageScaleType="fitCenter"
            fresco:progressBarImage="@mipmap/icon_progress_bar"
            fresco:progressBarImageScaleType="centerInside"
            fresco:progressBarAutoRotateInterval="5000"
            fresco:failureImage="@mipmap/icon_failure"
            fresco:failureImageScaleType="centerInside"
            fresco:retryImage="@mipmap/icon_retry"
            fresco:retryImageScaleType="centerCrop"
            ></com.facebook.drawee.view.SimpleDraweeView>
    
    </RelativeLayout>
    

    代码分析:

    修改我们的 MainActivity 里代码:

    public class MainActivity extends AppCompatActivity {
    
        private SimpleDraweeView simpleDraweeView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Fresco.initialize(this);
            setContentView(R.layout.activity_main);
            initView();
        }
    
        private void initView() {
            //创建SimpleDraweeView对象
            simpleDraweeView = (SimpleDraweeView) findViewById(R.id.main_sdv);
            //创建将要下载的图片的URI
            Uri imageUri = Uri.parse("https://img-my.csdn.net/uploads/avatar_y1scp.jpg");
            //开始下载
            simpleDraweeView.setImageURI(imageUri);
    
            //创建DraweeController
            DraweeController controller = Fresco.newDraweeControllerBuilder()
                    //加载的图片URI地址
                    .setUri(imageUri)
                    //设置点击重试是否开启
                    .setTapToRetryEnabled(true)
                    //设置旧的Controller
                    .setOldController(simpleDraweeView.getController())
                    //构建
                    .build();
    
            //设置DraweeController
            simpleDraweeView.setController(controller);
        }
    }
    

    代码说明:

    运行效果:

    注意:

    重复加载 4 次还是没有加载出来的时候才会显示 failureImage(失败图) 的图片

  • 淡入淡出动画—fadeDuration:

    修改我们刚刚书写的 activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:fresco="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/main_sdv"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_centerInParent="true"
            fresco:actualImageScaleType="focusCrop"
            fresco:placeholderImage="@mipmap/icon_placeholder"
            fresco:placeholderImageScaleType="fitCenter"
            fresco:progressBarImage="@mipmap/icon_progress_bar"
            fresco:progressBarImageScaleType="centerInside"
            fresco:progressBarAutoRotateInterval="5000"
            fresco:failureImage="@mipmap/icon_failure"
            fresco:failureImageScaleType="centerInside"
            fresco:retryImage="@mipmap/icon_retry"
            fresco:retryImageScaleType="centerCrop"
            fresco:fadeDuration="5000"
            ></com.facebook.drawee.view.SimpleDraweeView>
    
    </RelativeLayout>
    

    代码说明:

    MainActivity 中的代码无需修改。

    运行效果:

    重试 + 进度图 + 失败图进度图 + 正确图
  • 背景图—backgroundImage:

    这里呢,我们的背景图采用的是一个系统所提供的颜色中的一种。

    修改我们刚刚书写的 activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:fresco="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/main_sdv"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_centerInParent="true"
            fresco:actualImageScaleType="focusCrop"
            fresco:fadeDuration="5000"
            fresco:backgroundImage="@android:color/holo_orange_light"
            ></com.facebook.drawee.view.SimpleDraweeView>
    
    </RelativeLayout>
    

    代码说明:

    MainActivity 中的代码无需修改,运行效果:

  • 叠加图—overlayImage:

    这里呢,我们的背景图采用的是一个系统所提供的颜色中的一种。

    修改我们刚刚书写的 activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:fresco="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/main_sdv"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_centerInParent="true"
            fresco:actualImageScaleType="focusCrop"
            fresco:placeholderImage="@mipmap/icon_placeholder"
            fresco:placeholderImageScaleType="fitCenter"
            fresco:progressBarImage="@mipmap/icon_progress_bar"
            fresco:progressBarImageScaleType="centerInside"
            fresco:progressBarAutoRotateInterval="5000"
            fresco:failureImage="@mipmap/icon_failure"
            fresco:failureImageScaleType="centerInside"
            fresco:retryImage="@mipmap/icon_retry"
            fresco:retryImageScaleType="centerCrop"
            fresco:fadeDuration="5000"
            fresco:backgroundImage="@android:color/holo_orange_light"
            fresco:pressedStateOverlayImage="@android:color/holo_green_dark"
            fresco:overlayImage="@android:color/black"
            ></com.facebook.drawee.view.SimpleDraweeView>
    
    </RelativeLayout>
    

    代码说明:

    MainActivity 中的代码无需修改。

    运行效果:

    从运行效果来看,叠加图在最上面,覆盖了下面的图。

  • 圆形图—roundAsCircle:

    一行代码搞定圆形图:设置 roundAsCircle 为 true;

    修改我们刚刚书写的 activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:fresco="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/main_sdv"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_centerInParent="true"
            fresco:actualImageScaleType="focusCrop"
            fresco:placeholderImage="@mipmap/icon_placeholder"
            fresco:placeholderImageScaleType="fitCenter"
            fresco:progressBarImage="@mipmap/icon_progress_bar"
            fresco:progressBarImageScaleType="centerInside"
            fresco:progressBarAutoRotateInterval="5000"
            fresco:failureImage="@mipmap/icon_failure"
            fresco:failureImageScaleType="centerInside"
            fresco:retryImage="@mipmap/icon_retry"
            fresco:retryImageScaleType="centerCrop"
            fresco:fadeDuration="5000"
            fresco:backgroundImage="@android:color/holo_orange_light"
            fresco:roundAsCircle="true"
            ></com.facebook.drawee.view.SimpleDraweeView>
    
    </RelativeLayout>
    

    代码说明:

    MainActivity 中的代码无需修改。

    运行效果:

    可以看到,从图片开始加载一直到图片下载完毕,整个图像都是圆形的。

  • 圆角图—roundedCornerRadius:

    修改我们刚刚书写的 activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:fresco="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/main_sdv"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_centerInParent="true"
            fresco:actualImageScaleType="focusCrop"
            fresco:placeholderImage="@mipmap/icon_placeholder"
            fresco:placeholderImageScaleType="fitCenter"
            fresco:progressBarImage="@mipmap/icon_progress_bar"
            fresco:progressBarImageScaleType="centerInside"
            fresco:progressBarAutoRotateInterval="5000"
            fresco:failureImage="@mipmap/icon_failure"
            fresco:failureImageScaleType="centerInside"
            fresco:retryImage="@mipmap/icon_retry"
            fresco:retryImageScaleType="centerCrop"
            fresco:fadeDuration="5000"
            fresco:backgroundImage="@android:color/holo_orange_light"
            fresco:roundedCornerRadius="30dp"
            ></com.facebook.drawee.view.SimpleDraweeView>
    
    </RelativeLayout>
    

    代码说明:

    MainActivity 中的代码无需修改。

    运行效果:

    可以看到,从图片开始加载一直到图片下载完毕,整个图像都是圆角的。

    圆角属性圆角属性
    左上角是否为圆角fresco:roundTopLeft="false"右上角是否为圆角fresco:roundTopRight="false"
    左下角是否为圆角fresco:roundBottomLeft="false"右下角是否为圆角fresco:roundBottomRight="false"

    注意:

    当我们同时设置图像显示为圆形图像和圆角图像时,只会显示为圆形图像。

  • 圆形圆角边框宽度及颜色—roundingBorder:

    修改我们刚刚书写的 activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:fresco="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/main_sdv"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_centerInParent="true"
            fresco:actualImageScaleType="focusCrop"
            fresco:placeholderImage="@mipmap/icon_placeholder"
            fresco:placeholderImageScaleType="focusCrop"
            fresco:progressBarImage="@mipmap/icon_progress_bar"
            fresco:progressBarImageScaleType="focusCrop"
            fresco:progressBarAutoRotateInterval="5000"
            fresco:failureImage="@mipmap/icon_failure"
            fresco:failureImageScaleType="focusCrop"
            fresco:retryImage="@mipmap/icon_retry"
            fresco:retryImageScaleType="focusCrop"
            fresco:fadeDuration="5000"
            fresco:backgroundImage="@android:color/holo_orange_light"
            fresco:roundAsCircle="true"
            fresco:roundedCornerRadius="30dp"
            fresco:roundTopLeft="true"
            fresco:roundTopRight="true"
            fresco:roundBottomLeft="true"
            fresco:roundBottomRight="true"
            fresco:roundingBorderWidth="10dp"
            fresco:roundingBorderColor="@android:color/black"
            ></com.facebook.drawee.view.SimpleDraweeView>
    
    </RelativeLayout>
    

    代码说明:

    MainActivity 中的代码无需修改。

    运行效果 (左边显示的是带边框的圆形图像,右边显示的是带边框的圆角图像):

  • 圆形或圆角图像底下的叠加颜色—roundWithOverlayColor:

    修改我们刚刚书写的 activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:fresco="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/main_sdv"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_centerInParent="true"
            fresco:actualImageScaleType="focusCrop"
            fresco:placeholderImage="@mipmap/icon_placeholder"
            fresco:placeholderImageScaleType="focusCrop"
            fresco:progressBarImage="@mipmap/icon_progress_bar"
            fresco:progressBarImageScaleType="focusCrop"
            fresco:progressBarAutoRotateInterval="5000"
            fresco:failureImage="@mipmap/icon_failure"
            fresco:failureImageScaleType="focusCrop"
            fresco:retryImage="@mipmap/icon_retry"
            fresco:retryImageScaleType="focusCrop"
            fresco:fadeDuration="5000"
            fresco:backgroundImage="@android:color/holo_orange_light"
            fresco:roundWithOverlayColor="@android:color/darker_gray"
            fresco:roundAsCircle="true"
            ></com.facebook.drawee.view.SimpleDraweeView>
    
    </RelativeLayout>
    

    代码说明:

    MainActivity 中的代码无需修改。

    运行效果 (左边为圆形效果,右边为圆角效果):

  • 缩放类型—ScaleType:

    类型描述
    center居中,无缩放
    centerCrop保持宽高比缩小或放大,使得两边都大于或等于显示边界。居中显示。
    focusCrop同 centerCrop, 但居中点不是中点,而是指定的某个点
    centerInside使两边都在显示边界内,居中显示。如果图尺寸大于显示边界,则保持长宽比缩小图片。
    fitCenter保持宽高比,缩小或者放大,使得图片完全显示在显示边界内。居中显示
    fitStart同上。但不居中,和显示边界左上对齐
    fitEnd同 fitCenter, 但不居中,和显示边界右下对齐
    fitXY不保存宽高比,填充满显示边界
    none如要使用 tile mode 显示, 需要设置为 none

    推荐使用:focusCrop 类型

    Fresco 中文说明对这一点也有详情的说明: 缩放

  • 总结:

    XML 属性意义
    fadeDuration淡入淡出动画持续时间 (单位:毫秒 ms)
    actualImageScaleType实际图像的缩放类型
    placeholderImage占位图
    placeholderImageScaleType占位图的缩放类型
    progressBarImage进度图
    progressBarImageScaleType进度图的缩放类型
    progressBarAutoRotateInterval进度图自动旋转间隔时间 (单位:毫秒 ms)
    failureImage失败图
    failureImageScaleType失败图的缩放类型
    retryImage重试图
    retryImageScaleType重试图的缩放类型
    backgroundImage背景图
    overlayImage叠加图
    pressedStateOverlayImage按压状态下所显示的叠加图
    roundAsCircle设置为圆形图
    roundedCornerRadius圆角半径
    roundTopLeft左上角是否为圆角
    roundTopRight右上角是否为圆角
    roundBottomLeft左下角是否为圆角
    roundBottomRight右下角是否为圆角
    roundingBorderWidth圆形或者圆角图边框的宽度
    roundingBorderColor圆形或者圆角图边框的颜色
    roundWithOverlayColor圆形或者圆角图底下的叠加颜色 (只能设置颜色)
    viewAspectRatio控件纵横比
  • GitHub:

    本教程最终项目 GitHub 地址:github.com/scp50467784…