仿饿了么加入购物车旋转控件 - 自带闪转腾挪动画 的按钮
, mWidth - mCircleWidth, mHeight - mCircleWidth);
canvas.drawRoundRect(rectF, mHintBgRoundValue, mHintBgRoundValue, mHintPaint);
//前景文字
mHintPaint.setColor(mHintFgColor);
// 计算Baseline绘制的起点X轴坐标
int baseX = (int) (mWidth / 2 - mHintPaint.measureText(mHintText) / 2);
// 计算Baseline绘制的Y坐标
int baseY = (int) ((mHeight / 2) - ((mHintPaint.descent() + mHintPaint.ascent()) / 2));
canvas.drawText(mHintText, baseX, baseY, mHintPaint);
} else {
//左边
//背景 圆
if (mCount > 0) {
mDelPaint.setColor(mDelEnableBgColor);
} else {
mDelPaint.setColor(mDelDisableBgColor);
}
mDelPaint.setStrokeWidth(mCircleWidth);
mDelPath.reset();
mDelPath.addCircle(mLeft + mRadius, mTop + mRadius, mRadius, Path.Direction.CW);
mDelRegion.setPath(mDelPath, new Region(mLeft, mTop, mWidth - getPaddingRight(), mHeight - getPaddingBottom()));
canvas.drawPath(mDelPath, mDelPaint);
//前景 -
if (mCount > 0) {
mDelPaint.setColor(mDelEnableFgColor);
} else {
mDelPaint.setColor(mDelDisableFgColor);
}
mDelPaint.setStrokeWidth(mLineWidth);
canvas.drawLine(-mRadius / 2, 0,
+mRadius / 2, 0,
mDelPaint);
//数量
//是没有动画的普通写法,x left, y baseLine
canvas.drawText(mCount + “”, mLeft + mRadius * 2, mTop + mRadius - (mFontMetrics.top + mFontMetrics.bottom) / 2, mTextPaint);
//右边
//背景 圆
if (mCount < mMaxCount) {
mAddPaint.setColor(mAddEnableBgColor);
} else {
mAddPaint.setColor(mAddDisableBgColor);
}
mAddPaint.setStrokeWidth(mCircleWidth);
float left = mLeft + mRadius * 2 + mGapBetweenCircle;
mAddPath.reset();
mAddPath.addCircle(left + mRadius, mTop + mRadius, mRadius, Path.Direction.CW);
mAddRegion.setPath(mAddPath, new Region(mLeft, mTop, mWidth - getPaddingRight(), mHeight - getPaddingBottom()));
canvas.drawPath(mAddPath, mAddPaint);
//前景 +
if (mCount < mMaxCount) {
mAddPaint.setColor(mAddEnableFgColor);
} else {
mAddPaint.setColor(mAddDisableFgColor);
}
mAddPaint.setStrokeWidth(mLineWidth);
canvas.drawLine(left + mRadius / 2, mTop + mRadius, left + mRadius / 2 + mRadius, mTop + mRadius, mAddPaint);
canvas.drawLine(left + mRadius, mTop + mRadius / 2, left + mRadius, mTop + mRadius / 2 + mRadius, mAddPaint);
}
}
根据isHintMode
布尔值变量,区分是绘制第二层(Hint层)或者第一层(加减按钮层)。
绘制第二层时没啥好说的,就是利用canvas.drawRoundRect
,绘制圆角矩形,然后canvas.drawText
绘制hint。
(如果圆角的值足够大,矩形的宽度足够小,就变成了圆形。)
绘制第一层时,要根据当前的数量选择不同的颜色,注意在绘制加减按钮的圆圈时,我们是用Path
绘制的,这是因为我们还需要用Path
构建Region
类,这个类就是我们监听点击区域的重点。
点击事件的监听
在讲解动画之前,我们先说说如何监听点击的区域,因为本控件的动画是和加减数量息息相关的,而数量的加减是由点击相应”+ - 按钮”区域触发的。
所以我们的监听按钮的点击事件,其实就是监听相应的”+ - 按钮”区域。
上一节中,我们在绘制”+ - 按钮”区域时,通过Path
,构建了两个Region
类,Region
类有个contains(int x, int y)
方法如下,通过传入对应触摸的x、y坐标,就可知道知否点击了相应区域。
/**
- Return true if the region contains the specified point
*/
public native boolean contains(int x, int y);
知道了这一点,再写这部分代码就相当简单了:
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
//hint模式
if (isHintMode) {
onAddClick();
return true;
} else {
if (mAddRegion.contains((int) event.getX(), (int) event.getY())) {
onAddClick();
return true;
} else if (mDelRegion.contains((int) event.getX(), (int) event.getY())) {
onDelClick();
return true;
}
}
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
break;
}
return super.onTouchEvent(event);
}
hint模式时,我们可以认为控件所有范围都是“+”的有效区域。
而在非hint模式时,根据上一节构建的mAddRegion
和mDelRegion
去判断。
判断确认点击后,具体的操作,要根据业务的不同来编写了,设计到实际的购物车可能还有写数据库操作,或者请求接口等,要操作成功后才执行动画、或者修改count,这一块代码每个人写法可能不同。
使用时,可以重写onDelClick()
和onAddClick()
方法,并在合适的时机回调onCountAddSuccess()
和onCountDelSuccess()
以执行动画。
本文如下编写:
protected void onDelClick() {
if (mCount > 0) {
mCount–;
onCountDelSuccess();
}
}
protected void onAddClick() {
if (mCount < mMaxCount) {
mCount++;
onCountAddSuccess();
} else {
}
}
/**
- 数量增加成功后,使用者回调
*/
public void onCountAddSuccess() {
if (mCount == 1) {
cancelAllAnim();
mAnimReduceHint.start();
} else {
mAnimFraction = 0;
invalidate();
}
}
/**
- 数量减少成功后,使用者回调
*/
public void onCountDelSuccess() {
if (mCount == 0) {
cancelAllAnim();
mAniDel.start();
} else {
mAnimFraction = 0;
invalidate();
}
}
动画的实现
这里会用到两个变量:
//动画的基准值 动画:减 0~1, 加 1~0
// 普通状态下是0
protected float mAnimFraction;
//提示语收缩动画 0-1 展开1-0
//普通模式时,应该是1, 只在 isHintMode true 才有效
protected float mAnimExpandHintFraction;
依次分析有哪些动画:
Hint动画
主要是圆角矩形的展开、收缩。
固定right、bottom,当展开时,不断减少矩形的左起点left坐标值,则整个矩形宽度变大,呈现展开。收缩时相反。
代码:
//背景
mHintPaint.setColor(mHintBgColor);
RectF rectF = new RectF(mLeft + (mWidth - mRadius * 2) * mAnimExpandHintFraction, mTop
, mWidth - mCircleWidth, mHeight - mCircleWidth);
canvas.drawRoundRect(rectF, mHintBgRoundValue, mHintBgRoundValue, mHintPaint);
减按钮动画
看起来是旋转、位移、透明度。
那么对于背景的圆圈来说,我们只需要位移、透明度。因为它本身是个圆,就不要旋转了。
代码:
//动画 mAnimFraction :减 0~1, 加 1~0 ,
//动画位移Max,
float animOffsetMax = (mRadius * 2 +mGapBetweenCircle);
//透明度动画的基准
int animAlphaMax = 255;
int animRotateMax = 360;
//左边
//背景 圆
mDelPaint.setAlpha((int) (animAlphaMax * (1 - mAnimFraction)));
mDelPath.reset();
//改变圆心的X坐标,实现位移
mDelPath.addCircle(animOffsetMax * mAnimFraction + mLe
ft + mRadius, mTop + mRadius, mRadius, Path.Direction.CW);
canvas.drawPath(mDelPath, mDelPaint);
对于前景的“-”号来说,旋转、位移、透明度都需要做。
这里我们利用canvas.translate()
canvas.rotate
做旋转和位移动画,别忘了 canvas.save()
和 canvas.restore()
恢复画布的状态。(透明度在上面已经设置过了。)
//前景 -
//旋转动画
canvas.save();
canvas.translate(animOffsetMax * mAnimFraction + mLeft + mRadius, mTop + mRadius);
canvas.rotate((int) (animRotateMax * (1 - mAnimFraction)));
canvas.drawLine(-mRadius / 2, 0,
+mRadius / 2, 0,
mDelPaint);
canvas.restore();
数量的动画
看起来也是旋转、位移、透明度。同样是利用canvas.translate()
canvas.rotate
做旋转和位移动画。
//数量
canvas.save();
//平移动画
canvas.translate(mAnimFraction * (mGapBetweenCircle / 2 - mTextPaint.measureText(mCount + “”) / 2 + mRadius), 0);
//旋转动画,旋转中心点,x 是绘图中心,y 是控件中心
canvas.rotate(360 * mAnimFraction,
mGapBetweenCircle / 2 + mLeft + mRadius * 2 ,
mTop + mRadius);
//透明度动画
mTextPaint.setAlpha((int) (255 * (1 - mAnimFraction)));
//是没有动画的普通写法,x left, y baseLine
canvas.drawText(mCount + “”, mGapBetweenCircle / 2 - mTextPaint.measureText(mCount + “”) / 2 + mLeft + mRadius * 2, mTop + mRadius - (mFontMetrics.top + mFontMetrics.bottom) / 2, mTextPaint);
canvas.restore();
动画的定义:
动画是在View初始化时就定义好的,执行顺序:
-
数量增加,0-1时,先收缩Hint(第二层)
mAnimReduceHint
执行,完毕后执行减按钮(第一层)进入的动画mAnimAdd
。 -
数量减少,1-0时,先执行减按钮退出的动画
mAniDel
,再伸展Hint动画mAnimExpandHint
,完毕后,显示hint文字。
代码如下:
//动画 +
mAnimAdd = ValueAnimator.ofFloat(1, 0);
mAnimAdd.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mAnimFraction = (float) animation.getAnimatedValue();
invalidate();
}
});
mAnimAdd.setDuration(350);
//提示语收缩动画 0-1
mAnimReduceHint = ValueAnimator.ofFloat(0, 1);
mAnimReduceHint.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mAnimExpandHintFraction = (float) animation.getAnimatedValue();
invalidate();
}
});
mAnimReduceHint.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (mCount == 1) {
//然后底色也不显示了
isHintMode = false;
}
if (mCount == 1) {
Log.d(TAG, “现在还是1 开始收缩动画”);
if (mAnimAdd != null && !mAnimAdd.isRunning()) {
mAnimAdd.start();
}
}
}
@Override
public void onAnimationStart(Animator animation) {
if (mCount == 1) {
//先不显示文字了
isShowHintText = false;
}
}
});
mAnimReduceHint.setDuration(350);
//动画 -
mAniDel = ValueAnimator.ofFloat(0, 1);
mAniDel.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mAnimFraction = (float) animation.getAnimatedValue();
invalidate();
}
});
//1-0的动画
mAniDel.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (mCount == 0) {
Log.d(TAG, “现在还是0onAnimationEnd() called with: animation = [” + animation + “]”);
if (mAnimExpandHint != null && !mAnimExpandHint.isRunning()) {
mAnimExpandHint.start();
}
}
}
});
mAniDel.setDuration(350);
//提示语展开动画
//分析这个动画,最初是个圆。 就是left 不断减小
mAnimExpandHint = ValueAnimator.ofFloat(1, 0);
mAnimExpandHint.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mAnimExpandHintFraction = (float) animation.getAnimatedValue();
invalidate();
}
});
mAnimExpandHint.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (mCount == 0) {
isShowHintText = true;
}
}
@Override
public void onAnimationStart(Animator animation) {
if (mCount == 0) {
isHintMode = true;
}
}
});
mAnimExpandHint.setDuration(350);
针对复用机制的处理
因为我们的购物车控件肯定会用在列表中,不管你用ListView
还是RecyclerView
,都会涉及到复用的问题。
复用给我们带来一个麻烦的地方就是,我们要处理好一些属性状态值,否则UI上会有问题。
可以从两处下手处理:
onMeasure
列表复用时,依然会回调onMeasure()
方法,所以在这里初始化一些UI显示的参数。
这里顺带将适配wrap_content 的代码也一同贴上:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int wMode = MeasureSpec.getMode(widthMeasureSpec);
int wSize = MeasureSpec.getSize(widthMeasureSpec);
int hMode = MeasureSpec.getMode(heightMeasureSpec);
int hSize = MeasureSpec.getSize(heightMeasureSpec);
switch (wMode) {
case MeasureSpec.EXACTLY:
break;
case MeasureSpec.AT_MOST:
//不超过父控件给的范围内,自由发挥
int computeSize = (int) (getPaddingLeft() + mRadius * 2 +mGapBetweenCircle + mRadius * 2 + getPaddingRight() + mCircleWidth * 2);
wSize = computeSize < wSize ? computeSize : wSize;
break;
case MeasureSpec.UNSPECIFIED:
//自由发挥
computeSize = (int) (getPaddingLeft() + mRadius * 2 + mGapBetweenCircle + mRadius * 2 + getPaddingRight() + mCircleWidth * 2);
wSize = computeSize;
break;
}
switch (hMode) {
case MeasureSpec.EXACTLY:
break;
case MeasureSpec.AT_MOST:
int computeSize = (int) (getPaddingTop() + mRadius * 2 + getPaddingBottom() + mCircleWidth * 2);
hSize = computeSize < hSize ? computeSize : hSize;
break;
case MeasureSpec.UNSPECIFIED:
computeSize = (int) (getPaddingTop() + mRadius * 2 + getPaddingBottom() + mCircleWidth * 2);
hSize = computeSize;
break;
}
setMeasuredDimension(wSize, hSize);
//复用时会走这里,所以初始化一些UI显示的参数
mAnimFraction = 0;
initHintSettings();
}
/**
- 根据当前count数量 初始化 hint提示语相关变量
*/
private void initHintSettings() {
if (mCount == 0) {
isHintMode = true;
isShowHintText = true;
mAnimExpandHintFraction = 0;
} else {
isHintMode = false;
isShowHintText = false;
mAnimExpandHintFraction = 1;
}
}
在改变count时
一般在onBindViewHolder()
或者getView()
时,都会对本控件重新设置count值,count改变时,当然也是需要根据count进行属性值的调整。
且此时如果View正在做动画,应该停止这些动画。
/**
-
设置当前数量
-
@param count
-
@return
*/
public AnimShopButton setCount(int count) {
mCount = count;
//先暂停所有动画
if (mAnimAdd != null && mAnimAdd.isRunning()) {
mAnimAdd.cancel();
}
if (mAniDel != null && mAniDel.isRunning()) {
mAniDel.cancel();
}
//复用机制的处理
if (mCount == 0) {
// 0 不显示 数字和-号
mAnimFraction = 1;
} else {
mAnimFraction = 0;
}
initHintSettings();
return this;
}
总结
–
代码传送门:喜欢的话,随手点个star。多谢
https://github.com/mcxtzhang/AnimShopButton
想经济上支持我 or 想通过视频看我是怎么实现的:
http://edu.csdn.net/course/detail/3898
我在实现这个控件时,觉得难度相对大的地方在于做动画时,“-”按钮和数量的旋转动画,如何确定正确的坐标值。因为将text绘制的居中本身就有一些注意事项在里面,再涉及到动画,难免蒙圈。需要多计算,多试验。
还有就是观察饿了么的效果,将hint区域的动画利用改变RoundRect的宽度去实现。起初没有想到,也是思考了一会如何去做。这是属于分析、拆解动画遇到的问题。
除了绘制以外的重点是:
-
利用
Region
监听区域点击事件。 -
复用的列表,如何正确显示UI。
-
动画次序以及考虑到复用时,在合适的地方取消动画。
最后
小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
资料⬅专栏获取
imFraction = 0;
}
initHintSettings();
return this;
}
总结
–
代码传送门:喜欢的话,随手点个star。多谢
https://github.com/mcxtzhang/AnimShopButton
想经济上支持我 or 想通过视频看我是怎么实现的:
http://edu.csdn.net/course/detail/3898
我在实现这个控件时,觉得难度相对大的地方在于做动画时,“-”按钮和数量的旋转动画,如何确定正确的坐标值。因为将text绘制的居中本身就有一些注意事项在里面,再涉及到动画,难免蒙圈。需要多计算,多试验。
还有就是观察饿了么的效果,将hint区域的动画利用改变RoundRect的宽度去实现。起初没有想到,也是思考了一会如何去做。这是属于分析、拆解动画遇到的问题。
除了绘制以外的重点是:
-
利用
Region
监听区域点击事件。 -
复用的列表,如何正确显示UI。
-
动画次序以及考虑到复用时,在合适的地方取消动画。
最后
小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
[外链图片转存中…(img-RbTcTwdo-1719097483595)]一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
资料⬅专栏获取
相关文章:
仿饿了么加入购物车旋转控件 - 自带闪转腾挪动画 的按钮
, mWidth - mCircleWidth, mHeight - mCircleWidth); canvas.drawRoundRect(rectF, mHintBgRoundValue, mHintBgRoundValue, mHintPaint); //前景文字 mHintPaint.setColor(mHintFgColor); // 计算Baseline绘制的起点X轴坐标 int baseX (int) (mWidth / 2 - mHintPaint.m…...
Docker部署nacos集群
docker拉取nacos镜像,本文使用nacos2.0.3 三台服务器都要执行以下命令 docker pull nacos/nacos-server:v2.2.0准备挂载的日志目录和配置文件目录 日志:mkdir /usr/local/software/nacos/logs 配置文件:/usr/local/software/nacos/conf在配…...
centos查找文件 及 操作写入的进程
du -sh * 查看目录空间占用、发现大文件,确定进程,结束 yum install lsof 安装lsof 查看文件写入的 进程 2. lsof /root/.influxdbv2/engine/data/bab49411e5f7cbce/autogen/1/000000036-000000002.tsm COMMAND PID USER FD TYPE …...
构建高可用Java微服务架构的秘籍
构建高可用Java微服务架构的秘籍 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 随着云计算和分布式系统的快速发展,微服务架构已成为构建大型应用…...
VBA学习(18):VBA制作任意工作表均可使用的聚光灯
在需要制作聚光的工作簿,按<ALTF11>组合键,打开VBE编辑器。在右侧[工程资源管理器窗格]选中ThisWorkbook模块,将以下代码复制粘贴到该模块的代码窗口。 Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target …...
【STM32-启动文件 startup_stm32f103xe.s】
STM32-启动文件 startup_stm32f103xe.s ■ STM32-启动文件■ STM32-启动文件主要做了以下工作:■ STM32-启动文件指令■ STM32-启动文件代码详解■ 栈空间的开辟■ 栈空间大小 Stack_Size■ .map 文件的详细介绍■ 打开map文件 ■ 堆空间■ PRESERVE8 和 THUMB 指令…...
51学习记录(一)——51介绍及震动感应灯
文章目录 前言一、STC89C522.内部结构及引脚 二、继电器原理及震动传感器原理三、项目搭建及实现 前言 一个学习嵌入式的小白~ 有问题评论区或私信指出 提示:以下是本篇文章正文内容,下面案例可供参考 一、STC89C52 1.简介 所属系列:51单…...
2024GLEE生活暨教育(上海)博览会,8月20-22日,国家会展中心(上海)
2024GLEE生活暨教育(上海)博览会将于8月20-22日在中国国家会展中心(上海)举行,博览会总面积近万平方米,设有美好生活和教育产品两大主力展区,全面覆盖婴幼儿、学龄前、小学、初中、高中、大学、中年、老年各个年龄段的…...
debug调试高级功能 断点、布局 及Android Studio常用快捷按键使用详情
文章目录 debug断点篇:打临时断点(只用一次):alt断点条件断点:在断点上,点击右键,在Condition那里,设置我们需要的值,循环就会自动停到我们设置的那个值那里依赖断点&…...
51单片机STC89C52RC——6.1 中断系统
一,文字层面理解 反正我看下面的几段文字时脑壳没有正常运转。一个头几个大 中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的。 当中央处理机CPU正在处理某件事的时候外界发生了紧急事件请求,要求CPU暂停当前的工作,转而去处理这…...
Redis源码学习:高性能Hash表的设计与实现
哈希表(Hash)是Redis数据库的数据类型之一,理解哈希表的实现对于掌握Redis非常重要。这篇文章,从哈希冲突和哈希扩展这两个角度,来一步步讲解Redis哈希表的工作原理。 什么是哈希表? 哈希表是一种通过哈希…...
如何防范常见的数据库安全问题
随着数据量的增加和系统的复杂性提高,数据库可能面临多种安全威胁,包括未授权访问、数据泄露、注入攻击等。 1. 未授权访问 未授权访问是指,未经授权的用户对数据库的内容进行访问。这会导致数据泄露、数据篡改或其他安全事故。 针对未授权访问的防范措施如下。 (1)强化…...
[Day 19] 區塊鏈與人工智能的聯動應用:理論、技術與實踐
區塊鏈的數據透明性 區塊鏈技術作為一種分布式賬本技術,因其去中心化、不可篡改和高度透明的特性,已經在各行各業中得到了廣泛應用。在本文中,我們將深入探討區塊鏈的數據透明性,包括其原理、實現方法及相關代碼示例,…...
【Hadoop学习笔记】认识Hadoop
认识Hadoop 从网上找的课程做的笔记,有些图是自己理解画的,可能不正确,可以作为参考,有疑问的地方请直接指出,共同交流。 Hadoop是由Apache基金会开发的一个分布式系统基础架构,主要解决海量数据的存储和海…...
CISP-PTE综合靶机-WinServer2003
1.收集网站的地址和开放的端口,完成前期信息收集。10分 2.访问站点,找出站点的敏感文件,利用返回数据找到相关敏感信 息,完成网站结构的信息收集。10分 3.利用文件包含漏洞读取敏感文件,找出数据库连接凭证,利用此 凭证连接数据库。10分 4.网站后台提权:找出后台管理员登…...
sklearn之各类朴素贝叶斯原理
sklearn之贝叶斯原理 前言1 高斯朴素贝叶斯1.1 对连续变量的处理1.2 高斯朴素贝叶斯算法原理 2 多项式朴素贝叶斯2.1 二项分布和多项分布2.2 详细原理2.3 如何判断是否符合多项式贝叶斯 3 伯努利朴素贝叶斯4 类别贝叶斯4 补充朴素贝叶斯4.1 核心原理4.2 算法流程 前言 如果想看…...
年薪50w+的项目经理,手把手教你如何复盘
复盘是一种重要的学习和改进工具,对于项目经理来说,能帮助识别项目中的成功与失败,为未来的项目管理提供宝贵经验。 理论部分 定义目标。在开始复盘之前,明确复盘的目标是什么。是为了找出项目中的问题并提出解决方案,…...
Web3新视野:Lumoz节点的潜力与收益解读
摘要:低估值、高回报、无条件退款80%...... Lumoz正通过其 zkVerifier 节点销售活动,引领一场ZK计算革命。 长期以来,加密市场以其独特的波动性和增长潜力,持续吸引着全球投资者的目光。而历史数据表明,市场往往在一年…...
【shell脚本速成】mysql备份脚本
文章目录 案例需求脚本应用场景:解决问题脚本思路实现代码 🌈你好呀!我是 山顶风景独好 🎈欢迎踏入我的博客世界,能与您在此邂逅,真是缘分使然!😊 🌸愿您在此停留的每一刻…...
高考志愿填报,理科生如何分析选专业?
理科生选择专业的范围更大一些,相比文科说理工科的院校也更多,如何选择适合自己的专业,这是一个比较重要的课题,毕竟大学专业直接关系到职业,是一辈子的大事。 那么理科究竟如何选择专业呢?需要从什么地方…...
qt 简单实验 json格式的文件写入配置文件
1.概要 2.代码 //#include "mainwindow.h"#include <QApplication> #include <QFile> #include <QJsonDocument> #include <QJsonObject> //读取json数据的配置文件int main(int argc, char *argv[]) {QApplication a(argc, argv);QString…...
将WIN10的wifi上网分享给以太网接口
目录 打开网络设置设置属性点这里的设置将wlan主机的以太网接口IP设为自动获取 如果连接不成功,拔网线重连一次 打开网络设置 设置属性 点这里的设置 将wlan主机的以太网接口IP设为自动获取 如果连接不成功,拔网线重连一次...
在 iPhone 上恢复已删除联系人的 5 种简便方法
想象一下:您正在 iPhone 上滚动并搜索要拨打的联系人,但却找不到任何结果。然后您想起昨晚您试图删除一个名字相似的联系人,但不知何故删除了错误的联系人。或者您的孩子错误地删除了一些联系人。这些情况足以让您感到迷茫。但别担心…...
小白指南:前端使用javascript如何判断集合是不是空集合?
背景 最近在开发一个Web应用时,我遇到了一个关于集合处理的问题。具体来说,我需要判断一个集合是否为空。集合可以是数组、对象、Map或Set等不同的数据结构。就简单的整理了一下如何在JavaScript中有效地判断一个集合是否为空呢? 解决方案 …...
人力资源招聘社会校企类型招聘系统校园招聘小程序
校企社会人力资源招聘小程序:开启高效招聘新时代 🚀开篇:打破传统,开启招聘新篇章 在快速发展的现代社会,人力资源招聘已经成为企业和学校共同关注的重要议题。为了更高效、便捷地满足双方的招聘需求,一款…...
docker重要操作与直连方法
文章目录 前言一、nvidia-docker安装方法1、nvidia-docker安装2、重启动ssh 二、构建镜像1、构建镜像docker拉取构建本地镜像加载构建 2、容器转镜像3、镜像打包4、删除镜像 三、构建容器1、容器构建2、启动镜像3、删除容器 四、docker直连(ssh -p)1、docker更改密码2、物理机操…...
Windows环境利用 OpenCV 中 CascadeClassifier 分类器识别人眼 c++
Windows环境中配置OpenCV 关于在Windows环境中配置opencv的说明,具体可以参考:VS2022 配置OpenCV开发环境详细教程。 CascadeClassifier 分类器 CascadeClassifier 是 OpenCV 库中的一个类,它用于实现一种快速的物体检测算法,称…...
Golang | Leetcode Golang题解之第167题两数之和II-输入有序数组
题目: 题解: func twoSum(numbers []int, target int) []int {low, high : 0, len(numbers) - 1for low < high {sum : numbers[low] numbers[high]if sum target {return []int{low 1, high 1}} else if sum < target {low} else {high--}}r…...
【软件工程】【23.04】p2
关键字: 计算机软件定义、需求基本性质、创建系统类图所涉及的工作、RUP创建系统用况模型活动、软件生存周期模型、能力等级和成熟度等级区别联系; 模块结构图:深度宽度、扇入扇出、作用域、控制域; 程序流程图:语句…...
Java多线程编程与并发控制策略
Java多线程编程与并发控制策略 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天,我想和大家分享一下Java多线程编程与并发控制策略的相关知识&am…...
帮人做彩票网站有事吗/东莞做网站的公司吗
图书简介本教材配有以下教学资源:课件;例题和习题的源代码;授课视频,请登陆“学堂在线”网址:https://next.xuetangx.com/learn/HBPU08091001488/HBPU08091001488/1511853/video/1309556根据TIOBE 编程语言排行榜&…...
阳曲网站建设推荐咨询/风云榜
原文链接:http://blog.csdn.net/only_wan/article/details/52975760 mvn 创建时在generating project in interactive mode卡住了,怎么解决? 从图中可以看出,为啥卡在generating project in interactive mode, 因为请求…...
备份wordpress数据库/百度首页纯净版
函数形参默认值: 从第一个参数给定默认值的位置开始往右必须要有默认值 int swap(int a,int b10)//可以,有默认值的在右边 int swap(int a10;,int b)//不可以有默认参数的位置可以调用时可以不写参数 int swap(int a,int b10)int main(){swap(10);ret…...
百度推广一年收费标准/江西seo推广方案
“经济是技术的表达”,当一个新技术出现,往往会对现有经济带来冲击和重构。而区块链则更加特别,它催生了一个新的资产类别。该如何理解区块链及其带来的新资产类别?万向区块链董事长兼总经理肖风博士,在第九届银华基金…...
如何做网站301重定向/北京百度竞价托管
链接:https://www.nowcoder.com/acm/contest/133/B 来源:牛客网 题目描述 Applese有1个容量为v的背包,有n个物品,每一个物品有一个价值ai,以及一个大小bi 然后他对此提出了自己的疑问,如果我不要装的物…...
网站建设项目规划书案例/seo搜索引擎优化是什么
就像你可能不知道 现充 其实是 现实生活很充实的人生赢家 的缩写一样,我们经常看到 Github 上的码农们在 code review 时,把乱七八糟的缩写写得到处都是——娴熟的司机们都会使用缩写来达到提高逼格的效果——我们第一次看到时还是会出现一脸懵逼的状况&…...