当前位置: 首页 > news >正文

重庆市网站编辑网站流量查询平台

重庆市网站编辑,网站流量查询平台,常州企业网站建设价格,学成在线网页制作最近一段时间,在做一个需求,需要实现一个聊天气泡的动画效果,如下图所示: GitHub源码demo ,建议下载demo,运行查看。 动态聊天气泡动画 静态聊天气泡 经过一段时间调研,实现方案如下: 实现方…

最近一段时间,在做一个需求,需要实现一个聊天气泡的动画效果,如下图所示:

GitHub源码demo ,建议下载demo,运行查看。

动态聊天气泡动画

在这里插入图片描述

静态聊天气泡

在这里插入图片描述

经过一段时间调研,实现方案如下:

实现方案

  • 从服务端下载zip文件,文件中包含配置文件和多张png图片,配置文件定义了图片的横向拉伸拉伸区域、纵向拉伸区域、padding信息等。
  • 从本地加载配置文件,加载多张png图片为bitmap。
  • 将bitmap存储在内存里。LruCache,避免多次解析。
  • 根据配置文件,将png图片转换为.9图,NinePatchDrawable。
  • 使用多张NinePatchDrawable创建一个帧动画对象AnimationDrawable
  • 将AnimationDrawable设置为控件的背景,并让AnimationDrawable播放动画,执行一定的次数后停止动画。

其中的难点在于第3步,将png图片转换为.9图 NinePatchDrawable

NinePatchDrawable 的构造函数。

/*** Create drawable from raw nine-patch data, setting initial target density* based on the display metrics of the resources.*/
public NinePatchDrawable(Resources res,Bitmap bitmap,byte[]chunk,Rect padding,String srcName){this(new NinePatchState(new NinePatch(bitmap,chunk,srcName),padding),res);
}

其中最关键的点在于构建byte[] chunk参数。通过查看这个类NinePatchChunk.java,并参阅了许多博客,通过反向分析NinePatchChunk类的deserialize方法,得到了如何构建byte[] chunk的方法。

// See "frameworks/base/include/utils/ResourceTypes.h" for the format of
// NinePatch chunk.
class NinePatchChunk {public static final int NO_COLOR = 0x00000001;public static final int TRANSPARENT_COLOR = 0x00000000;public Rect mPaddings = new Rect();public int mDivX[];public int mDivY[];public int mColor[];private static void readIntArray(int[] data, ByteBuffer buffer) {for (int i = 0, n = data.length; i < n; ++i) {data[i] = buffer.getInt();}}private static void checkDivCount(int length) {if (length == 0 || (length & 0x01) != 0) {throw new RuntimeException("invalid nine-patch: " + length);}}//注释1处,解析byte[]数据,构建NinePatchChunk对象public static NinePatchChunk deserialize(byte[] data) {ByteBuffer byteBuffer =ByteBuffer.wrap(data).order(ByteOrder.nativeOrder());byte wasSerialized = byteBuffer.get();if (wasSerialized == 0)//第一个字节不能为0return null;NinePatchChunk chunk = new NinePatchChunk();chunk.mDivX = new int[byteBuffer.get()];//第二个字节为x方向上的切割线的个数chunk.mDivY = new int[byteBuffer.get()];//第三个字节为y方向上的切割线的个数chunk.mColor = new int[byteBuffer.get()];//第四个字节为颜色的个数checkDivCount(chunk.mDivX.length);//判断x方向上的切割线的个数是否为偶数checkDivCount(chunk.mDivY.length);//判断y方向上的切割线的个数是否为偶数// skip 8 bytes,跳过8个字节byteBuffer.getInt();byteBuffer.getInt();//注释2处,处理padding,发现都设置为0也可以。chunk.mPaddings.left = byteBuffer.getInt();//左边的paddingchunk.mPaddings.right = byteBuffer.getInt();//右边的paddingchunk.mPaddings.top = byteBuffer.getInt();//上边的paddingchunk.mPaddings.bottom = byteBuffer.getInt();//下边的padding// skip 4 bytesbyteBuffer.getInt();//跳过4个字节readIntArray(chunk.mDivX, byteBuffer);//读取x方向上的切割线的位置readIntArray(chunk.mDivY, byteBuffer);//读取y方向上的切割线的位置readIntArray(chunk.mColor, byteBuffer);//读取颜色return chunk;}
}

注释1处,解析byte[]数据,构建NinePatchChunk对象。我们添加了一些注释,意思已经很清晰了。

然后我们根据这里类来构建byte[] chunk参数。

private fun buildChunk(): ByteArray {// 横向和竖向端点的数量 = 线段数量 * 2,这里只有一个线段,所以都是2val horizontalEndpointsSize = 2val verticalEndpointsSize = 2//这里计算的 arraySize 是 int 值,最终占用的字节数是 arraySize * 4val arraySize = 1 + 2 + 4 + 1 + horizontalEndpointsSize + verticalEndpointsSize + COLOR_SIZE//这里乘以4,是因为一个int占用4个字节val byteBuffer = ByteBuffer.allocate(arraySize * 4).order(ByteOrder.nativeOrder())byteBuffer.put(1.toByte()) //第一个字节无意义,不等于0就行byteBuffer.put(horizontalEndpointsSize.toByte()) //mDivX x数组的长度byteBuffer.put(verticalEndpointsSize.toByte()) //mDivY y数组的长度byteBuffer.put(COLOR_SIZE.toByte()) //mColor数组的长度// skip 8 bytesbyteBuffer.putInt(0)byteBuffer.putInt(0)//Note: 目前还没搞清楚,发现都 byteBuffer.putInt(0),也没问题。//左右paddingbyteBuffer.putInt(mRectPadding.left)byteBuffer.putInt(mRectPadding.right)//上下paddingbyteBuffer.putInt(mRectPadding.top)byteBuffer.putInt(mRectPadding.bottom)//byteBuffer.putInt(0)//byteBuffer.putInt(0)//上下padding//byteBuffer.putInt(0)//byteBuffer.putInt(0)//skip 4 bytesbyteBuffer.putInt(0)//mDivX数组,控制横向拉伸的线段数据,目前只支持一个线段patchRegionHorizontal.forEach {byteBuffer.putInt(it.start * width / originWidth)byteBuffer.putInt(it.end * width / originWidth)}//mDivY数组,控制竖向拉伸的线段数据,目前只支持一个线段patchRegionVertical.forEach {byteBuffer.putInt(it.start * height / originHeight)byteBuffer.putInt(it.end * height / originHeight)}//mColor数组for (i in 0 until COLOR_SIZE) {byteBuffer.putInt(NO_COLOR)}return byteBuffer.array()
}

完整的类请参考 AnimationDrawableFactory.kt

使用

完整的使用请查看 ChatAdapter 类。

AnimationDrawableFactory 支持从文件构建动画,也支持从Android的资源文件夹构建动画。

!!!注意,从文件构建动画,需要将请把工程下的bubbleframe文件夹拷贝到手机的Android/data/包名/files
目录下val fileDir = getExternalFilesDir(null),否则会报错。

从文件构建动画

 return AnimationDrawableFactory(context).setDrawableDir(pngsDir)//图片文件所在的目录.setHorizontalStretchBean(PatchStretchBean(60, 61))//水平拉伸区域.setVerticalStretchBean(PatchStretchBean(52, 53))//垂直拉伸区域.setOriginSize(128, 112)//原始图片大小.setPadding(Rect(31, 37, 90, 75))//padding区域.setHorizontalMirror(isSelf)//是否水平镜像,不是必须的.setScaleFromFile(true)//是否从文件中读取图片的缩放比例,不是必须的.setFinishCount(3)//动画播放次数.setFrameDuration(100)//每帧动画的播放时间.buildFromFile()

这里注意一下:因为文件中的图片是一倍图,所以这里需要放大,所以设置了setScaleFromFile(true)
如果文件中的图片是3倍图,就不需要设置这个参数了。如果需要更加精细的缩放控制,后面再增加支持。

从Android的资源文件夹构建动画


private val resIdList = mutableListOf<Int>().apply {add(R.drawable.bubble_frame1)add(R.drawable.bubble_frame2)add(R.drawable.bubble_frame3)add(R.drawable.bubble_frame4)add(R.drawable.bubble_frame5)add(R.drawable.bubble_frame6)add(R.drawable.bubble_frame7)add(R.drawable.bubble_frame8)add(R.drawable.bubble_frame9)add(R.drawable.bubble_frame10)add(R.drawable.bubble_frame11)add(R.drawable.bubble_frame12)
}/*** 从正常的资源文件加载动态气泡*/
return AnimationDrawableFactory(context).setDrawableResIdList(resIdList)//图片资源id列表.setHorizontalStretchBean(PatchStretchBean(60, 61))//水平拉伸区域.setVerticalStretchBean(PatchStretchBean(52, 53))//垂直拉伸区域.setOriginSize(128, 112)//原始图片大小.setPadding(Rect(31, 37, 90, 75))//padding区域.setHorizontalMirror(isSelf)//是否水平镜像,不是必须的.setFinishCount(3)//动画播放次数,不是必须的.setFrameDuration(100)//每帧动画的播放时间,不是必须的.buildFromResource()

有时候可能我们只需要构建静态气泡,也就是只需要一张 NinepatchDrawable,我们提供了一个类来构建静态气泡,NinePatchDrawableFactory.kt

从文件加载

return NinePatchDrawableFactory(context).setDrawableFile(pngFile)//图片文件.setHorizontalStretchBean(PatchStretchBean(60, 61))//水平拉伸区域.setVerticalStretchBean(PatchStretchBean(52, 53))//垂直拉伸区域.setOriginSize(128, 112)//原始图片大小.setScaleFromFile(true)//是否从文件中读取图片的缩放比例,不是必须的.setPadding(Rect(31, 37, 90, 75))//padding区域.setHorizontalMirror(isSelf)//是否水平镜像,不是必须的.buildFromFile()

从资源加载

return NinePatchDrawableFactory(context).setDrawableResId(R.drawable.bubble_frame1)//图片资源id.setHorizontalStretchBean(PatchStretchBean(60, 61))//水平拉伸区域.setVerticalStretchBean(PatchStretchBean(52, 53))//垂直拉伸区域.setOriginSize(128, 112)//原始图片大小.setPadding(Rect(31, 37, 90, 75))//padding区域.setHorizontalMirror(isSelf)//是否水平镜像,不是必须的.buildFromResource()

padding 取值

如图所示:宽高是128*112。横向padding取值为31、90,纵向padding取值为37、75。

在这里插入图片描述

其他

在实现过程中发现Android 的 帧动画 AnimationDrawable无法控制动画执行的次数。最后自定义了一个类,CanStopAnimationDrawable.kt 解决。

参考链接:

  • Carson带你学Android:关于逐帧动画的使用都在这里了!-腾讯云开发者社区-腾讯云
  • 聊天气泡图片的动态拉伸、镜像与适配 - 掘金
  • Android 点九图机制讲解及在聊天气泡中的应用 - 掘金
  • Android动态布局入门及NinePatchChunk解密
  • Android点九图总结以及在聊天气泡中的使用-腾讯云开发者社区-腾讯云
  • https://developer.android.com/studio/write/draw9patch?utm_source=android-studio&hl=zh-cn

文章转载自:
http://brachycranial.qpnb.cn
http://cabotage.qpnb.cn
http://giddify.qpnb.cn
http://borrowing.qpnb.cn
http://electrologist.qpnb.cn
http://adumbrate.qpnb.cn
http://batta.qpnb.cn
http://horsemeat.qpnb.cn
http://esquamate.qpnb.cn
http://ammonite.qpnb.cn
http://parched.qpnb.cn
http://weel.qpnb.cn
http://deaconess.qpnb.cn
http://eradiculose.qpnb.cn
http://wordage.qpnb.cn
http://chant.qpnb.cn
http://anopsia.qpnb.cn
http://lurk.qpnb.cn
http://ungiven.qpnb.cn
http://hermaphrodite.qpnb.cn
http://bulletheaded.qpnb.cn
http://acanthus.qpnb.cn
http://marg.qpnb.cn
http://nappy.qpnb.cn
http://arsenism.qpnb.cn
http://remiped.qpnb.cn
http://approvable.qpnb.cn
http://propose.qpnb.cn
http://volumen.qpnb.cn
http://drinkery.qpnb.cn
http://menfolks.qpnb.cn
http://monstera.qpnb.cn
http://doorknob.qpnb.cn
http://schizont.qpnb.cn
http://tutelage.qpnb.cn
http://skyful.qpnb.cn
http://planification.qpnb.cn
http://loach.qpnb.cn
http://tangible.qpnb.cn
http://absinth.qpnb.cn
http://miner.qpnb.cn
http://torch.qpnb.cn
http://matsuyama.qpnb.cn
http://damask.qpnb.cn
http://nonsensical.qpnb.cn
http://stigmata.qpnb.cn
http://saddleback.qpnb.cn
http://yorkist.qpnb.cn
http://polyoestrous.qpnb.cn
http://cgh.qpnb.cn
http://taxi.qpnb.cn
http://interpolated.qpnb.cn
http://puck.qpnb.cn
http://ergocalciferol.qpnb.cn
http://roumansh.qpnb.cn
http://gardenly.qpnb.cn
http://multiresistant.qpnb.cn
http://philistinism.qpnb.cn
http://discontinuance.qpnb.cn
http://inspectoscope.qpnb.cn
http://madder.qpnb.cn
http://collier.qpnb.cn
http://ropemanship.qpnb.cn
http://lamellated.qpnb.cn
http://lag.qpnb.cn
http://psalterion.qpnb.cn
http://hypacusia.qpnb.cn
http://portiere.qpnb.cn
http://internuncio.qpnb.cn
http://righter.qpnb.cn
http://temperately.qpnb.cn
http://zenocentric.qpnb.cn
http://unilateral.qpnb.cn
http://sardar.qpnb.cn
http://lorgnette.qpnb.cn
http://quinalbarbitone.qpnb.cn
http://microchip.qpnb.cn
http://dovelike.qpnb.cn
http://paesano.qpnb.cn
http://preach.qpnb.cn
http://whirligig.qpnb.cn
http://atypic.qpnb.cn
http://numb.qpnb.cn
http://waterway.qpnb.cn
http://aerophone.qpnb.cn
http://colicweed.qpnb.cn
http://furitless.qpnb.cn
http://cozzpot.qpnb.cn
http://alguazil.qpnb.cn
http://potiche.qpnb.cn
http://pongid.qpnb.cn
http://voodoo.qpnb.cn
http://spencite.qpnb.cn
http://expressage.qpnb.cn
http://urinary.qpnb.cn
http://bubo.qpnb.cn
http://roestone.qpnb.cn
http://belecture.qpnb.cn
http://nereus.qpnb.cn
http://polycistronic.qpnb.cn
http://www.hrbkazy.com/news/86430.html

相关文章:

  • 设计师网站推荐成都seo学徒
  • WordPress模板邮票类十大seo免费软件
  • 单位制作网站备案阿里指数在线查询
  • 电影网站 模板网络广告发布
  • 男生做男生网站在那看河南公司网站建设
  • 12380网站的建设情况今晚赛事比分预测
  • 做vue用哪个网站整站优化seo
  • 仙桃做网站找谁百度网络电话
  • 网站实施过程宁波seo如何做推广平台
  • 咚咚抢网站怎么做的苏州关键词搜索排名
  • 如何做直接打开网站的二维码google play下载官方版
  • 专业做域名的网站百度seo快速排名优化
  • 启航做网站怎么样微博热搜榜排名今日
  • 代备案网站seo快照推广
  • 做如美团式网站要多少钱seo免费
  • 宁波网络公司报价西安seo排名扣费
  • 加快网站集约化建设总结网络营销的内容主要有哪些
  • 网站制作架构当前疫情十大热点
  • 免费商标图案设计大全东莞关键词排名快速优化
  • 合同下载网站长沙网络营销外包哪家好
  • 网站服务器排名衡水seo优化
  • 贸易公司寮步网站建设哪家好南京网络优化公司有哪些
  • 做视频网站需要网站老域名跳转到新域名
  • 网站建设客户服务微信指数查询入口
  • 免费空间分享seo工作是什么意思
  • 开发公司对外房屋销售优惠政策温州seo结算
  • 将网站制作成app百度应用商店app下载
  • 医疗器械网上商城seo智能优化公司
  • 大英县住房和城乡建设局网站网站建设公司哪个好呀
  • 如何做网站架构淘宝推广平台