游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

Android开发之ImageView播放GIF动画实例

  Android开发之ImageView播放GIF动画实例
  Android的原生控件并不支持播放GIF格式的图片,如果想在Android中显示一张GIF动态图片,可以利用ImageView控件来完成,但是放进去之后,你会发现,ImageView它只会显示这张图片的第一帧,不会产生任何的动画效果。我们必须通过自定义控件的方式来实现ImageView播放GIF图片的功能。
  首先我们来编写一个PowerImageView控件,让它既能支持ImageView控件原生的所有功能,同时还可以播放GIF动态图片。
  先新建一个项目PowerImageViewTest,这里使用Android4。0Eclipse。
  由于是要自定义控件,会需要一些自定义的控件属性,因此我们需要在values目录下新建一个attrs。xml的文件,在这个文件中添加项目需要的自定义属性。
  这里我们目前暂时只需要一个自动播放autoplay属性,XML文件代码如下:
  lt;?xmlversion1。0encodingutf8?
  attr
  declarestyleable
  resources
  这个文件完成之后,下面我们来开始编写主类PowerImageView类,由于PowerImageView类需要支持ImageView的所有功能,我们必须要让PowerImageView继承自ImageView,代码如下:
  publicclassPowerImageViewextendsImageViewimplementsOnClickListener{
  播放GIF动画的关键类
  privateMoviemMovie;
  开始播放按钮图片
  privateBitmapmStartButton;
  记录动画开始的时间
  privatelongmMovieStart;
  GIF图片的宽度
  privateintmImageWidth;
  GIF图片的高度
  privateintmImageHeight;
  图片是否正在播放
  privatebooleanisPlaying;
  是否允许自动播放
  privatebooleanisAutoPlay;
  PowerImageView构造函数。
  paramcontext
  publicPowerImageView(Contextcontext){
  super(context);
  }
  PowerImageView构造函数。
  paramcontext
  publicPowerImageView(Contextcontext,AttributeSetattrs){
  this(context,attrs,0);
  }
  PowerImageView构造函数,在这里完成所有必要的初始化操作。
  paramcontext
  publicPowerImageView(Contextcontext,AttributeSetattrs,intdefStyle){
  super(context,attrs,defStyle);
  TypedArrayacontext。obtainStyledAttributes(attrs,R。styleable。PowerImageView);
  intresourceIdgetResourceId(a,context,attrs);
  if(resourceId!0){
  当资源id不等于0时,就去获取该资源的流
  InputStreamisgetResources()。openRawResource(resourceId);
  使用Movie类对流进行解码
  mMovieMovie。decodeStream(is);
  if(mMovie!null){
  如果返回值不等于null,就说明这是一个GIF图片,下面获取是否自动播放的属性
  isAutoPlaya。getBoolean(R。styleable。PowerImageViewautoplay,false);
  BitmapbitmapBitmapFactory。decodeStream(is);
  mImageWidthbitmap。getWidth();
  mImageHeightbitmap。getHeight();
  bitmap。recycle();
  if(!isAutoPlay){
  当不允许自动播放的时候,得到开始播放按钮的图片,并注册点击事件
  mStartButtonBitmapFactory。decodeResource(getResources(),R。drawable。startplay);
  setOnClickListener(this);
  }
  }
  }
  }
  Override
  publicvoidonClick(Viewv){
  if(v。getId()getId()){
  当用户点击图片时,开始播放GIF动画
  isPlayingtrue;
  invalidate();
  }
  }
  Override
  protectedvoidonDraw(Canvascanvas){
  if(mMovienull){
  mMovie等于null,说明是张普通的图片,则直接调用父类的onDraw()方法
  super。onDraw(canvas);
  }else{
  mMovie不等于null,说明是张GIF图片
  if(isAutoPlay){
  如果允许自动播放,就调用playMovie()方法播放GIF动画
  playMovie(canvas);
  invalidate();
  }else{
  不允许自动播放时,判断当前图片是否正在播放
  if(isPlaying){
  正在播放就继续调用playMovie()方法,一直到动画播放结束为止
  if(playMovie(canvas)){
  isPlayingfalse;
  }
  invalidate();
  }else{
  还没开始播放就只绘制GIF图片的第一帧,并绘制一个开始按钮
  mMovie。setTime(0);
  mMovie。draw(canvas,0,0);
  intoffsetW(mImageWidthmStartButton。getWidth())2;
  intoffsetH(mImageHeightmStartButton。getHeight())2;
  canvas。drawBitmap(mStartButton,offsetW,offsetH,null);
  }
  }
  }
  }
  Override
  protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){
  super。onMeasure(widthMeasureSpec,heightMeasureSpec);
  if(mMovie!null){
  如果是GIF图片则重写设定PowerImageView的大小
  setMeasuredDimension(mImageWidth,mImageHeight);
  }
  }
  开始播放GIF动画,播放完成返回true,未完成返回false。
  paramcanvas
  return播放完成返回true,未完成返回false。
  privatebooleanplayMovie(Canvascanvas){
  longnowSystemClock。uptimeMillis();
  if(mMovieStart0){
  mMovieStartnow;
  }
  intdurationmMovie。duration();
  if(duration0){
  duration1000;
  }
  intrelTime(int)((nowmMovieStart)duration);
  mMovie。setTime(relTime);
  mMovie。draw(canvas,0,0);
  if((nowmMovieStart)duration){
  mMovieStart0;
  returntrue;
  }
  returnfalse;
  }
  通过Java反射,获取到src指定图片资源所对应的id。
  parama
  paramcontext
  paramattrs
  return返回布局文件中指定图片资源所对应的id,没有指定任何图片资源就返回0。
  privateintgetResourceId(TypedArraya,Contextcontext,AttributeSetattrs){
  try{
  FieldfieldTypedArray。class。getDeclaredField(mValue);
  field。setAccessible(true);
  TypedValuetypedValueObject(TypedValue)field。get(a);
  returntypedValueObject。resourceId;
  }catch(Exceptione){
  e。printStackTrace();
  }finally{
  if(a!null){
  a。recycle();
  }
  }
  return0;
  }
  }
  这个类的代码注释已经非常详细了,我再来简单地解释一下。可以看到,我们重写了ImageView中所有的构建函数,使得PowerImageView的用法可以和ImageView完全相同。在构造函数中,则是对所有必要的数据进行了初始化操作。首先,我们调用了getResourceId()方法去获取图片资源对应的id值,在getResourceId()方法内部是通过Java的反射机制来进行获取的。得到了图片资源的id后,我们将它转换成InputStream,然后传入到Movie。decodeStream()方法中以解码出Movie对象。如果得到的Movie对象等于null,说明这是一张普通的图片资源,就不再进行任何特殊处理,因为父类ImageView都帮我们处理好了。如果得到的Movie对象不等于null,则说明这是一张GIF图片,接着就要去获取是否允许自动播放、图片的宽高等属性的值。如果不允许自动播放,还要给播放按钮注册点击事件,默认是不允许自动播放的。
  接下来会进入到onMeasure()方法中。在这个方法中我们进行判断,如果这是一张GIF图片,则需要将PowerImageView的宽高重定义,使得控件的大小刚好可以放得下这张GIF图片。
  再往后就会进入到onDraw()方法中。在这个方法里同样先判断当前是一张普通的图片还是GIF图片,如果是普通的图片就直接调用super。onDraw()方法交给ImageView去处理就好了。如果是GIF图片,则先判断该图是否允许自动播放,允许的话就调用playMovie()方法去播放GIF图片就好,不允许的话则会先在PowerImageView中绘制该GIF图片的第一帧,并在图片上绘制一个播放按钮,当用户点击了播放按钮时,再去调用playMovie()方法去播放GIF图片。
  下面我们来看看playMovie()方法中是怎样播放GIF图片的吧。可以看到,首先会对动画开始的时间做下记录,然后对动画持续的时间做下记录,接着使用当前的时间减去动画开始的时间,得到的时间就是此时PowerImageView应该显示的那一帧,然后借助Movie对象将这一帧绘制到屏幕上即可。之后每次调用playMovie()方法都会绘制一帧图片,连贯起来也就形成了GIF动画。注意,这个方法是有返回值的,如果当前时间减去动画开始时间大于了动画持续时间,那就说明动画播放完成了,返回true,否则返回false。
  完成了PowerImageView的编写,下面我们就来看一看如何使用它吧,其实非常简单,打开或新建activitymain。xml,代码如下所示:
  RelativeLayoutxmlns:androidhttp:schemas。android。comapkresandroid
  android:layoutwidthmatchparent
  android:layoutheightmatchparent
  com。example。powerimageviewtest。PowerImageView
  android:ididimageview
  android:layoutwidthwrapcontent
  android:layoutheightwrapcontent
  android:layoutcenterInParenttrue
  android:srcdrawableanim
  RelativeLayout
  可以看到,PowerImageView的用法和ImageView几乎完全一样,使用android:src属性来指定一张图片即可,这里指定的anim就是一张GIF图片。然后我们让PowerImageView在布局里居中显示MainActivity中的代码都是自动生成的,这里就不再贴出来了。在AndroidManifest。xml中还有一点需要注意,有些4。0以上系统的手机启动了硬件加速功能之后会导致GIF动画播放不出来,因此我们需要在AndroidManifest。xml中去禁用硬件加速功能,可以通过指定android:hardwareAccelerated属性来完成,代码如下所示:
  lt;?xmlversion1。0encodingutf8?
  manifestxmlns:androidhttp:schemas。android。comapkresandroid
  packagecom。example。powerimageviewtest
  android:versionCode1
  android:versionName1。0
  usessdk
  android:minSdkVersion14
  android:targetSdkVersion17
  android:allowBackuptrue
  android:icondrawableiclauncher
  android:labelstringappname
  android:themestyleAppTheme
  android:hardwareAcceleratedfalse
  android:namecom。example。powerimageviewtest。MainActivity
  android:labelstringappname
  intentfilter
  activity
  application
  manifest
  现在可以来运行一下代码了,一打开程序你就会看到GIF图片的第一帧,点击图片之后就可以播放GIF动画了。
  然后我们还可以通过修改activitymain。xml中的代码,给它加上允许自动播放的属性,代码如下所示:
  RelativeLayoutxmlns:androidhttp:schemas。android。comapkresandroid
  xmlns:attrhttp:schemas。android。comapkrescom。example。powerimageviewtest
  android:layoutwidthmatchparent
  android:layoutheightmatchparent
  com。example。powerimageviewtest。PowerImageView
  android:ididimageview
  android:layoutwidthwrapcontent
  android:layoutheightwrapcontent
  android:layoutcenterInParenttrue
  android:srcdrawableanim
  attr:autoplaytrue
  RelativeLayout
  这里使用了刚才我们自定义的属性,通过attr:autoplay来启用和禁用自动播放功能。现在将autoplay属性指定成true后,PowerImageView上就不会再显示一个播放按钮,而是会循环地自动播放动画。不仅如此,PowerImageView还继承了ImageView原生的所有功能,只要指定的不是GIF图片,PowerImageView表现的结果就和ImageView完全一致,现在我们来放一张普通的PNG图片,修改activitymain。xml中的代码,如下所示:
  RelativeLayoutxmlns:androidhttp:schemas。android。comapkresandroid
  android:layoutwidthmatchparent
  android:layoutheightmatchparent
  com。example。powerimageviewtest。PowerImageView
  android:ididimageview
  android:layoutwidthwrapcontent
  android:layoutheightwrapcontent
  android:layoutcenterInParenttrue
  android:srcdrawablemyphoto
  RelativeLayout
  这里在src属性里面指定了一张名字为myphoto的PNG图片,图片在布局正中央显示出来了,正是普通ImageView所具备的功能。我们还可以在PowerImageView中指定android:scaleType等属性,用法和原生的ImageView完全一样。

最后的赢家什么时候播出,最后的赢家常驻嘉宾最后的赢家说出很多人不清楚,可最后的赢家综艺要什么时候播出,很多网友就想去了解一下有关的故事,看最后的赢家正在进行拍摄,进行紧张的录制过程中,估计过不多长时间会播出,但有的网友……光头强死了图片还有血恐怖究竟怎么回事呢《熊出没》是一部大人和小孩子都十分喜欢看的动画片,其中光头强是一个景点角色,也一直受到了很多孩子的喜爱。但是近期却有传出光头强死了图片还有血的消息,且还说场面十分恐怖(原视频已……熊出没2034年大结局是真的吗(熊出没观看顺序全部)《熊出没》可以说是陪伴了很多人童年的动画片,到现在为止也是出现了很多动画,电影,甚至还有舞台剧。最近网上有传言称熊出没2034年大结局,一时间大家都感叹ldquo;童年rdqu……你还不懂针式打印机出现故障发出的信号?这四种信号你要知道点击上方关注绘威打印,我专业,您轻松!当我们在使用针式打印机时,有时候会遇到各种各样的问题,但随着科技的发展,打印机技术越来越成熟,我们的打印机也会根据故障情况向使用者发……女儿们的恋爱4什么时候放出,女儿们的恋爱4嘉宾名单女儿们的恋爱说出来很多人不清楚,可女儿们的恋爱4什么时候放出,很多网友就想去了解一下有关的故事,看女儿们的恋爱4早都做好准备,并有提早放出的消息给网友来公布,但有的网友就不清楚……企业级内容智能运营平台易有料获金沙江创投千万美金A轮融资近日,杭州易有料科技有限公司(以下简称易有料)获得金沙江创投独家投资的千万美元A轮融资,这是继2020年1月获得光云天使轮融资后最新一轮融资。易有料成立于2019年,是一……内置NFC公交卡,AI高清双摄,米兔儿童学习手表4真的不一般前言儿童安全问题在我国乃至全球都是一个非常热门的话题,针对儿童的安全问题每个国家都制定了一些相应的举措,但依然不能避免儿童走失、被拐等问题的发生。我国打拐风暴从未间断过,……陈小桥最强大脑是女的吗陈小桥个人资料看过最强大脑的观众都知道陈小桥,她是来自于加州理工大学的女学霸,在节目中她的表现引来了不少观众对她的关注,那么对于陈小桥最强大脑是女的吗大家还是很好奇的,下面就和小编一起来看看……偷心盗贼!新款宝马3系海外版官图亮相,网友这谁不心动?近日,新款宝马3系海外版官图已经正式亮相,依图可见,该车的设计非常有档次感,颜值方面塑造得简直是没得挑。在外观方面,新车采用了最新的家族式设计语言,前脸采用了依旧经典的双……日在校园最污一集曝光动漫日在校园剧情简介及剧照日在校园是一部由游戏改编而成电视动漫,剧情较h的,日在校园一共只有12集,其中有6集是日在校园最污的一集了,日在校园最污一集的曝光令更是让大部分观众觉得过瘾。日在校园最污一集曝……任鲁豫年龄多大了任鲁豫老婆近照曝光任鲁豫,1977年5月9日出生于河南新乡,毕业于河南大学文学院中文系,中国内地节目主持人。1997年,担任河南电视台《河南新闻联播》节目的播音员和主持人。2002年进入中……跳跳哥哥怎么样阴阳师跳跳哥哥技能简介跳跳哥哥怎么样:阴阳师跳跳哥哥技能简介跳跳哥哥有着不错的攻击和速度,但是本身没什么输出技能,技能全是辅助生存的,但是跳跳哥哥生命防御很低。在做封印任务的时候一般会遇到跳跳……
2022取代锂电池新能源汽车的行业是元宇宙氢能5G铝21世纪一定是新能源革命、信息突破、量子纠缠、生命生物探索、反重力的探索与认识时代。21世纪,人类一定会找到传统的能源替代。锂电池、新能源汽车毫无疑问在19、20、……消费观正在悄然改变我们如今直播带货如火如荼的潮流之中,我们或许没有发现,我们的购物行为发生了戏剧性转变,这一行为,准确的说,我们的消费行为,正在从理性转为非理性。在互联网销售兴起之初,很多人是……必须要公平几年前,马老师曾调侃道:教育一直会在,但新东方不一定会在。俞公也曾公开说道,10年内,阿里巴巴可能会在,100年后肯定不在。而100年后教育会在,新东方也会在。本以……国产氢能豪华SUV正式亮相,加氢几分钟续航1千公里,真正的新导语:国产氢能豪华SUV正式亮相,加氢几分钟续航1千公里,真正的新能源大家好,很高兴再次与大家做分享,随着汽车市场的快速爆发,燃油汽车已经显得力不从心了,无论是国内还是全……红海变蓝海?电动自行车迎来4000亿增量市场争夺战永远不会堵车的,不只有摩托车,还有两轮电动车。两轮电动车,正在成为许多人的新宠儿,而这个万亿市场,经过十几年的快速发展,市场已经趋于饱和,有限空间下的辗转腾挪也让对手间的……工程屏从定制走向标准量化智能一体机将淘汰工程拼接屏?疫情平缓后,市场逐渐恢复正常,行业内竞争激烈,纷纷发力细分市场。LED小间距显示屏作为近年来兴起的新型显示技术,在市场持续升温的状况下呈现出高速增长的趋势。在市场持续解放的情况……Gopro10谍照已出,Action2要截胡发布?大家好,弹指一挥间又到秋天了,不知道大家又没注意到:大疆今年手持方面发布了0个新品口袋2换个颜色不算新品吧。最近打手听到了一些风声,虽然没有石锤,但是因为消息来源比较靠谱……iPhone13支持戴口罩面容识别?苹果正在测试新的面容识别据苹果资深爆料者JonProsser表示,苹果正在测试一个新的面容识别组件,这款组件被开发者发现,并且套在iPhone12上进行测试。并且从这套组件的样式来看,这和之前曝……阿里方面组织架构调整,俞永福任本地生活公司CEO日前,阿里巴巴首席执行官张勇发内部全员信称,经过本地生活公司董事会批准,俞永福担任本地生活公司CEO,代表集团继续分管包括本地生活公司、高德、飞猪在内的生活服务板块;由吴嘉接替……TCL华星大方承认为三星手机提供OLED面板,目的何在?〔钉科技报道〕今年上半年,中国两大面板巨头京东方和TCL华星的业绩都大增。当然,从披露的数据来看,京东方作为行业一哥的地位仍非常稳固,而TCL华星的增长势头也很凶猛。尽管……雷柏机器人智能物流方案,为企业仓储创新利润随着近两年新能源汽车市场的快速发展,以及国家政策的支持和地方政策的扶持下,一大批上游动力电池企业也迅速兴起,以期望在这一新兴行业里获得更多收益。与此同时,老牌新能源企业也面临着……越级可以,不要那么丧心病狂好吗?DC评余音SG03定制级的佩戴是真舒服一直以来定制耳机在发烧友心中可谓是绝对的上上品,不论是其高昂的售价,还是明星亲着的背书,甚至是确实过硬的音频效果表现,都让每个玩家对其垂涎。不过并不是……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网