Android项目实战(三十):Fresco加载gif图片并播放

简介: 前言: 项目中图文混合使用的太多太多了,但是绝大部分都是静态图片。 然而项目开发中有这么一个需求:显示一个出一个简短的动画(一般都不超过3秒)演示 比如说:一个功能提供很多步骤来教用户做广播体操,那么第一步就显示一个3秒钟的动作图,第二步显示一个几秒钟的动作图。

前言:

项目中图文混合使用的太多太多了,但是绝大部分都是静态图片。

然而项目开发中有这么一个需求:显示一个出一个简短的动画(一般都不超过3秒)演示

比如说:一个功能提供很多步骤来教用户做广播体操,那么第一步就显示一个3秒钟的动作图,第二步显示一个几秒钟的动作图。(当然这个需求不是这个功能)

怎么解决呢:一确定这个需求我的第一实现思路便是让美工给我搞几个连续的图片,我使用帧动画来轮回播放 便实现了这个动画。

但是帧动画使用起来太复杂了,一套动作我要搞好久来实现。那么就想Android中支持不支持播放gif格式的图片呢,让美工搞动态图我直接拿来用多方便。

-------------------------------------------------------------------------------------------------------------------

然后我就发现了Fresco,官方网址:http://www.fresco-cn.org/  ,中文文档,很方便查阅

看下官方的描述:

Fresco 是一个强大的图片加载组件。

Fresco 中设计有一个叫做 image pipeline 的模块。它负责从网络,从本地文件系统,本地资源加载图片。为了最大限度节省空间和CPU时间,它含有3级缓存设计(2级内存,1级文件)。

Fresco 中设计有一个叫做 Drawees 模块,方便地显示loading图,当图片不再显示在屏幕上时,及时地释放内存和空间占用。

Fresco 支持 Android2.3(API level 9) 及其以上系统。

------------------------------------------------------------------------------------------------------------------

其他的不管,这篇博客只要看Fresco特性之一:

支持 gif 动态图片     ,也许我们会构造一些自定义的类来实现,但是太复杂了,也太麻烦了,Fresco直接帮你封装好了

------------------------------------------------------------------------------------------------------------------

那么开始看怎么使用Fresco加载显示gif格式的图片了

1、必须要做的事,当然看官方文档也能知道,如何引入Fresco到项目中

Android Studio 或者 Gradle
dependencies { compile
'com.facebook.fresco:fresco:0.6.0+' }

 IDEA 和 Eclipse 就是别的方法了,具体看下 http://www.fresco-cn.org/docs/index.html#_

 

2、配置清单文件添加网络权限,这里具体获取网络gif图片并展示的Demo,加载本地的gif图片 可以不加网络权限

<uses-permission android:name="android.permission.INTERNET"/>

 

3、布局文件中的使用

(1)xml文件中,加入命名空间,用于给图片设置一些属性

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fresco="http://schemas.android.com/apk/res-auto">

(2)既然是gif图片,当然也就是图片,而当我们把Fresco导入到项目之后,就有了

com.facebook.drawee.view.SimpleDraweeView 类 

 1 //
 2 // Source code recreated from a .class file by IntelliJ IDEA
 3 // (powered by Fernflower decompiler)
 4 //
 5 
 6 package com.facebook.drawee.view;
 7 
 8 import android.content.Context;
 9 import android.net.Uri;
10 import android.util.AttributeSet;
11 import com.facebook.common.internal.Preconditions;
12 import com.facebook.common.internal.Supplier;
13 import com.facebook.drawee.generic.GenericDraweeHierarchy;
14 import com.facebook.drawee.interfaces.DraweeController;
15 import com.facebook.drawee.interfaces.SimpleDraweeControllerBuilder;
16 import com.facebook.drawee.view.GenericDraweeView;
17 import javax.annotation.Nullable;
18 
19 public class SimpleDraweeView extends GenericDraweeView {
20     private static Supplier<? extends SimpleDraweeControllerBuilder> sDraweeControllerBuilderSupplier;
21     private SimpleDraweeControllerBuilder mSimpleDraweeControllerBuilder;
22 
23     public static void initialize(Supplier<? extends SimpleDraweeControllerBuilder> draweeControllerBuilderSupplier) {
24         sDraweeControllerBuilderSupplier = draweeControllerBuilderSupplier;
25     }
26 
27     public static void shutDown() {
28         sDraweeControllerBuilderSupplier = null;
29     }
30 
31     public SimpleDraweeView(Context context, GenericDraweeHierarchy hierarchy) {
32         super(context, hierarchy);
33         this.init();
34     }
35 
36     public SimpleDraweeView(Context context) {
37         super(context);
38         this.init();
39     }
40 
41     public SimpleDraweeView(Context context, AttributeSet attrs) {
42         super(context, attrs);
43         this.init();
44     }
45 
46     public SimpleDraweeView(Context context, AttributeSet attrs, int defStyle) {
47         super(context, attrs, defStyle);
48         this.init();
49     }
50 
51     private void init() {
52         if(!this.isInEditMode()) {
53             Preconditions.checkNotNull(sDraweeControllerBuilderSupplier, "SimpleDraweeView was not initialized!");
54             this.mSimpleDraweeControllerBuilder = (SimpleDraweeControllerBuilder)sDraweeControllerBuilderSupplier.get();
55         }
56     }
57 
58     protected SimpleDraweeControllerBuilder getControllerBuilder() {
59         return this.mSimpleDraweeControllerBuilder;
60     }
61 
62     public void setImageURI(Uri uri) {
63         this.setImageURI(uri, (Object)null);
64     }
65 
66     public void setImageURI(Uri uri, @Nullable Object callerContext) {
67         DraweeController controller = this.mSimpleDraweeControllerBuilder.setCallerContext(callerContext).setUri(uri).setOldController(this.getController()).build();
68         this.setController(controller);
69     }
70 }
SimpleDraweeView.class

那么要显示gif图片的控件的标签便是:

<com.facebook.drawee.view.SimpleDraweeView>   </com.facebook.drawee.view.SimpleDraweeView>

注意:SimpleDraweeView 不支持wrap_content


所下载的图像可能和占位图尺寸不一致,如果设置出错图或者重试图的话,这些图的尺寸也可能和所下载的图尺寸不一致。

如果大小不一致,图像下载完之后,假设如果是wrap_content,View将会重新layout,改变大小和位置。这将会导致界面跳跃。

固定宽高比

只有希望显示的固定宽高比时,可以使用wrap_content。

如果希望显示的图片保持一定宽高比例,如果 4:3,则在XML中:

<com.facebook.drawee.view.SimpleDraweeView
    android:id="@+id/my_image_view"
    android:layout_width="20dp"
    android:layout_height="wrap_content"
    <!-- other attributes -->
然后在代码中指定显示比例:

mSimpleDraweeView.setAspectRatio(1.33f);

 

Demo代码:

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2                 xmlns:tools="http://schemas.android.com/tools"
 3                 xmlns:fresco="http://schemas.android.com/apk/res-auto"
 4                 android:layout_width="match_parent"
 5                 android:layout_height="match_parent"
 6                 android:paddingLeft="@dimen/activity_horizontal_margin"
 7                 android:paddingRight="@dimen/activity_horizontal_margin"
 8                 android:paddingTop="@dimen/activity_vertical_margin"
 9                 android:paddingBottom="@dimen/activity_vertical_margin"
10                 tools:context=".MainActivity">
11 
12     <com.facebook.drawee.view.SimpleDraweeView
13             android:id="@+id/img"
14             android:layout_width="400dp"
15             android:layout_height="400dp"
16             fresco:placeholderImage="@mipmap/ic_launcher"
17             />
18 
19 </RelativeLayout>
activity_main.xml

 

4、然后就是图片所在布局对应的Activity中的使用了

(1)初始化Fresco,注意位置,用过百度地图的应该理解这里,记住位置就行

super.onCreate(savedInstanceState);
Fresco.initialize(this);
setContentView(R.layout.activity_main);

(2)进行网络gif图片资源的加载并展示

Uri uri = Uri.parse("http://img.huofar.com/data/jiankangrenwu/shizi.gif");

DraweeController draweeController
= Fresco.newDraweeControllerBuilder() .setUri(uri) .setAutoPlayAnimations(true) // 设置加载图片完成后是否直接进行播放 .build(); img.setController(draweeController);

 

效果图:

   先给控件一个图片占位,当加载成功的时候显示加载的图片

就这么简单 ,其他的Fresco都会帮我们解决

显示占位图直到加载完成;
下载图片;
缓存图片;
图片不再显示时,从内存中移除

 

相关文章
|
5月前
|
存储 缓存 Android开发
安卓Jetpack Compose+Kotlin, 使用ExoPlayer播放多个【远程url】音频,搭配Okhttp库进行下载和缓存,播放完随机播放下一首
这是一个Kotlin项目,使用Jetpack Compose和ExoPlayer框架开发Android应用,功能是播放远程URL音频列表。应用会检查本地缓存,如果文件存在且大小与远程文件一致则使用缓存,否则下载文件并播放。播放完成后或遇到异常,会随机播放下一首音频,并在播放前随机设置播放速度(0.9到1.2倍速)。代码包括ViewModel,负责音频管理和播放逻辑,以及UI层,包含播放和停止按钮。
|
4月前
|
Java Android开发
Android面试题经典之Glide取消加载以及线程池优化
Glide通过生命周期管理在`onStop`时暂停请求,`onDestroy`时取消请求,减少资源浪费。在`EngineJob`和`DecodeJob`中使用`cancel`方法标记任务并中断数据获取。当网络请求被取消时,`HttpUrlFetcher`的`cancel`方法设置标志,之后的数据获取会返回`null`,中断加载流程。Glide还使用定制的线程池,如AnimationExecutor、diskCacheExecutor、sourceExecutor和newUnlimitedSourceExecutor,其中某些禁止网络访问,并根据CPU核心数动态调整线程数。
129 2
|
10天前
|
Android开发 UED
Android 中加载 Gif 动画
【10月更文挑战第20天】加载 Gif 动画是 Android 开发中的一项重要技能。通过使用第三方库或自定义实现,可以方便地在应用中展示生动的 Gif 动画。在实际应用中,需要根据具体情况进行合理选择和优化,以确保用户体验和性能的平衡。可以通过不断的实践和探索,进一步掌握在 Android 中加载 Gif 动画的技巧和方法,为开发高质量的 Android 应用提供支持。
|
3月前
|
Android开发
Android 利用MediaPlayer实现音乐播放
本文提供了一个简单的Android MediaPlayer音乐播放示例,包括创建PlayerActivity、配置AndroidManifest.xml和activity_player.xml布局,以及实现播放和暂停功能的代码。
25 0
Android 利用MediaPlayer实现音乐播放
|
3月前
|
编解码 网络协议 开发工具
Android平台如何实现多路低延迟RTSP|RTMP播放?
本文档详细介绍了大牛直播SDK在Android平台上实现RTSP与RTMP流媒体播放及录像功能的技术细节。早在2015年,SDK的第一版就已经支持了多实例播放,并且通过简单的实例封装就能轻松实现。文档中提供了代码示例,展示了如何开启播放、停止播放以及开始和停止录像等功能。此外,SDK还提供了丰富的配置选项,例如设置录像目录、文件大小限制、转码选项等。总结部分列出了该SDK的关键特性,包括但不限于高稳定性和低延迟的播放能力、多实例支持、事件回调、硬解码支持、网络状态监控以及复杂的网络环境处理等。这些功能使得SDK能够应对各种应用场景,特别是在对延迟和稳定性有极高要求的情况下表现优异。
|
3月前
|
编解码 网络协议 vr&ar
Android平台下VR头显如何低延迟播放4K以上超高分辨率RTSP|RTMP流
这段内容讲述了VR头显中实现高分辨率视频播放的技术背景与实现方法,并强调了其重要性。高分辨率对于提升VR体验至关重要,它能提供更清晰的画面、增强沉浸感、补偿透镜放大效应,并维持宽广视场角下的图像质量。文中提到的大牛直播SDK具备极低的延迟(200-400ms),支持多种协议与格式,并具有丰富的功能特性,如多实例播放、事件回调、视频及音频格式支持等。此外,提供了基于Unity的播放器示例代码,展示了如何配置播放参数并开始播放。最后,作者指出此类技术在远程控制、虚拟仿真等应用场景中的重要意义。
|
3月前
|
存储 缓存 Java
Android项目架构设计问题之优化业务接口数据的加载效率如何解决
Android项目架构设计问题之优化业务接口数据的加载效率如何解决
44 0
|
3月前
|
Java Android开发 Kotlin
Android项目架构设计问题之要在Glide库中加载网络图片到ImageView如何解决
Android项目架构设计问题之要在Glide库中加载网络图片到ImageView如何解决
32 0
|
5月前
|
存储 Android开发 Kotlin
Kotlin开发安卓app,在使用 MediaPlayer 播放 res/raw 中的音乐时遇到突然中断的问题,而 onErrorListener 没有接收到任何报错
在使用 Android MediaPlayer 播放 res/raw 中的音乐时遇到中断问题,可能的原因包括资源问题、媒体文件编码格式、生命周期管理和设备资源配置。要排查问题,检查音频文件是否正确包含,格式编码是否支持,MediaPlayer 是否正确管理及释放,以及设备是否有足够存储和配置。通过设置 onErrorListener 日志和确保在 onDestroy 中释放资源来调试。如果文件过大,考虑使用 AssetManager。遵循这些步骤可帮助诊断并解决播放中断的问题。