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

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

Springboot——jxls实现同sheet多个列表展示

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

分布式软件架构——服务端缓存的三种属性

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

Flink之Watermark策略代码模板

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

ubuntu 安装postgresql,增加VECTOR向量数据库插件 踏坑详细流程

PGSQL安装&#xff0c;删除&#xff0c;运行&#xff0c;修改密码流程 Ubuntu18.04安装与配置postgresql含远程连接教程&#xff08;含踩坑记录&#xff09;_sudo apt-get install postgresql-CSDN博客 详细安装流程以上博客&#xff0c;自己也记录下 安装vector扩展连接 声明…...

基于Springboot实现影视影院订票选座管理系统【项目源码+论文说明】分享

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

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

异构无线接入网络的能源效率 论文信息&#xff1a;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连…...

光引擎、光模块、光器件之间的关系和区别

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

【办公-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组件本身并不支持宽度自适应&#xff0c;但实际项目需要&#xff0c;而且多处有用到table组件&#xff0c;所以尝试着自己来二次封装一下组件 想法 刚开始的想法很简单&#xff0c;就是获取每一列中数据和标题在表格中的长度&#xff0c;然后将当中最大的长度作为该列…...

Node.js代码漏洞扫描工具介绍——npm audit

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

node.js知识系列(3)-每天了解一点

目录 1. Express.js 中的中间件2. 处理路由和请求3. RESTful 路由4. 身份验证和授权5. 视图引擎6. 错误处理中间件7. 文件上传处理8. Cookie 和 Session 管理9. 路由参数和查询参数10. 处理跨域请求&#xff08;CORS&#xff09; &#x1f44d; 点赞&#xff0c;你的认可是我创…...

Zabbix监控系统 自定义监控项、自动发现与自动注册

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

Python信号之分享

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

环信web、uniapp、微信小程序SDK报错详解---登录篇

项目场景&#xff1a; 记录对接环信sdk时遇到的一系列问题&#xff0c;总结一下避免大家再次踩坑。这里主要针对于web、uniapp、微信小程序在对接环信sdk时遇到的问题。主要针对报错400、404、401、40 (一) 登录用户报400 原因分析&#xff1a; 从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.岛屿的周长 分析&#xff1a; 1.陆地的旁边是海面&#xff0c;存在周长2.陆地在边界上&#xff0c;存在周长 思路一&#xff1a;深度优先遍历 1.通过记录访问情况来访问数据 class Solution { public:int direct[4][2]{{0,1},{0,-1},{1,0},{-1,0}};int res0;void dfs(…...

C++ - 完美语义(右值引用的中篇) - lambda表达式

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

常见排序算法详解

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

监控搭建-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、背景 随着项目信息化进程的推进&#xff0c;操作系统、…...

指纹浏览器开发指南-EasyBR

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

qml入门

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

一文熟练使用python修改Excel中的数据

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

java Spring Boot在配置文件中关闭热部署

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

【物联网】Arduino+ESP8266物联网开发(一):开发环境搭建 安装Arduino和驱动

ESP8266物联网开发 1.开发环境安装 开发软件下载地址&#xff1a; 链接: https://pan.baidu.com/s/1BaOY7kWTvh4Obobj64OHyA?pwd3qv8 提取码: 3qv8 1.1 安装驱动 将ESP8266连接到电脑上&#xff0c;安装ESP8266驱动CP210x 安装成功后&#xff0c;打开设备管理器&#xff0c…...

自定义UI对象转流程节点

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

P1-P5_动手学深度学习-pytorch(李沐版,粗浅的笔记)

目录 预告  1.学习深度学习的关键是动手  2.什么是《动手学深度学习》  3.曾经推出的版本&#xff08;含github链接&#xff09; 一、课程安排  1.目标  2.内容  3.上课形式  4.你将学到什么  5.资源 二、深度学习的介绍  1.AI地图  2.深度学习在一些应用上…...