RE:从零开始的车载Android HMI(四) - 收音机刻度尺
最近比较忙,研究复杂的东西需要大量集中的时间,但是又抽不出来,就写点简单的东西吧。车载应用开发中有一个几乎避不开的自定义View,就是收音机的刻度条。本篇文章我们来研究如何绘制一个收音机的刻度尺。
本系列文章的目的是在讲解自定义View是如何实现的,阅读时,注意一些通用效果的实现方式,而不要仅仅局限于如何实现本文中提到的刻度尺。
本文涉及的的知识点如下:
- 自定义View时的一些常识,例如:如何处理
layout_height、layout_width; - 刻度的绘制;
- OverScroller介绍,以及如何实现惯性滑动;
- 滑动位置修正,实现刻度吸附效果。
实现思路
写一个 Android 收音机 UI 上的刻度尺 View 的基本思路如下:
- 第一步,创建一个自定义 View 类,继承自 View 并根据需要重写构造方法和onMeasure、onLayout、onDraw 方法。
- 第二步,在 onDraw 方法中使用 Canvas 和 Paint 对象来绘制刻度尺的各个部分,包括刻度线,刻度值,指示器等。
- 第三步,使用 scrollBy 或者 scrollTo 方法来实现刻度尺的滑动效果,并使用 Scroller 或者 OverScroller 对象来实现惯性滑动效果。
- 第四步,在自定义 View 类中定义一些接口或者回调方法,用于与外部进行通信和交互。
下面我们来一一实现。
实现过程
定义View的宽、高
定义View的宽、高就是重写onMeasure方法。还记得View测量模式的含义吗?没关系,我们简单回忆一下即可。
- MeasureSpec.EXACTLY(精确模式)
当我们在xml中将为layout_height或layout_width设定为match_parent或者具体的值时,在onMeasure时对应的测量模式就会是EXACTLY,表示当前View的高度或宽度值是已经确定好的。
所以,在EXACTLY时我们一般不会修改系统测量出的值,直接将其用作当前View的高度或宽度。
- MeasureSpec.AT_MOST(至多模式)
当我们在xml中将为layout_height或layout_width设定为wrap_content时,在onMeasure时对应的测量模式就会是AT_MOST,表示系统并不知道当前View的高度和宽度,但是有一个确定范围值,只要不超过系统给出值,都可以。
所以,在EXACTLY时我们需要计算出当前View需要的高度和宽度(也就是View默认宽高)。大于、等于系统的测量值时,使用系统的测量值;小于系统的测量值时,使用我们自己的。
- MeasureSpec.UNSPECIFIED(不限制模式)
当自定义View的父布局时ScrollView一类,可以跟随子View大小改变自身大小的View时,在onMeasure时对应的测量模式就会是UNSPECIFIED。处理方式不定,一般也可以直接采用系统的测量值。
在本例中,我们只计算View的高度,宽度使用系统测量好的即可。
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),measureHeight(heightMeasureSpec))
}private fun measureHeight(heightMeasureSpec: Int): Int {val heightMode = MeasureSpec.getMode(heightMeasureSpec)val heightSize = MeasureSpec.getSize(heightMeasureSpec)var height = 0when (heightMode) {// MeasureSpec.EXACTLY 为match_parent或者具体的值MeasureSpec.EXACTLY -> {height = heightSize}// MeasureSpec.AT_MOST 为wrap_contentMeasureSpec.AT_MOST -> {// 高度 = 刻度尺长刻度的高度 + 上边距 + 下边距height = longScaleHeight.coerceAtLeast(pointHeight) + paddingTop + paddingBottom// 如果高度大于父容器给的高度,则取父容器给的高度height = height.coerceAtMost(heightSize)}// MeasureSpec.UNSPECIFIED 父容器对于子容器没有任何限制,子容器想要多大就多大,多出现于ScrollViewMeasureSpec.UNSPECIFIED -> {height = heightSize}}return height
}
为了支持xml中的padding属性,在计量高度时还需要加上paddingTop、paddingBottom。然后,在onSizeChanged方法中我们会得到View的最终宽、高,并据此计算出刻度条长指针、短指针的高度。
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {super.onSizeChanged(w, h, oldw, oldh)viewWidth = wviewHeight = hinitParams()
}private fun initParams() {// 长刻度的高度 = 控件高度 - 上边距 - 下边距longScaleHeight = height - paddingTop - paddingBottom// 短刻度的高度 = 长刻度的高度 - 15dpshortScaleHeight = longScaleHeight - 15.dp
}
到此,我们定义的View已经可以正确处理xml中的layout_height和layout_width属性了。接下来我们开始绘制刻度条。
绘制刻度
绘制刻度原理并不复杂,思路如下:
- 使用刻度尺的最大值 - 最小值,得到总的刻度数
- 循环总刻度数,使用drawLine绘制出线条
- 绘制出收音机刻度尺中间的游标
override fun onDraw(canvas: Canvas?) {super.onDraw(canvas)for (i in 0..scaleCount) {// 点从下往上绘制// 刻度起始的x坐标 = 刻度间隔 * i + 左边距val x1 = scaleSpace * i// 刻度起始的y坐标 = 上边距val y1 = height - paddingBottom// 刻度终点的x坐标 = 刻度起始的x坐标val x2 = x1// 刻度终点的y坐标 = 控件高度 - 下边距 - 刻度高度val y2 = height - paddingBottom - (if (i % 10 == 0) longScaleHeight else shortScaleHeight)// 绘制表尺刻度canvas?.drawLine(x1.toFloat(), y1.toFloat(),x2.toFloat(), y2.toFloat(),linePaint)drawCenterLine(canvas)}
}private fun drawCenterLine(canvas: Canvas?) {// 表尺中心点的x坐标 +滚动的距离是为了让中心点始终在屏幕中间val centerPointX = viewWidth / 2 + scrollX// 中间刻度的起始y坐标 = 上边距 - 5dp(加长5dp)val centerStartPointY = paddingTop - 5.dp// 中间刻度的终点y坐标 = 控件高度 - 下边距 + 5dp(加长5dp)val centerEndPointY = viewHeight - paddingBottom + 5.dpcanvas?.drawLine(centerPointX.toFloat(), centerStartPointY.toFloat(),centerPointX.toFloat(), centerEndPointY.toFloat(),pointPaint)
}
完成上述步骤我们就可以看到下面的效果。

这一步,我们绘制出了刻度尺的刻度和游标,已经可以看到刻度尺基本的雏形了。接下来,我们继续实现刻度尺的滑动。
触摸滑动
常规实现触摸滑动的方式之一是重写OnTouchEvent方法,根据触摸移动时的坐标判断是否处于滑动状态。本例中,我们使用手势识别类 - GestureDetector。
GestureDetector是一个用于检测用户在屏幕上的手势操作的类,它可以识别一些基本的手势,如按下、抬起、滑动、长按、轻击、快速滑动等。
它的使用方法是创建一个GestureDetector实例,并传入一个GestureDetector.OnGestureListener接口,该接口定义了一些方法,用于处理不同的手势事件。在需要检测手势的View或Activity中,将触摸事件传递给GestureDetector的onTouchEvent方法,从而让GestureDetector响应触摸事件并调用相应的监听器方法。
private val gestureDetector by lazy { GestureDetector(context, touchGestureListener) }private val touchGestureListener = object : GestureDetector.SimpleOnGestureListener() {override fun onDown(e: MotionEvent): Boolean {return true}override fun onScroll(e1: MotionEvent,e2: MotionEvent,distanceX: Float,distanceY: Float): Boolean {// 当监听到滑动事件时,滚动到指定位置scrollBy(distanceX.toInt(), 0)return true}}override fun onTouchEvent(event: MotionEvent?): Boolean {// return gestureDetector.onTouchEvent(event!!)}
上面的代码中,当GestureDetector监听到触摸手势为滑动onScroll时,调用View.scrollBy()方法,将当前View的内容移动对应的滑动距离。onScroll 的回调值 distanceX 就是手指在x轴(水平)上滑动的距离。
这里注意scrollBy和scrollTo的区别和特点:
scrollBy是在当前的位置基础上,相对滑动一定的距离,而scrollTo是直接滑动到指定的绝对位置。scrollBy实际上是调用了scrollTo方法,它的参数是滑动的增量,而scrollTo的参数是滑动的目标位置。scrollBy和scrollTo都是移动View的内容,而不是View本身。对于一个ViewGroup,它的内容是它的所有子View;对于一个TextView,它的内容是它的文本。

这一步中,我们实现了触摸滑动。但是当停止滑动时,刻度尺会立即停下,用户体验比较差,所以还需进一步实现惯性滑动。
惯性滑动
惯性滑动是一种在用户在屏幕上滑动页面后,页面不会马上停下,而是继续保持一定时间的滚动效果的手势操作。它可以提高用户的交互体验,让页面的滚动更加平滑和自然。
Android中的OverScroller是一个用于实现View平滑滚动的辅助类,它可以根据用户的手势操作或者指定的参数来计算出每一时刻View的位置和速度,并提供了一些方法来控制滚动的开始、结束、中断等状态。
OverScroller.fling()方法可以实现,从指定位置滑动一段位置然后停下。滑动效果只与离手速度以及滑动边界有关,不能设置惯性滑动距离、时间和插值器。
private val touchGestureListener = object : GestureDetector.SimpleOnGestureListener() {// ...override fun onFling(e1: MotionEvent,e2: MotionEvent,velocityX: Float,velocityY: Float): Boolean {// 启动滚动器,设置滚动的起始位置,速度,范围和回弹距离scroller.fling(scrollX, 0,-velocityX.toInt() / 2, 0,-viewWidth / 2, (scaleCount - 1) * scaleSpace - viewWidth / 2,0, 0,viewWidth / 4, 0)invalidate()return true}
}
fling方法参数的含义如下:
- startX, startY:表示滑动的起始位置的x和y坐标。
- velocityX, velocityY:表示滑动的初始速度的x和y分量,单位是像素/秒。
- minX, maxX, minY, maxY:表示滑动的边界范围,如果滑动超过这个范围,就会触发OverScroll效果。
- overX, overY:表示OverScroll的最大距离,即滑动超过边界后,还能继续滑动的距离
computeScroll()是一个用于控制View的滑动效果的方法,它会在View的draw()方法中被调用,用于计算View在每一时刻的位置和状态。
override fun computeScroll() {super.computeScroll()// 如果滚动器正在滚动,更新滚动的位置,并根据需要修正位置if (scroller.computeScrollOffset()) {scrollTo(scroller.currX, scroller.currY)invalidate()}}

OverScroller不仅可以实现惯性滑动,还可以实现以下几种滚动效果:
startScroll:从指定位置滚动一段指定的距离然后停下,滚动效果与设置的滚动距离、滚动时间、插值器有关,跟离手速度没有关系。一般用于控制View滚动到指定的位置。springBack:从指定位置回弹到指定位置,一般用于实现拖拽后的回弹效果,不能指定回弹时间和插值器。
好了,惯性滑动实现了,但是当前的刻度尺还有很多瑕疵,例如:滑动时会越界,滑动停止后可能停在两个刻度之间,接下来我们还需要进一步修正这些瑕疵。
限定滑动范围
首先,我们需要限定滑动的范围,保证滑动时不能越界。
重写View的scrollTo方法,在这里我们可以监听View每次的滑动坐标,当滑动坐标越界时,及时修正滑动坐标,就可以防止越界。
// 滚动方法
override fun scrollTo(x: Int, y: Int) {Log.e("TAG", "scrollTo: ")// 限制滚动的范围,避免越界var x = x// 当x坐标小于可视区域的一半时,设置x坐标为可视区域的一半if (x < -viewWidth / 2) {x = -viewWidth / 2}// 当x坐标大于最大滚动距离时,设置x坐标为最大滚动距离if (x > (scaleCount) * scaleSpace - viewWidth / 2) {x = (scaleCount) * scaleSpace - viewWidth / 2}// 调用父类的滚动方法super.scrollTo(x, y)// 保存当前选中的值 和x坐标currentValue = (x + viewWidth / 2) / scaleSpace + scaleMinValuecurrentX = x// 触发重绘,更新视图invalidate()
}
在scrollTo中我们计算出了当前的实际刻度值,这里保存好备用。

位置修正
在computeScroll()中判断滚动事件是否已经结束,如果结束,就开始修正滑动坐标。
override fun computeScroll() {// 如果滚动器正在滚动,更新滚动的位置,并根据需要修正位置if (scroller.computeScrollOffset()) {scrollTo(scroller.currX, scroller.currY)if (scroller.isFinished) {correctPosition()}invalidate()}
}
修正坐标基本思路是,首先计算出当前刻度数值对应的x坐标,因为刻度值在计算时已经取整了,所以一定是不等于当前的实际x坐标,两者的差值就是偏移量。当偏移量大于刻度间距的一半时,向前滑动,否则向后滑动。
// 修正位置,计算当前选中值距离最近的刻度的偏移量,并根据偏移量进行平滑滚动到正确的位置
private fun correctPosition() {// 刻度值对应的x坐标val scaleX: Int = (currentValue - scaleMinValue) * scaleSpace - viewWidth / 2// 偏移值 = 刻度值对应的x坐标-当前x坐标 的绝对值val offset = (scaleX - currentX).absoluteValueif (offset == 0) {return}// 大于间距if (offset > scaleSpace / 2) {smoothScrollBy(scaleSpace - offset)} else {smoothScrollBy(-offset)}
}// 平滑滚动方法
private fun smoothScrollBy(dx: Int) {// 启动滚动器,设置滚动的起始位置,距离,时间和插值器scroller.startScroll(scrollX, 0, dx, 0, 200)invalidate()
}
由于computeScroll()只有在滑动时才会有回调,所以还需要在手指抬起时修正一次位置,防止遗漏拖动事件。
override fun onTouchEvent(event: MotionEvent?): Boolean {// 当手指抬起时,校准位置if (event?.action == MotionEvent.ACTION_UP || event?.action == MotionEvent.ACTION_CANCEL) {correctPosition()// 将刻度值通过回调传出去.}return gestureDetector.onTouchEvent(event!!)
}

通过,以上这几步我们就完成了一个收音机刻度,最后我们进行收尾。
收尾
刻度尺需要支持外部传入数据,并移动相应的位置,所以暴露一个setCurrentValue方法,然后重写onLayout方法,在其中计算出刻度值的滑动坐标,使用scrollTo滑动到对应的x坐标即可。
// 注意,由于会主动调用requestLayout(),所以不能复写kotlin的set方法。
fun setCurrentValue(value: Int) {// 限制值的范围,避免越界var value = valueif (value < scaleMinValue) {value = scaleMinValue}if (value > scaleMaxValue) {value = scaleMaxValue}currentValue = value// 更新当前选中值,并重新布局requestLayout()
}override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {super.onLayout(changed, left, top, right, bottom)// 根据当前选中值计算滚动的距离 = (当前选中值 - 最小值) * 刻度间隔 - 控件宽度的一半val scrollX: Int = (currentValue - scaleMinValue) * scaleSpace - viewWidth / 2scrollTo(scrollX, 0)
}
使用一段测试代码,就可以实现收音机搜台效果了。
val handler = Handler(Looper.getMainLooper())for (i in 0..155) {handler.postDelayed({findViewById<ScaleView>(R.id.scaleView).setCurrentValue(i)}, 150 * i.toLong())
}

总结
本文介绍了如何编写一个刻度尺View,不过本文的例子不要直接使用在你的项目中,以我个人经验而言,收音机刻度尺变化较多,互联网上很少有View能不做修改直接运用在项目中的,所以更应该关注实现的原理,方便我们在需要时进行修改和定义。
源码地址:https://github.com/linxu-link/FuckView
好,以上就是本文的所有内容,感谢你的阅读,希望对你有所帮助。
相关文章:
RE:从零开始的车载Android HMI(四) - 收音机刻度尺
最近比较忙,研究复杂的东西需要大量集中的时间,但是又抽不出来,就写点简单的东西吧。车载应用开发中有一个几乎避不开的自定义View,就是收音机的刻度条。本篇文章我们来研究如何绘制一个收音机的刻度尺。 本系列文章的目的是在讲…...
评估安全 Wi-Fi 接入:Cisco ISE、Aruba、Portnox 和 Foxpass
在当今不断变化的数字环境中,对 Wi-Fi 网络进行强大访问控制的需求从未像现在这样重要。各组织一直在寻找能够为其用户提供无缝而安全的体验的解决方案。 在本博客中,我们将深入探讨保护 Wi-Fi(和有线)网络的四种领先解决方案——…...
java 泛型作为方法的返回值的封装
问题背景 业务需要,经常需要http方式调用某服务,然后某服务返回特定类型的返回内容。 类似 String resStr xxxHttpClient.post() ,然后它返回一个字符串,你还需要反序列化成某种格式的。 返回值可以反序列化成的形式如下&#…...
ASP.NET Core 中基于 Minimal APIs 的Web API
基于 Minimal APIs 的Web API Minimal APIs 是ASP.NET Core中快速构建 REST API 的方式,可以用最少的代码构建全功能的REST API。比如下面三行代码: var app WebApplication.Create(args); app.MapGet("/", () > "Hello World!&quo…...
Unity ProBuilder SetUVs 不起作用
ProBuilder SetUVs 不起作用 🐟 需要设置face.manulUV true public static void Set01UV(this ProBuilderMesh mesh){foreach (var face in mesh.faces){face.manualUV true;//设置为手动uv}var vertices mesh.GetVertices().Select(v > v.position).ToArray(…...
c#接口(interface)
概述: 在C#中,接口是一种定义了一组相关方法、属性和事件的规范。接口可以被类或结构体实现,以提供一种方式来定义类之间的契约或协议。 接口定义了一组成员,这些成员没有具体的实现。实现接口的类必须提供这些成员的具体实现。…...
SSH远程连接macOS服务器:通过cpolar内网穿透技术实现远程访问的设置方法
文章目录 前言1. macOS打开远程登录2. 局域网内测试ssh远程3. 公网ssh远程连接macOS3.1 macOS安装配置cpolar3.2 获取ssh隧道公网地址3.3 测试公网ssh远程连接macOS 4. 配置公网固定TCP地址4.1 保留一个固定TCP端口地址4.2 配置固定TCP端口地址 5. 使用固定TCP端口地址ssh远程 …...
【C++】Visual Studio EditorConfig 格式设置
【C】Visual Studio EditorConfig 格式设置 文章目录 【C】Visual Studio EditorConfig 格式设置I - EditorConfig1.1 - 通用设置indent_styleindent_sizetab_widthend_of_linecharsettrim_trailing_whitespaceinsert_final_newline II - Visual Studio 特定键值缩进设置cpp_in…...
服务器单机大规模数据存储方案
大规模数据存储都需要解决三个核心问题: 1.数据存储容量的问题,既然大数据要解决的是数据 PB 计的数据计算问题,而一般的服务器磁盘容量通常 1~2TB,那么如何存储这么大规模的数据呢? 2.数据读写速度的问题&…...
ElasticSearch-集成ik分词器
本文已收录于专栏 《中间件合集》 目录 背景介绍版本选择优势说明集成过程1.下载安装包2.解压安装包3.重启ElasticSearch服务3.1通过ps -ef | grep elastic查看正在启动的es进程号3.2使用kill -9 xxx 杀死进程3.3使用 ./elasticsearch 启动es服务 分词测试细粒度分词方式分词请…...
c++版opencv求二值图的质心
代码 #include <iostream> #include <opencv2/core.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp>int main(int argc, char* argv[]) {cv::Mat input_image cv::imread("Untitled.png", cv::IMREAD_GRAYSCALE);cv:…...
6、深入解析Kotlin类与对象:构造、伴生、单例全面剖析
前言 本篇文章将带您了解Kotlin编程中的重要概念:类及构造函数、访问修饰符、伴生对象和单例模式。就像搭积木一样,我们会逐步揭开这些概念的面纱,让您轻松理解它们的作用和用法。无论您是编程新手还是有经验的开发者,本文都将为…...
【开源ESP32谷歌恐龙小游戏】【游戏演示和介绍】LVGL ST7789 适用于Arduino
【源码及教程地址-持续更新】 ESP32 C3 LVGL 迷你小电视 Google谷歌恐龙小游戏 1.9寸LCD显示屏开发板 ST7789 适用于Arduino开发板,教程,资料,程序,代码,PDF手册 【开源 & ESP32谷歌恐龙小游戏】【游戏演示和介绍】LVGL ST7789 适用于Arduin...
openCV实战-系列教程7:轮廓检测2与模板匹配(轮廓检测/轮廓特征/轮廓近似/轮廓边界矩阵/轮廓边界圆/模版匹配)、原理解析、源码解读
🧡💛💚💙💜OpenCV实战系列总目录 打印一个图片可以做出一个函数: def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows() 1、轮廓特征与近似 1.1 轮廓特征 前面我们计算了…...
cs231n_1_IntroToConv
参考的视频来自如下链接https://www.bilibili.com/video/BV1Ed4y1b7bm/ 参考笔记如下https://blog.csdn.net/TeFuirnever/article/details/89059673 x.1 CV历史 生物快速发展于5.4亿年前,那时的化石显示生物进化出了视觉,视觉使得生物多样性大爆炸。 …...
OPENCV实现SURF特征检测
1、SURF优点:SIFT速度慢,一次出现了SURF;2、使用SURF步骤:surf = cv2.xfeatures2d.SURF_create()kp,des = surf.detectAndComputer(img,mask)# -*- coding:utf-8 -*- """ 作者:794919561 日期:2023/8/31 """# -*-...
Android Gradle 同步优化
作者:究极逮虾户 很多人听到方法论三个字,就觉得我要开始pua,说我阿里味,但是我觉得这个查问题的方式可能会对大家有点帮助。 很多人都会有这样的困扰,给你的一个工作内容是一个你完全陌生的东西,第一选择…...
BeautifulSoup:学习使用BeautifulSoup库进行HTML解析和数据提取。
BeautifulSoup是一个用于解析HTML和XML文档的Python库。它可以帮助我们从网页中提取数据,并以易于操作的方式进行分析。 以下是使用BeautifulSoup进行HTML解析和数据提取的基本语法: 安装BeautifulSoup库:首先,你需要在你的Python…...
基于沙猫群算法优化的BP神经网络(预测应用) - 附代码
基于沙猫群算法优化的BP神经网络(预测应用) - 附代码 文章目录 基于沙猫群算法优化的BP神经网络(预测应用) - 附代码1.数据介绍2.沙猫群优化BP神经网络2.1 BP神经网络参数设置2.2 沙猫群算法应用 4.测试结果:5.Matlab代…...
PCL 判断三点共线(三维空间)
文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 继续之前的思路PCL 判断两条线段的平行性(三维空间),我们可以把判断三点共线看做是判断两条线段是否具有平行性,且这两条线段共用其中一个端点,基于此当这两条线段平行时,则证明这三点共线。 二、实现代码 /…...
避坑指南:MATLAB调用ROS2话题时,消息类型错误‘std_msgs/String’怎么办?
MATLAB与ROS2通信避坑指南:消息类型错误的深度解析与实战解决方案 当你在MATLAB中尝试与ROS2系统建立通信时,是否遇到过这样的报错:"Error using ros2subscriber. The message type std_msgs/String is invalid."?这看似…...
从零开始:LabelImg图像标注工具的完整实战指南
从零开始:LabelImg图像标注工具的完整实战指南 【免费下载链接】labelImg LabelImg is now part of the Label Studio community. The popular image annotation tool created by Tzutalin is no longer actively being developed, but you can check out Label Stu…...
文墨共鸣应用场景:高校思政课教案语义重复检测与创新性评估
文墨共鸣应用场景:高校思政课教案语义重复检测与创新性评估 1. 引言:当传统思政课遇上AI语义分析 高校思政课教师每年都要准备大量教案,从经典理论阐释到时事热点分析,内容创作压力不小。一个常见的问题是:不同章节的…...
AMD平台黑苹果智能配置引擎:从技术困境到自动化解决方案的完整指南
AMD平台黑苹果智能配置引擎:从技术困境到自动化解决方案的完整指南 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 在传统黑苹果配置领域&…...
Wonder3D:从单张图片生成3D模型的终极指南
Wonder3D:从单张图片生成3D模型的终极指南 【免费下载链接】Wonder3D Single Image to 3D using Cross-Domain Diffusion 项目地址: https://gitcode.com/gh_mirrors/wo/Wonder3D Wonder3D是一款革命性的AI工具,能够在短短2-3分钟内将单张2D图片转…...
RTX4090D大模型推理专用镜像体验:Qwen-Image预装环境,一键启动图文对话
RTX4090D大模型推理专用镜像体验:Qwen-Image预装环境,一键启动图文对话 1. 镜像概述与核心优势 1.1 为什么选择专用镜像 在本地部署大语言模型时,环境配置往往是最耗时的环节。以Qwen-VL这样的视觉语言模型为例,需要处理CUDA版…...
提升工作效率的利器:哦我的Claude代码(Oh-My-ClaudeCode)
轻松掌握Claude Code的多代理 orchestration——oh-my-claudecode 在我们的工程师和开发者面前,常常会遇到复杂的任务调度和多代理协作的问题。如何有效地利用可用的AI助手并提高工作效率,成为了一个不容忽视的挑战。oh-my-claudecode正是为了解决这些问…...
一个普通程序员转型AI的崩溃日记:我做了一个“没用”的系统救了他
一位Java程序员在转型AI时遭遇严重崩溃,面对AI代码生成的失控感和同行成功的压力,同时因学习心理学而无法再通过"压榨自己"换取成功。在最痛苦之际,他创建了名为"LifeGame"的自我安抚系统,将困扰转化为游戏任…...
告别手动复制!Mac版PowerPoint备注导出神器:自定义AppleScript脚本全解析
Mac版PowerPoint备注导出神器:AppleScript脚本开发实战指南 每次在会议前整理PPT备注时,你是否也厌倦了手动复制粘贴的繁琐操作?作为一位长期使用Mac和PowerPoint的资深用户,我深刻理解这种效率低下的痛苦。本文将带你深入探索如何…...
5步掌握戴森球计划工厂蓝图:从新手到自动化大师的实战指南
5步掌握戴森球计划工厂蓝图:从新手到自动化大师的实战指南 【免费下载链接】FactoryBluePrints 游戏戴森球计划的**工厂**蓝图仓库 项目地址: https://gitcode.com/GitHub_Trending/fa/FactoryBluePrints 戴森球计划工厂蓝图是构建高效星际生产体系的关键工具…...
