android——自定义控件(不停变化的textview、开关switch、动画效果的打勾)

一、从开始数字到结束数字,不断变化

import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.animation.AccelerateDecelerateInterpolator;import androidx.appcompat.widget.AppCompatTextView;import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;/*** FileName: NumberAnimTextView* Date: 2020/12/14* Description: TextView动画,从开始到结束,数字不断变化* History:* <author> <time> <version> <desc>*/public class NumberAnimTextView extends AppCompatTextView {private String mNumStart = "0";  //private String mNumEnd; //private long mDuration = 1000;          // 动画持续时间 ms,默认1sprivate String mPrefixString = "";      // 前缀private String mPostfixString = "";     // 后缀public NumberAnimTextView(Context context) {super(context);}public NumberAnimTextView(Context context, AttributeSet attrs) {super(context, attrs);}public NumberAnimTextView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}public void setNumberString(String number) {setNumberString("0", number);}public void setNumberString(String numberStart, String numberEnd) {mNumStart = numberStart;mNumEnd = numberEnd;start();
//        if (checkNumString(numberStart, numberEnd)) {
//            // 数字合法 开始数字动画
//            start();
//        } else {
//            // 数字不合法 直接调用 setText 设置最终值
//            setText(mPrefixString + numberEnd + mPostfixString);
//        }}public void setDuration(long mDuration) {this.mDuration = mDuration;}public void setPrefixString(String mPrefixString) {this.mPrefixString = mPrefixString;}public void setPostfixString(String mPostfixString) {this.mPostfixString = mPostfixString;}private boolean isInt; // 是否是整数/*** 校验数字的合法性** @param numberStart  开始的数字* @param numberEnd    结束的数字* @return 合法性*/private boolean checkNumString(String numberStart, String numberEnd) {try {new BigInteger(numberStart);new BigInteger(numberEnd);isInt = true;} catch (Exception e) {isInt = false;e.printStackTrace();}try {BigDecimal start = new BigDecimal(numberStart);BigDecimal end = new BigDecimal(numberEnd);return end.compareTo(start) >= 0;} catch (Exception e) {e.printStackTrace();return false;}}private void start() {ValueAnimator animator = ValueAnimator.ofObject(new BigDecimalEvaluator(), new BigDecimal(mNumStart), new BigDecimal(mNumEnd));animator.setDuration(mDuration);animator.setInterpolator(new AccelerateDecelerateInterpolator());animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {BigDecimal value = (BigDecimal) valueAnimator.getAnimatedValue();setText(mPrefixString + format(value) + mPostfixString);}});animator.start();}/*** 格式化 BigDecimal ,小数部分时保留两位小数并四舍五入** @param bd  BigDecimal* @return 格式化后的 String*/private String format(BigDecimal bd) {String pattern;if (isInt) {pattern = "#,###";} else {pattern = "#,##0.00";}DecimalFormat df = new DecimalFormat(pattern);return df.format(bd);}class BigDecimalEvaluator implements TypeEvaluator {@Overridepublic Object evaluate(float fraction, Object startValue, Object endValue) {BigDecimal start = (BigDecimal) startValue;BigDecimal end = (BigDecimal) endValue;BigDecimal result = end.subtract(start);return result.multiply(new BigDecimal("" + fraction)).add(start);}}
}

设置开始数字和结束数字即可:setNumberString("12345", "1234567")

二、自定义开关switch

import android.animation.Animator;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;import androidx.annotation.Nullable;import com.fslihua.my_application_1.R;/*** 自定义开关Switch*/
public class CustomSwitch extends View implements ValueAnimator.AnimatorUpdateListener, ValueAnimator.AnimatorListener{private final String TAG = CustomSwitch.class.getSimpleName();//默认的宽高比例private static final float DEFAULT_WIDTH_HEIGHT_PERCENT = 0.45f;//动画最大的比例private static final float ANIMATION_MAX_FRACTION = 1;private int mWidth,mHeight;//画跑道型背景private Paint mBackgroundPain;//画背景上的字private Paint mDisaboleTextPaint;//开启private Paint mEnableTextPaint;//关闭//画白色圆点private Paint mSlidePaint;//是否正在动画private boolean isAnimation;private ValueAnimator mValueAnimator;private float mAnimationFraction;private String openText;private String closeText;private int mOpenColor = Color.GREEN;private int mCloseColor = Color.GRAY;private int mCurrentColor = Color.GRAY;//监听private OnCheckedChangeListener mCheckedChangeListener;private boolean isChecked;public CustomSwitch(Context context) {super(context);init();}public CustomSwitch(Context context, @Nullable AttributeSet attrs) {super(context, attrs);TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomSwitch);openText = typedArray.getString(R.styleable.CustomSwitch_openText);closeText = typedArray.getString(R.styleable.CustomSwitch_closeText);mOpenColor = typedArray.getColor(R.styleable.CustomSwitch_openColor, Color.GREEN);mCloseColor = typedArray.getColor(R.styleable.CustomSwitch_closeColor, Color.GRAY);mCurrentColor = mCloseColor;
//        mWidth = typedArray.getInteger(R.styleable.CustomSwitch_customWidth,1);
//        mHeight = typedArray.getInteger(R.styleable.CustomSwitch_customHeight,1);typedArray.recycle();init();}public CustomSwitch(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomSwitch);openText = typedArray.getString(R.styleable.CustomSwitch_openText);closeText = typedArray.getString(R.styleable.CustomSwitch_closeText);mOpenColor = typedArray.getColor(R.styleable.CustomSwitch_openColor, Color.GREEN);mCloseColor = typedArray.getColor(R.styleable.CustomSwitch_closeColor, Color.GRAY);mCurrentColor = mCloseColor;
//        mWidth = typedArray.getInteger(R.styleable.CustomSwitch_customWidth,1);
//        mHeight = typedArray.getInteger(R.styleable.CustomSwitch_customHeight,1);typedArray.recycle();init();}private void init(){Log.e(TAG,"init()被调用");mBackgroundPain = new Paint();mBackgroundPain.setAntiAlias(true);mBackgroundPain.setDither(true);mBackgroundPain.setColor(Color.GRAY);
//        开启的文字样式mDisaboleTextPaint = new Paint();mDisaboleTextPaint.setAntiAlias(true);mDisaboleTextPaint.setDither(true);mDisaboleTextPaint.setStyle(Paint.Style.STROKE);mDisaboleTextPaint.setColor(Color.WHITE);mDisaboleTextPaint.setTextAlign(Paint.Align.CENTER);
//        关闭的文字样式mEnableTextPaint = new Paint();mEnableTextPaint.setAntiAlias(true);mEnableTextPaint.setDither(true);mEnableTextPaint.setStyle(Paint.Style.STROKE);mEnableTextPaint.setColor(Color.parseColor("#7A88A0"));mEnableTextPaint.setTextAlign(Paint.Align.CENTER);mSlidePaint = new Paint();mSlidePaint.setColor(Color.WHITE);mSlidePaint.setAntiAlias(true);mSlidePaint.setDither(true);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int width =  MeasureSpec.getSize(widthMeasureSpec);int height = (int) (width*DEFAULT_WIDTH_HEIGHT_PERCENT);setMeasuredDimension(width,height);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mWidth = w;mHeight = h;}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);drawBackground(canvas);drawSlide(canvas);}private void drawSlide(Canvas canvas){float distance = mWidth - mHeight;
//        Log.e(TAG,"distance = " + distance);
//        Log.e(TAG,"mAnimationFraction = " + mAnimationFraction);
//        canvas.drawCircle(mHeight/2+distance*mAnimationFraction,mHeight/2,mHeight/3,mSlidePaint);canvas.drawCircle(mHeight/2+distance*mAnimationFraction,mHeight/2, mHeight/2.5f,mSlidePaint);
//        canvas.drawCircle(mHeight/2+distance*mAnimationFraction, (float) (mHeight/2.2), (float) (mHeight/2.2),mSlidePaint);}private void drawBackground(Canvas canvas){Path path = new Path();RectF rectF = new RectF(0,0,mHeight,mHeight);path.arcTo(rectF,90,180);rectF.left = mWidth-mHeight;rectF.right = mWidth;path.arcTo(rectF,270,180);path.close();mBackgroundPain.setColor(mCurrentColor);canvas.drawPath(path,mBackgroundPain);//        mDisaboleTextPaint.setTextSize(mHeight/2);mDisaboleTextPaint.setTextSize(mHeight/2.2f);
//        mEnableTextPaint.setTextSize(mHeight/2);mEnableTextPaint.setTextSize(mHeight/2.2f);Paint.FontMetrics fontMetrics = mDisaboleTextPaint.getFontMetrics();float top = fontMetrics.top;float bottom = fontMetrics.bottom;
//        基线位置int baseLine = (int) (mHeight/2 + (bottom-top)*0.3);if (!TextUtils.isEmpty(openText)){//启用mDisaboleTextPaint.setAlpha((int) (255*mAnimationFraction));canvas.drawText(openText,mWidth*0.3f,baseLine,mDisaboleTextPaint);}if (!TextUtils.isEmpty(closeText)){//启用mEnableTextPaint.setAlpha((int) (255*(1-mAnimationFraction)));canvas.drawText(closeText,mWidth*0.7f,baseLine,mEnableTextPaint); //第二个值改变x轴的位置}}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()){case MotionEvent.ACTION_DOWN:return true;case MotionEvent.ACTION_CANCEL:break;case MotionEvent.ACTION_UP:if (isAnimation){return true;}if (isChecked){startCloseAnimation();isChecked = false;if (mCheckedChangeListener!=null){mCheckedChangeListener.onCheckedChanged(false);}}else {startOpeAnimation();isChecked = true;if (mCheckedChangeListener!=null){mCheckedChangeListener.onCheckedChanged(true);}}return true;}return super.onTouchEvent(event);}private void startOpeAnimation(){mValueAnimator = ValueAnimator.ofFloat(0.0f, ANIMATION_MAX_FRACTION);mValueAnimator.setDuration(500);mValueAnimator.addUpdateListener(this);mValueAnimator.addListener(this);mValueAnimator.start();startColorAnimation();}private void startCloseAnimation(){mValueAnimator = ValueAnimator.ofFloat(ANIMATION_MAX_FRACTION, 0.0f);mValueAnimator.setDuration(500);mValueAnimator.addUpdateListener(this);mValueAnimator.addListener(this);mValueAnimator.start();startColorAnimation();}private void startColorAnimation(){int colorFrom = isChecked?mOpenColor:mCloseColor; //mIsOpen为true则表示要启动关闭的动画int colorTo = isChecked? mCloseColor:mOpenColor;ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);colorAnimation.setDuration(500); // millisecondscolorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animator) {mCurrentColor = (int)animator.getAnimatedValue();}});colorAnimation.start();}//设置监听public void setOnCheckedChangeListener(OnCheckedChangeListener listener){mCheckedChangeListener = listener;}public boolean isChecked() {return isChecked;}public void setChecked(boolean checked) {isChecked = checked;if (isChecked){mCurrentColor = mOpenColor;mAnimationFraction = 1.0f;}else {mCurrentColor = mCloseColor;mAnimationFraction = 0.0f;}invalidate();}@Overridepublic void onAnimationStart(Animator animator) {isAnimation = true;}@Overridepublic void onAnimationEnd(Animator animator) {isAnimation = false;}@Overridepublic void onAnimationCancel(Animator animator) {isAnimation = false;}@Overridepublic void onAnimationRepeat(Animator animator) {isAnimation = true;}@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {mAnimationFraction = (float) valueAnimator.getAnimatedValue();invalidate();}public interface OnCheckedChangeListener{void onCheckedChanged(boolean isChecked);}
}

attrs.xml代码

<?xml version="1.0" encoding="utf-8"?>
<resources><!--    开关按钮CustomSwitch的样式定义  --><declare-styleable name="CustomSwitch"><attr name="closeText" format="string" /><attr name="openText" format="string" /><attr name="closeColor" format="color" /><attr name="openColor" format="color" /><attr name="customWidth" format="integer" /><attr name="customHeight" format="integer" /></declare-styleable>
</resources>

activity的xml代码:

<com.fslihua.my_application_1.cumstom_ui.CustomSwitchandroid:id="@+id/customSwitch"android:layout_marginTop="20dp"android:layout_marginStart="20dp"android:layout_width="50dp"android:layout_height="25dp"app:closeColor="#6A6A6A"app:closeText="关"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" />

三、包含动画效果的打勾

import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.graphics.PathMeasure
import android.util.AttributeSet
import android.util.Log
import android.util.TypedValue
import android.view.View
import android.view.animation.DecelerateInterpolator
import com.fslihua.my_application_1.R/*** 创建时间:2023/11/9* 类说明:包含动画效果的打勾*/
class AnimatedCheckView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) {private val circlePaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)private val checkPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)private var circlePath = Path()private var checkPath = Path()private var circleColor = 0private var checkColor = 0private var pathLength = 0f// 默认值private var circleStrokeWidth = 1fprivate var checkStrokeWidth = 1fprivate val animator = ValueAnimator().apply {interpolator = DecelerateInterpolator()addUpdateListener {invalidate()}}private var animateTime: Float = 2f // 2秒init {context.theme.obtainStyledAttributes(attrs, R.styleable.AnimatedCheckView, 0, 0).apply {try {circleColor = getColor(R.styleable.AnimatedCheckView_circleColor, Color.BLACK)checkColor = getColor(R.styleable.AnimatedCheckView_checkColor, Color.BLACK)circleStrokeWidth = getDimension(R.styleable.AnimatedCheckView_circleStrokeWidth, dp2px(context, circleStrokeWidth).toFloat())checkStrokeWidth = getDimension(R.styleable.AnimatedCheckView_checkStrokeWidth, dp2px(context, checkStrokeWidth).toFloat())animateTime = getFloat(R.styleable.AnimatedCheckView_animateTime, animateTime)Log.i("AnimatedCheckView", "circleStrokeWidth: $circleStrokeWidth, checkStrokeWidth: $checkStrokeWidth" )} finally {recycle()}}circlePaint.apply {style = Paint.Style.STROKEstrokeWidth = circleStrokeWidthcolor = circleColor}checkPaint.apply {style = Paint.Style.STROKEstrokeWidth = checkStrokeWidthcolor = checkColor}}override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {super.onSizeChanged(w, h, oldw, oldh)val centerX = w / 2fval centerY = h / 2fval radius = w.coerceAtMost(h) / 2f - circleStrokeWidth / 2initPaths(centerX, centerY, radius)animator.apply {setFloatValues(0f, pathLength)duration = (animateTime * 1000).toLong()start()}Log.i("AnimatedCheckView", "w: $w, h: $h, centerX: $centerX, centerY: $centerY, radius: $radius" )}private fun initPaths(centerX: Float, centerY: Float, radius: Float) {circlePath.addCircle(centerX, centerY, radius, Path.Direction.CW)checkPath.apply {moveTo(centerX - radius / 2 - radius / 15, centerY + radius / 15)lineTo(centerX - radius / 2, centerY)lineTo(centerX - radius / 8, centerY + radius / 3)lineTo(centerX + radius / 2, centerY - radius / 3)}val measure = PathMeasure(circlePath, false)val circleLength = measure.lengthmeasure.setPath(checkPath, false)val checkLength = measure.lengthpathLength = circleLength + checkLength}@SuppressLint("DrawAllocation")override fun onDraw(canvas: Canvas) {super.onDraw(canvas)val measure = PathMeasure(circlePath, false)val dst = Path()val animatedValue = animator.animatedValue as Floatval circleLength = measure.lengthif (animatedValue < circleLength) {measure.getSegment(0f, animatedValue, dst, true)canvas.drawPath(dst, circlePaint)} else {measure.getSegment(0f, circleLength, dst, true)canvas.drawPath(dst, circlePaint)measure.nextContour()measure.setPath(checkPath, false)dst.rewind()measure.getSegment(0f, animatedValue - circleLength, dst, true)canvas.drawPath(dst, checkPaint)}}fun dp2px(context: Context, dpVal: Float): Int {return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dpVal, context.resources.displayMetrics).toInt()}
}

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources><declare-styleable name="AnimatedCheckView"><attr name="circleColor" format="color" /><attr name="checkColor" format="color" /><attr name="circleStrokeWidth" format="dimension" /><attr name="checkStrokeWidth" format="dimension" /><attr name="animateTime" format="float" /></declare-styleable>
</resources>

activity中的代码:

<com.fslihua.my_application_1.cumstom_ui.AnimatedCheckViewandroid:id="@+id/ac_success"android:layout_width="55dp"android:layout_height="55dp"android:layout_marginTop="64dp"app:animateTime="0.7"app:checkColor="#3ACFA5"app:checkStrokeWidth="2dp"app:circleColor="#3ACFA5"app:circleStrokeWidth="2dp"app:layout_constraintStart_toEndOf="@+id/customSwitch"app:layout_constraintTop_toTopOf="parent" />

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/446278.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式-原型模式(克隆、Clone、Prototype)

原型模式&#xff08;克隆、Clone、Prototype&#xff09;是一种创建型设计模式&#xff0c; 使你能够复制已有对象&#xff0c; 而又无需使代码依赖它们所属的类。 问题 譬如美国研制了一种特效药&#xff0c;而且还在专利保护器内&#xff0c;而印度制药公司看中了&#xff0…

2024 第一次周赛

A: 题目大意 骑士每连续 i 天每天会得到 i 个金币&#xff0c;&#xff08;i 1&#xff0c; 2&#xff0c; 3 &#xff0c; …&#xff09;,那么展开看每一天可以得到的金币数&#xff1a;1 2 2 3 3 3 4 4 4 5 5 5 5 5 … 可以发现就是1个1 &#xff0c;2个2, 3个3…,那么我…

Flutter 3.24 发布:GPU模块及多视图嵌入功能

Flutter 3.24 发布&#xff1a;GPU模块及多视图嵌入功能 Flutter 3.24 带来了许多新功能和改进&#xff0c;让开发应用程序变得更加容易和有趣。这个版本重点展示了 Flutter GPU 的预览功能&#xff0c;让应用程序可以直接使用高级图形和 3D 场景功能。 此外&#xff0c;网页…

win软件 超强的本地视频 图片去水印 动态水印!

AI视频图片去水印 HitPaw Watermark Remover 电脑软件&#xff0c;内涵安装教程&#xff0c;以后看到有水印的视频不怕啦&#xff0c;用这个就行了&#xff0c;可以去除动态水印&#xff01; 【下载】 https://pan.quark.cn/s/1ba6f088f0b2 【应用名称】:HitPaw Watermark R…

ARIMA 模型初体验 —— 预测股票数据

第 1 步&#xff0c;从 twelvedata 上获取苹果 11 号 15:30 到 16:00 的 OHLC、成交量 数据。 第 2 步&#xff0c;编写 Python 代码&#xff08;实际上可以用 R 语言&#xff0c;R 语言从语言的级别对分析预测提供了支持&#xff0c;而 Python 需要第三方库&#xff09;。 …

C++ day04(友元 friend、运算符重载、String字符串)

目录 【1】友元 friend 1》概念 2》友元函数 3》友元类 4》友元成员函数 【2】运算符重载 1》概念 2》友元函数运算符重载 ​编辑 3》成员函数运算符重载 4》赋值运算符与类型转换运算符重载 5》注意事项 【3】String 字符串类 【1】友元 friend 1》概念 定义&#x…

BUUCTF-greatescape1

发现有ftp包和tcp包居多 下载解压是个流量包&#xff0c;使用wiresharh打开&#xff0c;CTRLF&#xff0c;按下图搜索ftp tcp18流发现ssc.key 传送&#xff0c;在19流发现key内容 复制保存为ssc.key, 加载key解密tls&#xff0c;再追踪tls流可得flag INS{OkThatWasWay2Easy} …

多元线性回归:机器学习中的经典模型探讨

引言 多元线性回归是统计学和机器学习中广泛应用的一种回归分析方法。它通过分析多个自变量与因变量之间的关系&#xff0c;帮助我们理解和预测数据的行为。本文将深入探讨多元线性回归的理论背景、数学原理、模型构建、技术细节及其实际应用。 一、多元线性回归的背景与发展…

基于Java的旅游网站管理系统—计算机毕业设计源码39235

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对旅游网站等问题&#xff0c;对旅游网站进行…

一区大黄蜂!人工蜂群算法优化!ABC-CNN-LSTM-MATT多特征分类预测

一区大黄蜂&#xff01;人工蜂群算法优化&#xff01;ABC-CNN-LSTM-MATT多特征分类预测 目录 一区大黄蜂&#xff01;人工蜂群算法优化&#xff01;ABC-CNN-LSTM-MATT多特征分类预测分类效果基本介绍程序设计参考资料 分类效果 基本介绍 1.Matlab实现ABC-CNN-LSTM-MATT人工蜂群…

PDF转JPG神器!一键转换,轻松搞定文档分享

各位亲爱的小伙伴们&#xff0c;有没有遇到过需要把PDF文件转换成JPG图片的情况呢&#xff1f;今天我就来给大家推荐几款好用的PDF转JPG工具&#xff0c;让我们一起来看看这些工具的详细介绍和使用感受吧&#xff01; 一、福昕转换器 直通车&#xff08;粘贴到浏览器打开&…

获取时隔半个钟的三天与el-time-select

摘要&#xff1a; 今天遇到需求是配送时间&#xff0c;时隔半个钟的排线&#xff01;所以需要拼接时间&#xff01;例如2024-10-08 14&#xff1a;30&#xff0c;2024-10-08 15&#xff1a;00&#xff0c;2024-10-08 15&#xff1a;30 <el-form-item label"配送时间&a…

优先算法1--双指针

“一念既出&#xff0c;万山无阻。”加油陌生人&#xff01; 目录 1.双指针--移动零 2.双指针-复写零 ok&#xff0c;首先在学习之前&#xff0c;为了方便大家后面的学习&#xff0c;我们这里需要补充一个知识点&#xff0c;我这里所谓的指针&#xff0c;不是之前学习的带有…

如何构建高效的公路工程资料管理系统?

本文介绍了构建高效的公路工程资料管理系统的方法&#xff0c;涵盖了系统需求分析、功能设计、开发平台选择、开发过程、系统上线与培训、持续改进与维护等关键环节。通过合理规划和科学管理&#xff0c;可以确保系统满足用户需求&#xff0c;提高工作效率&#xff0c;保障公路…

react18+react-transition-group实现路由切换过度

效果如下 官网安装对应的插件 创建对应的样式 .fade-enter {opacity: 0; } .fade-exit {opacity: 1; } .fade-enter-active {opacity: 1; } .fade-exit-active {opacity: 0; } .fade-enter-active, .fade-exit-active {transition: opacity 500ms; }const location useLoca…

STM32 | STM32F4OTA_ESP8266_Bootloader为引导程序远程更新的代码(APP)

更新。点击上方"蓝字"关注我们 01、思路 >>> STM32F4OTA_ESP8266_Bootloader为引导程序 远程更新的代码&#xff08;APP&#xff09;:远程更新的APP Ymoden_server&#xff1a;为运行在Linux的TCP服务器 备注&#xff1a;STM32 OTA远程更新需要连接热点 电…

【实战项目】——Boost搜索引擎(五万字)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、项目的相关背景 1.1、什么是Boost库&#xff1f; 1.2、什么是搜索引擎&#xff1f; 1.3、为什么要做Boost库搜索引擎&#xff1f; 二、搜索引擎的宏观原…

【优选算法篇】双指针的优雅舞步:C++ 算法世界的浪漫探索

文章目录 C 双指针详解&#xff1a;基础题解与思维分析前言第一章&#xff1a;对撞指针1.1 移动零解题思路图解分析C代码实现易错点提示代码解读 1.2 复写零解题思路算法步骤C代码实现易错点提示代码复杂度 1.3 盛最多水的容器1. 题目链接2. 题目描述解法一&#xff08;暴力求解…

MySQL SELECT 查询(三):查询常用函数大全

MySQL SELECT 查询&#xff08;三&#xff09;&#xff1a;查询常用函数大全 1. 单行函数 单行函数是 SQL 中一类重要的函数&#xff0c;它们可以对单行数据进行处理&#xff0c;并返回单个结果。单行函数可以嵌套使用&#xff0c;并提供灵活的数据处理能力。 1.1 定义 只对单…

H7-TOOL的LUA小程序教程第14期:任意波形信号发生器,0-20mA输出和微型数控电源(2024-10-11,已更新)

LUA脚本的好处是用户可以根据自己注册的一批API&#xff08;当前TOOL已经提供了几百个函数供大家使用&#xff09;&#xff0c;实现各种小程序&#xff0c;不再限制Flash里面已经下载的程序&#xff0c;就跟手机安装APP差不多&#xff0c;所以在H7-TOOL里面被广泛使用&#xff…