Android 视图动画与属性动画的区别
Android的视图动画和属性动画在功能和使用上有一些明显的区别。
视图动画主要作用于视图,实现如缩放、旋转等效果。这种动画效果相对固定,只能应用于视图对象,且只能改变视图的大小和位置,而不能真正改变视图的属性。视图动画在Android 3.0以前的版本中广泛应用,但其在应用中的灵活性相对较低。
相比之下,属性动画在Android 3.0之后引入,其功能和灵活性都大大增强。属性动画可以对一个对象的属性进行操作,不仅能应用于视图对象,还能应用于任何对象。它不仅能实现缩放、旋转等效果,还能自定义动画效果,监听动画的过程,并在动画过程中或完成后执行特定的动作。属性动画通过改变对象的属性来实现动画,可以真正改变对象的属性。
总的来说,属性动画比视图动画更强大和灵活。它不仅可以实现视图动画的所有功能,还具有更多的自定义选项和更广泛的应用范围。
正文
我们知道视图动画并不能真正影响VIew的属性,而view的相对位置,大小等都是view的属性,所以视图动画并不能真正的改变view,所以属性动画便有了价值。同时之前的视图动画不能动态的改变背景颜色什么的,而属性动画却可以。下面我们来看属性动画的一些相关类:
- ValueAnimator :Animator 的子类,实现了动画的整个处理逻辑,也是属性动画最为核心的类
- ObjectAnimator:对象属性动画的操作类,继承自ValueAnimator,通过该类使用动画的形式操作对象的属性
- TimeInterpolator:时间插值器,它的作用是根据时间流逝的百分比来计算当前属性值改变的百分比,系统预置的有线性插值器、加速减速插值器、减速插值器等。
- TypeEvaluator:TypeEvaluator翻译为类型估值算法,它的作用是根据当前属性改变的百分比来计算改变后的属性值
- Property:属性对象、主要定义了属性的set和get方法
- PropertyValuesHolder:持有目标属性Property、setter和getter方法、以及关键帧集合的类。
- KeyframeSet:存储一个动画的关键帧集
ValueAnimator
那么应该如何理解ValueAnimator呢?ValueAnimator可以看做一个动画时间值的处理分发器,他逻辑上并不直接操作view的属性。我们通过监听去获取到分发下来的值去对view进行操作,所以说,一个valueAnimator 分发下来的值只建议操作一个属性,写到一起也不是不行。那么如何获取到值的分发就很重要了。
ValueAnimator主要支持以下设置:
- setDuration 设置动画执行时间。
- setRepeatCount 重复次数 当等于ValueAnimator.INFINITE 表示循环。
- setRepeatMode 设置循环播放模式,正序播放(RESTART)和逆序播放(REVERSE)。
- setStartDelay 延时开始时间,第一次生效后,重复动画过程中将不再生效。
- getAnimatedValue 获取当前运动点的值。
- start 开始动画
- cancel 取消动画
- addUodateListenner 添加动画值的变化的监听。
- addListener 添加动画监听。 开始start,结束end ,取消cancel,重复repeat
- removeUpdateListener 移除更新值的监听,removeAllUpdateListeners 移除所有更新值的监听。
- removelistener 移除动画监听,removeListeners 移除所有的动画监听
- setStartDelay 延时多久开始动画,单位毫秒。
- clone 完全克隆一个动画对象,包括他的所有设置及其监听器代码。
构造器
- static ValueAnimator ofInt(int… values)
- static ValueAnimator ofArgb(int… values)
- static ValueAnimator ofFloat(float… values)
- static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder… values)
- static ValueAnimator ofObject(TypeEvaluator evaluator, Object… values)
可以看到入参都是多个。支持int,argb,float,PropertyValuesHolder,TypeEvaluator等类型。
如何实现视图动画的效果
我们知道,视图动画支持缩放scale、alpha 透明度、rotate旋转、translate平移。而ValueAnimator 主要是基于时间将我们设置到值进行分发,所以我们需要获取到每个片的值的改变。这个就是上面提到的addUodateListenner
translate 平移效果
我们知道,view的位置的决定是由layout(l,t,r,b) 个参数决定的。
- l 视图的左边界相对于其父视图的位置。
- t 顶部
- r 右边
- 底部
所以说,我们平移,就可以通过改变view.layout 中的值进行处理。
val animator=ValueAnimator.ofInt(0,400)
animator.duration = 1000
animator.addUpdateListener {val curValue :Int= it.animatedValue as Intbinding.btn1.layout(curValue,0,curValue+binding.btn1.width,binding.btn1.height)
}
animator.start()
上面的代码,我们将一个view 在X轴方向上,从0移动到400px 的位置。整个动画耗时1秒。下面代码也是平移:
val animator=ValueAnimator.ofInt(0,400)
animator.duration = 1000
animator.addUpdateListener {val curValue :Int= it.animatedValue as Intbinding.btn1.translationX=curValue.toFloat()
}
animator.start()
那么平移还有没有其他思路,我们知道view 还有一个滚动函数。如果说是平移内容,跑马灯效果,那么就可以调用scrollTo 函数。
scale 缩放
view 也提供了scale 函数用于缩放view。那么我们尝试将整个view在1秒内从1变化到2.
val animator=ValueAnimator.ofFloat(1f,2f)animator.duration = 1000animator.addUpdateListener {val curValue :Float= it.animatedValue as Floatbinding.btn1.scaleX=curValue}animator.start()
可以看到,我们只是缩放了X轴,并没有缩放Y轴,缩放Y轴则是调用scaleY
roate 旋转
view 提供了rotation、rotationX、rotationY
val animator=ValueAnimator.ofFloat(0f,360f)animator.duration = 1000animator.addUpdateListener {val curValue :Float= it.animatedValue as Float//binding.btn1.rotation=curValuebinding.btn1.rotationX=curValue//binding.btn1.rotationY=curValue}animator.start()
可以看到,上面的代码,我们围绕X轴进行了翻转360度。
alpha 透明度
改变透明度分为改变整个view的透明度和改变view 背景的透明度。
val animator=ValueAnimator.ofFloat(1f,0f,1f)
animator.duration = 3000
animator.addUpdateListener {val curValue :Float= it.animatedValue as Floatbinding.btn1.alpha=curValue
}
animator.start()
可以看到,上面代码是将一个view的透明度从1改变到0完全透明在到1完全不透明。
val animator=ValueAnimator.ofFloat(255f,0f,255f)animator.duration = 3000animator.addUpdateListener {val curValue :Float= it.animatedValue as Floatbinding.btn1.background.alpha=curValue.toInt()}animator.start()
上面代码是将view的背景从完全不透明改到完全透明,再到完全不透明。
改变颜色
我们将按钮的颜色由黑色变化到红色。
val animator=ValueAnimator.ofArgb(Color.BLACK,Color.RED)animator.duration = 1000animator.addUpdateListener {val curValue :Int= it.animatedValue as Intbinding.btn1.setTextColor(curValue)}animator.start()
}
总结
可以看到,我们上面的几乎的所有写法都是基于addUpdateListener,然后去改变view的属性。所以说,限制我们的全是想象力。这个动画只要view属性支持,我们就可以整出各种花样来。
自定义插值器与evaluator
我们在视图动画里面,知道Android 系统给我们提供了很多插值器。哪些插值器,在属性动画中同样可用。默认的插值器是LinearInterpolator。
自定义插值器
可以看懂LinearInterpolator 继承于BaseInterpolator。最终可以看到都是继承于TimeInterpolator,而这个接口只有一个函数。
float getInterpolation(float input);
而LinearInterpolator 则是原封不动的将input 给返回了,所以说,自定义插值器其实是对于input 进行计算,然后返回。在这个接口的描述中我们知道 input 的取值范围是0到1。这个用于表示动画执行时间的百分比。所以这个干预的是动画的时间。
evaluator
通过自定义插值器的描述,我们可以知道,插值器只是对于动画时长的处理。但是我们通过构造器,发现可以传入很多种类型,而对不同类型的值的分发,就靠evaluator了。所以不同的值类型有自己的evaluator.所有的evaluator都实现 TypeEvaluator 接口。默认的有:
- IntEvaluator
- FloatEvaluator
- ArgbEvaluator
这个干预的是动画分发下来的值。我们看下IntEvaluator的实现代码:
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {int startInt = startValue;return (int)(startInt + fraction * (endValue - startInt));
}
他是开始位置+百分比*(结束位置-开始位置)。所以,evaluate会调用多次。
使用ofObject 分发想要的内容
比如说,有一个需求,分发A到Z,因为涉及到动画,所以考虑写到动画里面。那么结合上面的知识,我们就需要自定义一个Evaluator.结合IntEvaluator 的经验。这里又一个知识点。就是每个char都有一个ASCII码,所以我们通过ASCII 码进行计算。
class CharEvaluator : TypeEvaluator<Char> {override fun evaluate(fraction: Float, startValue: Char, endValue: Char): Char {val start = startValue.codeval end = endValue.codeval cur = start + fraction * (end - start)return cur.toInt().toChar()}
}
class CharEvaluator : TypeEvaluator<Char> {override fun evaluate(fraction: Float, startValue: Char, endValue: Char): Char {val start = startValue.codeval end = endValue.codeval cur = start + fraction * (end - start)return cur.toInt().toChar()}
}
propertyValuesHolder与关键帧KeyFrame
构造器里面有一个 **static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder… values) ** 。通过阅读ValueAnimator 源码可以发现,几乎所有的构造器都会生成一个ProPertyValuesHolder 对象,这个对象其中保存了动画过程中需要操作的属性和对应的值。所以我们可以根据这个对象构造动画,大致分为一下几个大类。
- ofFloat
- ofint
- ofKeyFrame,关键帧
- ofMultFloat
- ofMultInt
- ofObject
当然包含了不同入参的重载函数,可以看到propertyValuesHolder是允许传入多个的,我使用ofInt 等每次都只能生成一个PropertyValuesHolder。
val animator=ValueAnimator.ofPropertyValuesHolder(PropertyValuesHolder.ofFloat("a",0f,10f),PropertyValuesHolder.ofInt("b",1,50),PropertyValuesHolder.ofInt("c",100,50))
animator.duration = 1000
animator.addUpdateListener {LogUtils.e("${it.getAnimatedValue("a")} ${it.getAnimatedValue("b")} ${it.getAnimatedValue("c")} ")
}
animator.start()
当我们设置多个Holderd的时候,可以调用 **Object getAnimatedValue(String propertyName) ** 获取对应的value。如果只有一个值,默认去的第一个,所以 it.animatedValue 就可以获取到。当然一个值也可以传递propertyName 进行获取。
keyFrame 关键帧
我们想要控制动画的速率的变化,可以通过自定义插值器或者自定义Evaluator实现。但是这个涉及到数学知识,为了更方便的解决控制动画速率的问题,Google提供了一个新的思路,Keyframe,这个和帧动画的概念类似,动画将由具体帧决定,而不是计算。而Keyframe 则依旧和ValueAnimator一样,操作的是数据。可以看到keyframe 依旧支持3种类型的重载:
- ofFloat
- ofInt
- ofObject
入参:
- fraction 表示当前显示的进度,即插值器中getInterpolation 函数的返回值。
- value 表示动画当前所在的数值位置,即animateValue .
例如:keyFrame.ofFloat(0.25f,25) 表示动画进度是百分之25,数值是25。
val animator=ValueAnimator.ofPropertyValuesHolder(PropertyValuesHolder.ofKeyframe("a",Keyframe.ofInt(0f,0),Keyframe.ofInt(0.25f,25),Keyframe.ofInt(0.50f,50),Keyframe.ofInt(0.75f,75),Keyframe.ofInt(1f,100),))
animator.duration = 1000
animator.addUpdateListener {LogUtils.e("${it.getAnimatedValue("a")} ")
}
animator.start()
通过Log可以看到,这个同样包含匀速的插值器,所以这个也可以设置插值器。和之前的逻辑是一致的,values 的值必须大于等于2,必须保证有一个开始和一个结束,所以Keyframe 必须大于等于2。
ObjectAnimator
通过上面的例子,我们可以看到,ValueAnimator 只是对值进行了分发,一些属性的设置还需要我们自己写,于是就产生了ObjectAnimator类。结合ValueAnimator 实现动画的经验,ObjectAnimator 其实也就是在addUpdateListener 中帮助我们调用了函数,默认帮我们拼接了set,所以这个应该是反射实现的。
淡入淡出
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(binding.image, "alpha", 1.0f, 0.5f, 0.8f, 1.0f);alphaAnim.setDuration(3000);alphaAnim.start();
旋转
// 旋转ObjectAnimator anim = ObjectAnimator.ofFloat(binding.image, "rotation", 0f, 360f);// 动画时长anim.setDuration(1000);anim.start();
缩放
ObjectAnimator anim = ObjectAnimator.ofFloat(binding.image, "scaleX", 1.0f, 1.5f);anim.setDuration(1000);anim.start();
平移
ObjectAnimator transXAnim = ObjectAnimator.ofFloat(binding.image, "translationX", 100, 400);transXAnim.setDuration(3000);transXAnim.start();
组合同时缩放X与Y
AnimatorSet set = new AnimatorSet();ObjectAnimator animX = ObjectAnimator.ofFloat(binding.image, "scaleX", 1.0f, 1.5f);ObjectAnimator animY = ObjectAnimator.ofFloat(binding.image, "scaleY", 1.0f, 1.5f);// 同时动set.playTogether(animX, animY);set.setDuration(3000);set.start();
组合顺序缩放X与Y
AnimatorSet set = new AnimatorSet();ObjectAnimator animX = ObjectAnimator.ofFloat(binding.image, "scaleX", 1.0f, 1.5f);ObjectAnimator animY = ObjectAnimator.ofFloat(binding.image, "scaleY", 1.0f, 1.5f);// 按照顺序动set.playSequentially(animX, animY);set.setDuration(3000);set.start();
view 生命周期绑定动画
这么写的好处就是view 移除出屏幕就暂停动画了。而且便于recyclerview的复用
binding.image.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {@Overridepublic void onViewAttachedToWindow(View v) {// TODO 设置动画 }@Overridepublic void onViewDetachedFromWindow(View v) {v.clearAnimation();}});
自定义属性与ofObject(Object target, String propertyName,
TypeEvaluator evaluator, Object... values)
那么,当我们需要调用view的自定义函数呢?那么就需要使用这个函数了。还是上面的哪例子,我们A到Z,设置为text。这个时候,就需要用到反射的相关知识了,setText 的入参类型是CharSequence,但是它是通过values去获取到对应的class的,但是我们传入的参数是CharSequence的实现类,所以,基于values 是永远拿不到void setText(CharSequence text)这个函数的。但是我们可以偷换概念。既然65是ASCII码的A,那么我们就用int,然后自己写一个int 入参的函数调用setText.
val animator= ObjectAnimator.ofObject(this,"Text",IntEvaluator(),65,75)animator.duration=1000animator.start()
fun setText(code:Int){binding.btn1.text = code.toChar().toString()
}
当然。写一个入参类型是string 的方法也行。
组合动画 AnimatorSet
因为ValueAnimator 需要自己绑定属性,那么我们做动画的大多数都是基于ObjectAnimator。
- playAwquentially 动画依次执行。
- playTogether 动画一起执行。
- setDuration 单个动画的时长,优先级高于子动画的时长。
- setInterPolator 插值器,优先级高于子动画。
- setTarget 目标动画,这个优先级也高于子动画。
- setStartDelay 设置延时开始动画时长,仅争对AnimatorSet的激活时长,对单个动画的延时设置没有影响。
我们知道动画是否循环播放是又动画本身控制的。所以AnimatorSet 不参与动画循环播放的控制。
animatorSet.builder
用于更精细化的控制组合动画的播放。
- play 播放那个动画
- with 和前面动画一起播放。
- before 先执行这个动画,再执行前面的动画。
- after 前面的动画执行完成后,才执行这个动画
- after 延迟n毫秒后执行动画。
animatorSet 监听器AnimatorListener
- onAnimationStart 开始
- end 结束
- cancel 取消
- repeat 重复
ViewPropertyAnimator
通过ObjectAnimator 可以便捷的设置属性动画,那么还有没有更便捷的呢?那就是ViewPropertyAnimator。
binding.btn1.animate().setDuration(1000).translationX(10f).rotationX(360f).start()
因为这个并没有像ObjectAnimator 一样使用反射,而是通过计算出具体的的属性值,然后调用invalidata() 函数进行重绘,性能是要比ObjectAnimator 高一些,但是反射的性能影响微乎其微,所以他的优势是链式调度与简化了代码的读写。
在xml中的实现
如何通过XML 实现ValueAnimator,ObjectAnimator,AnimatorSet。我们通常不使用ValueAnimator,而是使用ObjectAnimator。
ValueAnimator
对应的标签为animator。通过animatorInflater.loadAnimator() 获取xml中的属性动画。
- duration 动画时长。
- valueFrom 初始动画的值,为float,int和color种类型。
- valueTo 同样3个类型的值。
- startOffset 动画激活延时,单位毫秒。
- repeatConunt 重复次数,infinite 表示无限循环
- repeatMode 重复模式。repeat 正序,reverse 倒序。
- valueType 表示数值类型,和to、from 对应,如果是color 就不需要设置这个值。
- interpolator 设置插值器。
objectAnimator 标签
和animator 标签类似,只是多了一个属性:
- propertyName 对应要操作的属性的名称。
set标签
这个在属性动画中特指animatorSet,用于实现多个属性动画的组合。
总结
整体的属性动画都是还是基于一个分发器和操作view的属性去实现的。通常而言,还是写到代码里面的时候居多,而且通过ViewPropertyAnimator也可以实现一些简单的组合动画什么的。
Android 学习笔录
Android 性能优化篇:https://qr18.cn/FVlo89
Android Framework底层原理篇:https://qr18.cn/AQpN4J
Android 车载篇:https://qr18.cn/F05ZCM
Android 逆向安全学习笔记:https://qr18.cn/CQ5TcL
Android 音视频篇:https://qr18.cn/Ei3VPD
Jetpack全家桶篇(内含Compose):https://qr18.cn/A0gajp
OkHttp 源码解析笔记:https://qr18.cn/Cw0pBD
Kotlin 篇:https://qr18.cn/CdjtAF
Gradle 篇:https://qr18.cn/DzrmMB
Flutter 篇:https://qr18.cn/DIvKma
Android 八大知识体:https://qr18.cn/CyxarU
Android 核心笔记:https://qr21.cn/CaZQLo
Android 往年面试题锦:https://qr18.cn/CKV8OZ
2023年最新Android 面试题集:https://qr18.cn/CgxrRy
Android 车载开发岗位面试习题:https://qr18.cn/FTlyCJ
音视频面试题锦:https://qr18.cn/AcV6Ap
相关文章:

Android 视图动画与属性动画的区别
Android的视图动画和属性动画在功能和使用上有一些明显的区别。 视图动画主要作用于视图,实现如缩放、旋转等效果。这种动画效果相对固定,只能应用于视图对象,且只能改变视图的大小和位置,而不能真正改变视图的属性。视图动画在A…...

Springboot——jxls实现同sheet多个列表展示
文章目录 前言制定模板1、限定模板数据的范围2、设定报表展示项 编写测试类1、将xls模板文件放于 resource 下的 doc文件夹中2、导入依赖文件3、编写接口和导出逻辑 效果预览结论 前言 在之前的博客中Springboot——使用jxls实现excel模板导出excel,具体说明了jxls…...

分布式软件架构——服务端缓存的三种属性
服务端缓存 在透明多级分流系统中,我们以流量从客户端中发出开始,以流量到达服务器集群中真正处理业务的节点结束。一起探索了在这个过程中与业务无关的一些通用组件,包括DNS、CDN、客户端缓存,等等。 实际上,服务端缓…...

Flink之Watermark策略代码模板
方式作用WatermarkStrategy.noWatermarks()不生成watermarkWatermarkStrategy.forMonotonousTimestamps()紧跟最大事件时间watermark生成策略WatermarkStrategy.forBoundedOutOfOrderness()允许乱序watermark生成策略WatermarkStrategy.forGenerator()自定义watermark生成策略 …...

ubuntu 安装postgresql,增加VECTOR向量数据库插件 踏坑详细流程
PGSQL安装,删除,运行,修改密码流程 Ubuntu18.04安装与配置postgresql含远程连接教程(含踩坑记录)_sudo apt-get install postgresql-CSDN博客 详细安装流程以上博客,自己也记录下 安装vector扩展连接 声明…...

基于Springboot实现影视影院订票选座管理系统【项目源码+论文说明】分享
基于Springboot实现影视影院订票选座管理系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个影城管理系统 ,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S架构,面向对象编程思想进行项目开发。在引言中,作者将论…...

mysql批量插入数据,跳过唯一索引报错
数据准备 DROP TABLE IF EXISTS user1; CREATE TABLE user1 ( id INT NOT NULL AUTO_INCREMENT, name VARCHAR(45) NULL, age INT(3) NOT NULL, PRIMARY KEY (id), UNIQUE INDEX u_name (name));insert into user1(name, age) values (zhangshan, 18), (lisi, 19);1. INSERT I…...

论文阅读--Energy efficiency in heterogeneous wireless access networks
异构无线接入网络的能源效率 论文信息:Navaratnarajah S, Saeed A, Dianati M, et al. Energy efficiency in heterogeneous wireless access networks[J]. IEEE wireless communications, 2013, 20(5): 37-43. I. ABSTRACT && INTRODUCTION 本文提出了无…...

Redis的C客户端(hiredis库)使用
文章目录 1、Ubuntu安装redis服务端2、hiredis库的安装3、同步API接口的使用3.1、连接redis数据库redisConnect3.2、发送需要执行的命令redisCommand3.3、redisCommandArgv函数3.4、redisAppendCommand*函数支持管道命令3.5、释放资源3.6、同步连接代码 3.7、异步连接4、redis连…...

光引擎、光模块、光器件之间的关系和区别
最近小编有收到一些用户问“光引擎、光模块、光器件之间的关系和区别?”,众所周知光通信技术一直在不断演进,为满足不断增长的数据传输需求提供了强大的解决方案。而光通信系统中,光引擎、光模块和光器件是关键的组成部分…...

【办公-excel】两个时间相减 (二) - 带毫秒的时间进行相减操作
一、使用内部函数 1.1 效果展示 TEXT(((RIGHT(TEXT(B2,"yyyy-mm-dd hh:mm:ss.000"),LEN(TEXT(B2,"yyyy-mm-dd hh:mm:ss.000"))-FIND(".",TEXT(B2,"yyyy-mm-dd hh:mm:ss.000")))-RIGHT(TEXT(A2,"yyyy-mm-dd hh:mm:ss.000"),…...

二次封装View Design的table组件,实现宽度自适应,内容在一行展示
由于table组件本身并不支持宽度自适应,但实际项目需要,而且多处有用到table组件,所以尝试着自己来二次封装一下组件 想法 刚开始的想法很简单,就是获取每一列中数据和标题在表格中的长度,然后将当中最大的长度作为该列…...

Node.js代码漏洞扫描工具介绍——npm audit
npm audit 运行安全检查 主要作用:检查命令将项目中配置的依赖项的描述提交到默认注册中心,并要求报告已知漏洞。如果发现任何漏洞,则将计算影响和适当的补救措施。如果 fix 提供了参数,则将对包树应用补救措施。 具体参考&#x…...

node.js知识系列(3)-每天了解一点
目录 1. Express.js 中的中间件2. 处理路由和请求3. RESTful 路由4. 身份验证和授权5. 视图引擎6. 错误处理中间件7. 文件上传处理8. Cookie 和 Session 管理9. 路由参数和查询参数10. 处理跨域请求(CORS) 👍 点赞,你的认可是我创…...

Zabbix监控系统 自定义监控项、自动发现与自动注册
Zabbix监控系统 自定义监控项、自动发现与自动注册 一、自定义监控内容部署实例二、zabbix 自动发现与自动注册部署实例2.1 部署zabbix自动发现 一、自定义监控内容部署实例 案列:自定义监控客户端服务器登录的人数 需求:限制登录人数不超过 3 个&#…...

Python信号之分享
在了解了Linux的信号基础之后,Python标准库中的signal包就很容易学习和理解。signal包负责在Python程序内部处理信号,典型的操作包括预设信号处理函数,暂停并等待信号,以及定时发出SIGALRM等。要注意,signal包主要是针…...

环信web、uniapp、微信小程序SDK报错详解---登录篇
项目场景: 记录对接环信sdk时遇到的一系列问题,总结一下避免大家再次踩坑。这里主要针对于web、uniapp、微信小程序在对接环信sdk时遇到的问题。主要针对报错400、404、401、40 (一) 登录用户报400 原因分析: 从console控制台输出及networ…...

DAZ To UMA⭐五.模型在Blender中的配置教程
文章目录 🟥 创建符合UMA的材质球属性1️⃣ 合并材质球🎁 选择材质球🎁 合并材质球🎁 删除多余材质球2️⃣ 将身体按材质球拆分🎁 进入身体编辑模式🎁 全选身体🎁 按材质分割身体🎁 重命名不同部位3️⃣ 将其余部位进行拆分🟧 更正选择缩放🟩 更新骨骼结构…...

网络安全工具汇总
网络安全工具汇总 1. 前言1.1. 工具提供 2. 漏洞库3. 杂项3.1. topology-scanner3.2. MDUT3.3. 404 4. 插件工具4.1. 浏览器插件4.1.1. Heimdallr4.1.2. HackTools4.1.3. SwitchyOmega4.1.4. fofa_view4.1.5. mitaka 4.2. CS插件4.2.1. taowu-cobalt_strike4.2.2. OLa4.2.3. Z1…...

day-65 代码随想录算法训练营(19)图论 part 04
463.岛屿的周长 分析: 1.陆地的旁边是海面,存在周长2.陆地在边界上,存在周长 思路一:深度优先遍历 1.通过记录访问情况来访问数据 class Solution { public:int direct[4][2]{{0,1},{0,-1},{1,0},{-1,0}};int res0;void dfs(…...

C++ - 完美语义(右值引用的中篇) - lambda表达式
前言 之前对右值引用的理解,用使用场景做了详细说明,具体看博客:C - 右值引用 和 移动拷贝-CSDN博客 在 有值引用 当中还有一个 完美转发,请看本篇博客。 完美转发 我们现在看这个例子: void Fun(int& x) { …...

常见排序算法详解
目录 排序的相关概念 排序: 稳定性: 内部排序: 外部排序: 常见的排序: 常见排序算法的实现 插入排序: 基本思想: 直…...

监控搭建-Prometheus
监控搭建-Prometheus 1、背景2、目标3、选型4、Prometheus4.1、介绍4.2、架构4.3、构件4.4、运行机制4.5、环境介绍4.6、数据准备4.7、网络策略4.7.1、主机端口放行4.7.2、设备端口放行 4.8、部署4.9、验证4.10、配置 1、背景 随着项目信息化进程的推进,操作系统、…...

指纹浏览器开发指南-EasyBR
想开发一款指纹浏览器,指纹浏览器名字叫做EasyBR,大致构思了下开发的步骤。 EasyBR指纹浏览器开发指南: 后台技术、前端技术和指纹修改 简介: EasyBR指纹浏览器是一款旨在提供个性化服务和广告定位的浏览器,通过收…...

qml入门
window import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.5Window { //root控件,父窗口是主界面width: 640height: 480visible: true//相对于父控件的偏移量x: 100y:100minimumWidth: 400 //最小宽度minimumHeight: 300 //最小高度ma…...

一文熟练使用python修改Excel中的数据
使用python修改Excel中的内容 1.初级修改 1.1 openpyxl库的功能: openpyxl模块是一个读写Excel 2010文档的Python库,如果要处理更早格式的Excel文档,需要用到额外的库,例如Xlwings。openpyxl是一个比较综合的工具,能…...

java Spring Boot在配置文件中关闭热部署
之前更大家一起搭建了一个热部署的开发环境 但是 大家要清楚一个情况 我们线上程序运行突然内部发生变化这是不可能的。 所以 他就只会对我们开发环境有效 是否开启 我们可以通过 application配置文件来完成 我这里是yml格式的 参考代码如下 spring:devtools:restart:enabled…...

【物联网】Arduino+ESP8266物联网开发(一):开发环境搭建 安装Arduino和驱动
ESP8266物联网开发 1.开发环境安装 开发软件下载地址: 链接: https://pan.baidu.com/s/1BaOY7kWTvh4Obobj64OHyA?pwd3qv8 提取码: 3qv8 1.1 安装驱动 将ESP8266连接到电脑上,安装ESP8266驱动CP210x 安装成功后,打开设备管理器,…...

自定义UI对象转流程节点
自定义UI对象转流程节点 实体自定义对象转bpmn activitiy学习 (动态加签,动态流程图,指定节点跳转,指定多人节点跳转) 前端页面仿的这个 提供一个思路 实体 ActivitiValueVo import io.swagger.annotations.ApiModel; import io.swagger.a…...

P1-P5_动手学深度学习-pytorch(李沐版,粗浅的笔记)
目录 预告 1.学习深度学习的关键是动手 2.什么是《动手学深度学习》 3.曾经推出的版本(含github链接) 一、课程安排 1.目标 2.内容 3.上课形式 4.你将学到什么 5.资源 二、深度学习的介绍 1.AI地图 2.深度学习在一些应用上…...