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

Android自定义控件:一款多特效的智能loadingView

先上效果图(如果感兴趣请看后面讲解):

1、登录效果展示

img

2、关注效果展示

img

1、【画圆角矩形】

画图首先是onDraw方法(我会把圆代码写上,一步一步剖析): 首先在view中定义个属性:private RectF rectf = new RectF();//可以理解为,装载控件按钮的区域

rectf.left = current_left;
rectf.top = 0;      //(这2点确定空间区域左上角,current_left,是为了后面动画矩形变成等边矩形准备的,这里你可以看成0)  
rectf.right = width - current_left; 
rectf.bottom = height;       //(通过改变current_left大小,更新绘制,就会实现了动画效果)
//画圆角矩形 
//参数1:区域
//参数2,3:圆角矩形的圆角,其实就是矩形圆角的半径
//参数4:画笔
canvas.drawRoundRect(rectf, circleAngle, circleAngle, paint)

2、【确定控件的大小】

上面是画圆角,那width和height怎么来呢当然是通过onMeasure;

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {height = measuredHeight(heightMeasureSpec);  //这里是测量控件大小width = measureWidth(widthMeasureSpec);  //我们经常可以看到我们设置控件wrap_content,match_content或者固定值setMeasuredDimension(width, height);
}

下面以measureWidth为例:

private int measureWidth(int widthMeasureSpec) {int result;int specMode = MeasureSpec.getMode(widthMeasureSpec);int specSize = MeasureSpec.getSize(widthMeasureSpec);//这里是精准模式,比如match_content,或者是你控件里写明了控件大小if (specMode == MeasureSpec.EXACTLY) {result = specSize;} else {//这里是wrap_content模式,其实这里就是给一个默认值//下面这段注销代码是最开始如果用户不设置大小,给他一个默认固定值。这里以字体长度来决定更合理//result = (int) getContext().getResources().getDimension(R.dimen.dp_150);//这里是我设置的长度,当然你写自定义控件可以设置你想要的逻辑,根据你的实际情况result = buttonString.length() * textSize + height * 5 / 3;if (specMode == MeasureSpec.AT_MOST) {result = Math.min(result, specSize);}}return result;}

3、【绘制文字text】

这里我是用自己的方式实现:当文字长度超过控件长度时,文字需要来回滚动。所以自定义控件因为你需要什么样的功能可以自己去实现(当然这个方法也是在onDraw里,为什么这么个顺序讲,目的希望我希望你能循序渐进的理解,如果你觉得onDraw方代码太杂,你可以用个方法独立出去,你可以跟作者一样用private void drawText(Canvas canvas) {}), //绘制文字的路径(文字过长时,文字来回滚动需要用到)

private Path textPath = new Path():

textRect.left = 0;
textRect.top = 0;
textRect.right = width;
textRect.bottom = height; //这里确定文字绘制区域,其实就是控件区域
Paint.FontMetricsInt fontMetrics = textPaint.getFontMetricsInt();
//这里是获取文字绘制的y轴位置,可以理解上下居中
int baseline = (textRect.bottom + textRect.top - fontMetrics.bottom - fontMetrics.top) / 2;
//这里判断文字长度是否大于控件长度,当然我控件2边需要留文字的间距,所以不是大于width,这么说只是更好的理解
//这里是当文字内容大于控件长度,启动回滚效果。建议先看下面else里的正常情况
if ((buttonString.length() * textSize) > (width - height * 5 / 3)) {textPath.reset()//因为要留2遍间距,以heigh/3为间距textPath.moveTo(height / 3, baseline);textPath.lineTo(width - height / 3, baseline);//这里的意思是文字从哪里开始写,可以是居中,这里是右边textPaint.setTextAlign(Paint.Align.RIGHT);//这里是以路径绘制文字,scrollSize可以理解为文字在x轴上的便宜量,同时,我的混动效果就是通过改变scrollSize//刷新绘制来实现canvas.drawTextOnPath(buttonString, textPath, scrollSize, 0, textPaint);if (isShowLongText) {//这里是绘制遮挡物,因为绘制路径没有间距这方法,所以绘制遮挡物类似于间距方式canvas.drawRect(new Rect(width - height / 2 - textSize / 3, 0, width - height / 2, height),paintOval);canvas.drawRect(new Rect(height / 2, 0, height / 2 + textSize / 3, height), paintOval);//这里有个bug 有个小点-5  因画笔粗细产生canvas.drawArc(new RectF(width - height, 0, width - 5, height), -90, 180, true, paintOval);canvas.drawArc(new RectF(0, 0, height, height), 90, 180, true, paintOval);}if (animator_text_scroll == null) { //这里是计算混到最右边和最左边的距离范围animator_text_scroll = ValueAnimator.ofInt(buttonString.length() * textSize - width + height * 2 / 3,-textSize);//这里是动画的时间,scrollSpeed可以理解为每个文字滚动控件外所需的时间,可以做成控件属性提供出去 animator_text_scroll.setDuration(buttonString.length() * scrollSpeed);//设置动画的模式,这里是来回滚动animator_text_scroll.setRepeatMode(ValueAnimator.REVERSE);//设置插值器,让整个动画流畅animator_text_scroll.setInterpolator(new LinearInterpolator());//这里是滚动次数,-1无限滚动animator_text_scroll.setRepeatCount(-1);animator_text_scroll.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {//改变文字路径x轴的偏移量scrollSize = (int) animation.getAnimatedValue();postInvalidate();}});animator_text_scroll.start();}
} else {//这里是正常情况,isShowLongText,是我在启动控件动画的时候,是否启动 文字有渐变效果的标识,//如果是长文字,启动渐变效果的话,如果控件变小,文字内容在当前控件外,会显得很难看,所以根据这个标识,关闭,这里你可以先忽略(同时因为根据路径绘制text不能有间距效果,这个标识还是判断是否在控件2遍绘制遮挡物,这是作者的解决方式,如果你有更好的方式可以在下方留言)isShowLongText = false;/*** 简单的绘制文字,没有考虑文字长度超过控件长度* *///这里是居中显示textPaint.setTextAlign(Paint.Align.CENTER);//参数1:文字//参数2,3:绘制文字的中心点//参数4:画笔canvas.drawText(buttonString, textRect.centerX(), baseline, textPaint);
}

4、【自定义控件属性】

<?xml version="1.0" encoding="utf-8"?>
<resources><declare-styleable name="SmartLoadingView"><attr name="textStr" format="string" /><attr name="errorStr" format="string" /><attr name="cannotclickBg" format="color" /><attr name="errorBg" format="color" /><attr name="normalBg" format="color" /><attr name="cornerRaius" format="dimension" /><attr name="textColor" format="color" /><attr name="textSize" format="dimension" /><attr name="scrollSpeed" format="integer" /></declare-styleable>
</resources>

这里以,文案为例, textStr。比如你再布局种用到app:txtStr=“文案内容”。在自定义控件里获取如下:

public SmartLoadingView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);//自定义控件的3参方法的attrs就是我们设置自定义属性的关键//比如我们再attrs.xml里自定义了我们的属性,TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.SmartLoadingView);//这里是获取用户有没有设置整个属性//这里是从用户那里获取有没有设置文案String title = typedArray.getString(R.styleable.SmartLoadingView_textStr);if (TextUtils.isEmpty(title)){//如果获取来的属性是空,那么可以默认一个属性//(作者忘记设置了!因为已经发布后期优化,老尴尬了)buttonString ="默认文案";}else{//如果有设置文案buttonString = title;}}

5、【设置点击事件,启动动画】

为了点击事件的直观,也可以把处理防止重复点击事件封装在里面

//这是我自定义登录点击的接口
public interface LoginClickListener {void click();
}public void setLoginClickListener(final LoginClickListener loginClickListener) {this.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {if (loginClickListener != null) {//防止重复点击if (!isAnimRuning) {start();loginClickListener.click();}}}});
}

6、【动画讲解】

6.1、第一个动画,矩形到正方形,以及矩形到圆角矩形(这里是2个动画,只是同时进行)

矩形到正方形(为了简化,我把源码一些其他属性去掉了,这样方便理解)

//其中  default_all_distance = (w - h) / 2;除以2是因为2遍都往中间缩短
private void set_rect_to_circle_animation() {//这是一个属性动画,current_left 会在duration时间内,从0到default_all_distance匀速变化//想添加多样化的话  还可以加入插值器。animator_rect_to_square = ValueAnimator.ofInt(0, default_all_distance);animator_rect_to_square.setDuration(duration);animator_rect_to_square.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {//这里的current_left跟onDraw相关,还记得吗//onDraw里的控件区域 //控件左边区域 rectf.left = current_left;//控件右边区域 rectf.right = width - current_left;current_left = (int) animation.getAnimatedValue();//刷新绘制invalidate();}});

矩形到圆角矩形。就是从一个没有圆角的变成完全圆角的矩形,当然我展示的时候只有第三个图,最后一个按钮才明显了。

其他的我直接设置成了圆角按钮,因为我把圆角做成了一个属性。

还记得onDraw里的canvas.drawRoundRect(rectf, circleAngle, circleAngle, paint);circleAngle就是圆角的半径

可以想象一下如果全是圆角,那么circleAngle会是多少,当然是height/2;没错吧,所以

因为我把圆角做成了属性obtainCircleAngle是从xml文件获取的属性,如果不设置,则为0,就没有任何圆角效果

animator_rect_to_angle = ValueAnimator.ofInt(obtainCircleAngle, height / 2);
animator_rect_to_angle.setDuration(duration);
animator_rect_to_angle.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {//这里试想下如果是一个正方形,刚好是圆形的圆角,那就是一个圆circleAngle = (int) animation.getAnimatedValue();//刷新绘画invalidate();}
});

2个属性动画做好后,用 private AnimatorSet animatorSet = new AnimatorSet();把属性动画加进去,可以设置2个动画同时进行,还是先后顺序 这里是同时进行所用用with

animatorSet.play(animator_rect_to_square).with(animator_rect_to_angle);
6.2、变成圆形后,有一个loading加载动画

这里就是画圆弧,只是不断改变,圆弧的起始点和终点,最终呈现loading状态,也是在onDraw里

//绘制加载进度
if (isLoading) {//参数1:绘制圆弧区域//参数2,3:绘制圆弧起始点和终点canvas.drawArc(new RectF(width / 2 - height / 2 + height / 4, height / 4, width / 2 + height / 2 - height / 4, height / 2 + height / 2 - height / 4), startAngle, progAngle, false, okPaint);//这里是我通过实践,实现最佳loading动画//当然这里有很多方式,因为我自定义这个view想把所有东西都放在这个类里面,你也可以有你的方式//如果有更好的方式,欢迎留言,告知我一下startAngle += 6;if (progAngle >= 270) {progAngle -= 2;isAdd = false;} else if (progAngle <= 45) {progAngle += 6;isAdd = true;} else {if (isAdd) {progAngle += 6;} else {progAngle -= 2;}}//刷新绘制,这里不用担心有那么多刷新绘制,会不会影响性能//postInvalidate();
}
6.3、loading状态,到打勾动画

那么这里首先要把loading动画取消,那么直接改变isLoading=false;不会只它同时启动打勾动画;打勾动画的动画,这里比较麻烦,也是我在别人自定义动画里学习的,通过PathMeasure,实现路径动画

/*** 路径--用来获取对勾的路径*/
private Path path = new Path();
/*** 取路径的长度*/
private PathMeasure pathMeasure;
//初始化打勾动画路径;
private void initOk() {//对勾的路径path.moveTo(default_all_distance + height / 8 * 3, height / 2);path.lineTo(default_all_distance + height / 2, height / 5 * 3);path.lineTo(default_all_distance + height / 3 * 2, height / 5 * 2);pathMeasure = new PathMeasure(path, true);
}
//初始化打勾动画
private void set_draw_ok_animation() {animator_draw_ok = ValueAnimator.ofFloat(1, 0);animator_draw_ok.setDuration(duration);animator_draw_ok.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {startDrawOk = true;isLoading = false;float value = (Float) animation.getAnimatedValue();effect = new DashPathEffect(new float[]{pathMeasure.getLength(), pathMeasure.getLength()}, value * pathMeasure.getLength());okPaint.setPathEffect(effect);invalidate();}});
}//启动打勾动画只需要调用
animator_draw_ok.start();

onDraw里绘制打勾动画

//绘制打勾,这是onDraw的,startDrawOk是判断是否开启打勾动画的标识
if (startDrawOk) {canvas.drawPath(path, okPaint);
}
6.4、loading状态下回到失败样子(有点类似联网失败了)

之前6.1提到了矩形到圆角矩形和矩形到正方形的动画,

那么这里只是前面2个动画反过来,再加上联网失败的文案,和联网失败的背景图即刻

6.5、loading状态下启动扩散全屏动画(重点)

这里我通过loginSuccess里参数的类型启动不同效果:

1、启动扩散全屏动画
public void loginSuccess(Animator.AnimatorListener endListener) {}2、启动打勾动画
public void loginSuccess(AnimationOKListener animationOKListener) {}

启动扩散全屏是本文的重点,里面还涉及到了一个自定义view

CirclBigView,这个控件是全屏的,而且是从一个小圆不断改变半径变成大圆的动画,那么有人会问,全屏肯定不好啊,会影响布局,
但是这里,我把它放在了activity的视图层:
ViewGroup activityDecorView = (ViewGroup) ((Activity) getContext()).getWindow().getDecorView();
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
activityDecorView.addView(circlBigView, layoutParams);

这个灵感也是前不久在学习微信,拖拽退出的思路里发现的。全部代码如下:

public void toBigCircle(Animator.AnimatorListener endListener) {//把缩小到圆的半径,告诉circlBigViewcirclBigView.setRadius(this.getMeasuredHeight() / 2);//把当前背景颜色告诉circlBigViewcirclBigView.setColorBg(normal_color);int[] location = new int[2];//测量当前控件所在的屏幕坐标x,ythis.getLocationOnScreen(location);//把当前坐标告诉circlBigView,同时circlBigView会计算当前点,到屏幕4个点的最大距离,即是当前控件要扩散到的半径//具体建议读者看完本博客后,去下载玩耍下。circlBigView.setXY(location[0] + this.getMeasuredWidth() / 2, location[1]);if (circlBigView.getParent() == null) {ViewGroup activityDecorView = (ViewGroup) ((Activity) getContext()).getWindow().getDecorView();ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);activityDecorView.addView(circlBigView, layoutParams);}circlBigView.startShowAni(endListener);isAnimRuning = false;
}

结束语

因为项目是把之前的功能写成了控件,所以有很多地方不完善。希望有建议的大牛和小伙伴,提示提示我,让我完善的更好。谢谢

更多Android进阶指南 可以扫码 解锁 《Android十大板块文档》

1.Android车载应用开发系统学习指南(附项目实战)

2.Android Framework学习指南,助力成为系统级开发高手

3.2023最新Android中高级面试题汇总+解析,告别零offer

4.企业级Android音视频开发学习路线+项目实战(附源码)

5.Android Jetpack从入门到精通,构建高质量UI界面

6.Flutter技术解析与实战,跨平台首要之选

7.Kotlin从入门到实战,全方面提升架构基础

8.高级Android插件化与组件化(含实战教程和源码)

9.Android 性能优化实战+360°全方面性能调优

10.Android零基础入门到精通,高手进阶之路

敲代码不易,关注一下吧。ღ( ´・ᴗ・` ) 🤔

相关文章:

Android自定义控件:一款多特效的智能loadingView

先上效果图&#xff08;如果感兴趣请看后面讲解&#xff09;&#xff1a; 1、登录效果展示 2、关注效果展示 1、【画圆角矩形】 画图首先是onDraw方法&#xff08;我会把圆代码写上&#xff0c;一步一步剖析&#xff09;&#xff1a; 首先在view中定义个属性&#xff1a;priv…...

C语言之初阶指针

一、指针&#xff1a; 其实按照我的理解&#xff0c;当我们写c语言程序的时候&#xff0c;创建的变量&#xff0c;数组等都要在内存上开辟空间。而每一个内存都有一个唯一的编号&#xff0c;这个编号也被称为地址编号&#xff0c;就相当于&#xff0c;编号地址指针。 二、指针…...

MongoDB基础知识~

引入MongoDB&#xff1a; 在面对高并发&#xff0c;高效率存储和访问&#xff0c;高扩展性和高可用性等的需求下&#xff0c;我们之前所学习过的关系型数据库(MySql,sql server…)显得有点力不从心&#xff0c;而这些需求在我们的生活中也是随处可见的&#xff0c;例如在社交中…...

41. 缺失的第一个正数

给你一个未排序的整数数组 nums &#xff0c;请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,0] 输出&#xff1a;3示例 2&#xff1a; 输入&#xff1a;nums [3…...

数据结构—数组栈的实现

前言&#xff1a;各位小伙伴们我们前面已经学习了带头双向循环链表&#xff0c;数据结构中还有一些特殊的线性表&#xff0c;如栈和队列&#xff0c;那么我们今天就来实现数组栈。 目录&#xff1a; 一、 栈的概念 二、 栈的实现 三、 代码测试 栈的概念&#xff1a; 栈的概念…...

AI大模型低成本快速定制秘诀:RAG和向量数据库

文章目录 1. 前言2. RAG和向量数据库3. 论坛日程4. 购票方式 1. 前言 当今人工智能领域&#xff0c;最受关注的毋庸置疑是大模型。然而&#xff0c;高昂的训练成本、漫长的训练时间等都成为了制约大多数企业入局大模型的关键瓶颈。 这种背景下&#xff0c;向量数据库凭借其独特…...

Please No More Sigma(构造矩阵)

Please No More Sigma 给f(n)定义如下&#xff1a; f(n)1 n1,2; f(n)f(n-1)f(n-2) n>2; 给定n&#xff0c;求下式模1e97后的值 Input 第一行一个数字T&#xff0c;表示样例数 以下有T行&#xff0c;每行一个数&#xff0c;表示n。 保证T<100&#xff0c;n<100000…...

HTML设置标签栏的图标

添加此图标最简单的方法无需修改内容&#xff0c;只需按以下步骤操作即可&#xff1a; 1.准备一个 ico 格式的图标 2.将该图标命名为 favicon.ico 3.将图标文件置于index.html同级目录即可 为什么我的没有变化&#xff1f; 答曰&#xff1a;ShiftF5强制刷新一下网页就行了...

4.CentOS7安装MySQL5.7

CentOS7安装MySQL5.7 2023-11-13 小柴你能看到嘛 哔哩哔哩视频地址 https://www.bilibili.com/video/BV1jz4y1A7LS/?vd_source9ba3044ce322000939a31117d762b441 一.解压 tar -xvf mysql-5.7.26-linux-glibc2.12-x86_64.tar.gz1.在/usr/local解压 tar -xvf mysql-5.7.44-…...

【华为OD题库-014】告警抑制-Java

题目 告警抑制&#xff0c;是指高优先级告警抑制低优先级告警的规则。高优先级告警产生后&#xff0c;低优先级告警不再产生。请根据原始告警列表和告警抑制关系&#xff0c;给出实际产生的告警列表。不会出现循环抑制的情况。告警不会传递&#xff0c;比如A->B.B->C&…...

高频SQL50题(基础题)-5

文章目录 主要内容一.SQL练习题1.602-好友申请&#xff1a;谁有最多的好友代码如下&#xff08;示例&#xff09;: 2.585-2016年的投资代码如下&#xff08;示例&#xff09;: 3.185-部门工资前三高的所有员工代码如下&#xff08;示例&#xff09;: 4.1667-修复表中的名字代码…...

Spring IoC DI 使⽤

关于 IoC 的含义&#xff0c;推荐看IoC含义介绍&#xff08;Spring的核心思想&#xff09; 喜欢 Java 的推荐点一个免费的关注&#xff0c;主页有更多 Java 内容 前言 通过上述的博客我们知道了 IoC 的含义&#xff0c;既然 Spring 是⼀个 IoC&#xff08;控制反转&#xff09…...

Zigbee智能家居方案设计

背景 目前智能家居物联网中最流行的三种通信协议&#xff0c;Zigbee、WiFi以及BLE&#xff08;蓝牙&#xff09;。这三种协议各有各的优势和劣势。本方案基于CC2530芯片来设计&#xff0c;CC2530是TI的Zigbee芯片。 网关使用了ESP8266CC2530。 硬件实物 节点板子上带有继电器…...

机器视觉目标检测 - opencv 深度学习 计算机竞赛

文章目录 0 前言2 目标检测概念3 目标分类、定位、检测示例4 传统目标检测5 两类目标检测算法5.1 相关研究5.1.1 选择性搜索5.1.2 OverFeat 5.2 基于区域提名的方法5.2.1 R-CNN5.2.2 SPP-net5.2.3 Fast R-CNN 5.3 端到端的方法YOLOSSD 6 人体检测结果7 最后 0 前言 &#x1f5…...

无监督学习的集成方法:相似性矩阵的聚类

在机器学习中&#xff0c;术语Ensemble指的是并行组合多个模型&#xff0c;这个想法是利用群体的智慧&#xff0c;在给出的最终答案上形成更好的共识。 这种类型的方法已经在监督学习领域得到了广泛的研究和应用&#xff0c;特别是在分类问题上&#xff0c;像RandomForest这样…...

16. 机器学习——决策树

机器学习面试题汇总与解析——决策树 本章讲解知识点 什么是决策树决策树原理决策树优缺点决策树的剪枝决策树的改进型本专栏适合于Python已经入门的学生或人士,有一定的编程基础。 本专栏适合于算法工程师、机器学习、图像处理求职的学生或人士。 本专栏针对面试题答案进行了…...

DevOps系列---【jenkinsfile使用sshpass发送到另一台服务器】

1.首先在宿主机安装sshpass 2.把物理机的sshpass复制到容器中 which sshpass cp $(which sshpass) /usr/local/app/ docker cp sshpass 容器id:/usr/local/bin/sshpass 3.在jenkinsfile中添加 #在stages中添加stage stage(部署TEST服务){steps{sh "sshpass -p root1234 sc…...

Docker 和 Kubernetes:技术相同和不同之处

Docker和Kubernetes是当今最流行的容器化技术解决方案。本文将探讨Docker和Kubernetes的技术相似之处和不同之处&#xff0c;以帮助读者更好地理解这两种技术。 Docker和Kubernetes&#xff1a;当今最流行的容器化技术解决方案 在当今的IT领域&#xff0c;Docker和Kubernetes无…...

通信世界扫盲基础二(原理部分)

上次我们刚学习了关于通信4/G的组成和一些通识&#xff0c;今天我们来更深层次了解一些原理以及一些新的基础~ 目录 专业名词 LTE(4G系统) EPC s1 E-UTRAN UE UU X2 eNodeB NR(5G系统) NGC/5GC NG NG-RAN Xn gNodeB N26接口 手机的两种状态 空闲态 连接态 …...

手机厂商参与“百模大战”,vivo发布蓝心大模型

在2023 vivo开发者大会上&#xff0c;vivo发布自研通用大模型矩阵——蓝心大模型&#xff0c;其中包含十亿、百亿、千亿三个参数量级的5款自研大模型&#xff0c;其中&#xff0c;10亿量级模型是主要面向端侧场景打造的专业文本大模型&#xff0c;具备本地化的文本总结、摘要等…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

c++第七天 继承与派生2

这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分&#xff1a;派生类构造函数与析构函数 当创建一个派生类对象时&#xff0c;基类成员是如何初始化的&#xff1f; 1.当派生类对象创建的时候&#xff0c;基类成员的初始化顺序 …...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...