Android SeekBar深度定制:从原理到实践,实现高度与样式精准控制
1. 从“能用”到“好用”SeekBar的深度实践与高度定制在Android应用开发里处理用户交互式进度调节的场景SeekBar几乎是绕不开的组件。无论是音乐播放器的音量滑块、视频播放的进度拖拽还是图片编辑器的参数微调你都能看到它的身影。表面上看SeekBar就是一个带滑块的进度条android:progress属性一设监听器一加功能就实现了。但真到了UI需要高度定制尤其是产品经理拿着设计稿指着那个“又细又精致”的进度条问你“这个高度和样式能实现吗”的时候很多开发者才会意识到事情没那么简单。默认的SeekBar样式往往粗犷且与设计语言格格不入而直接调整layout_height属性你可能发现滑块Thumb的位置诡异、触摸区域错位进度条ProgressDrawable的绘制也不对劲。这背后涉及的是Android视图测量Measure、布局Layout、绘制Draw的完整流程以及SeekBar对进度条和滑块样式的特殊管理机制。今天我们就来彻底拆解SeekBar不仅让你知道怎么“设置高度”更让你明白为什么这么设置以及如何优雅地实现任何自定义设计。2. SeekBar核心架构与样式系统解析要解决高度设置问题必须先理解SeekBar的构成。SeekBar继承自AbsSeekBar而AbsSeekBar又继承自ProgressBar。因此SeekBar的本质是一个特殊的进度条它增加了可拖动的滑块Thumb和对应的触摸交互逻辑。其视觉上主要由三个核心部分构成背景轨道Track进度条的底层背景通常是一个长条形的Drawable。进度条Progress覆盖在背景轨道上表示当前进度的部分也是一个Drawable。在SeekBar中背景轨道和进度条通常被合并定义在一个LayerDrawable中也就是我们常通过android:progressDrawable属性设置的。滑块Thumb用户可拖动的圆形或任意形状指示器通过android:thumb属性设置。系统默认会为这三个部分提供一套样式。当你直接在布局文件中设置android:layout_height为一个较大值时SeekBar的整体高度确实会增加但进度条ProgressDrawable和滑块Thumb的绘制很可能不会按你预期的方式适配这个新高度从而导致视觉错乱。2.1 为什么直接设置layout_height会出问题这源于SeekBar更准确地说是其父类ProgressBar对progressDrawable的默认处理逻辑。系统默认的进度条Drawable例如android:drawable/progress_horizontal自身有固定的内在高度Intrinsic Height。当SeekBar的测量高度大于这个内在高度时默认的绘制行为可能不会将其拉伸Stretch以填满整个SeekBar视图区域而是可能居中或从顶部开始绘制导致进度条看起来还是原来的粗细只是周围多了空白。更棘手的是滑块Thumb的垂直居中计算。滑块的默认垂直位置通常是基于进度条Drawable的绘制区域来计算的而非整个SeekBar视图的高度。当进度条没有正确拉伸时滑块的垂直位置就会偏离你的预期。2.2 SeekBar样式定制的正确入口LayerDrawable与NinePatchAndroid为这类可缩放控件样式推荐使用NinePatch图片.9.png或XML定义的ShapeDrawable、LayerDrawable。对于SeekBar我们通常需要自定义一个progressDrawable它是一个layer-list里面至少包含两个item一个代表背景android:idandroid:id/background一个代表进度android:idandroid:id/progress。关键在于要使进度条的高度随SeekBar变化你必须确保这个progressDrawable中的Drawable本身是可拉伸的。对于图片使用NinePatch并定义好可拉伸区域是最佳实践。对于纯色或简单形状使用shape标签并在其中定义size或依赖父容器缩放属性则更为灵活。3. 实战一步步实现精确高度与样式的SeekBar理解了原理我们进入实战环节。假设设计稿要求一个高度为4dp的细进度条滑块直径为24dp进度条颜色为蓝色背景为浅灰色。3.1 第一步创建自定义进度条Drawable我们完全使用XML来定义这样无需切图且适配性最好。在res/drawable目录下创建seekbar_custom_track.xml。?xml version1.0 encodingutf-8? layer-list xmlns:androidhttp://schemas.android.com/apk/res/android !-- 背景轨道 (id必须是background) -- item android:idandroid:id/background shape corners android:radius2dp / !-- 圆角半径通常为高度的一半 -- solid android:color#E0E0E0 / !-- 浅灰色背景 -- size android:height4dp / !-- 核心固定高度为4dp -- /shape /item !-- 二级进度如果有需要例如缓冲进度 -- !-- item android:idandroid:id/secondaryProgress ... /item -- !-- 前景进度条 (id必须是progress) -- item android:idandroid:id/progress clip shape corners android:radius2dp / solid android:color#2196F3 / !-- 蓝色进度 -- size android:height4dp / !-- 高度必须与背景一致 -- /shape /clip /item /layer-list关键点解析size android:height4dp这是控制进度条视觉高度的核心。它直接定义了ShapeDrawable的固有高度。无论SeekBar的layout_height设为多少这个Shape都将以4dp的高度进行绘制。clip标签包裹progress的shape。这是必须的因为AbsSeekBar会使用这个ClipDrawable来根据当前进度值裁剪进度条的显示范围。没有clip进度条将不会随滑块移动而增长/缩短。corners设置圆角让进度条两端呈现圆形。半径通常设置为高度4dp的一半即2dp这样两端就是完美的半圆形。3.2 第二步创建自定义滑块ThumbDrawable在res/drawable目录下创建seekbar_custom_thumb.xml。?xml version1.0 encodingutf-8? shape xmlns:androidhttp://schemas.android.com/apk/res/android android:shapeoval !-- 圆形滑块 -- solid android:color#2196F3 / !-- 与进度条同色 -- stroke android:width2dp android:color#FFFFFF / !-- 白色描边增加辨识度 -- size android:width24dp android:height24dp / !-- 固定尺寸为24dp -- /shape也可以使用一个Selector来实现按下状态的效果?xml version1.0 encodingutf-8? selector xmlns:androidhttp://schemas.android.com/apk/res/android item android:state_pressedtrue shape android:shapeoval solid android:color#1976D2 / !-- 按下时深蓝色 -- stroke android:width2dp android:color#FFFFFF/ size android:width28dp android:height28dp/ !-- 按下时可稍大 -- /shape /item item shape android:shapeoval solid android:color#2196F3 / stroke android:width2dp android:color#FFFFFF/ size android:width24dp android:height24dp/ /shape /item /selector3.3 第三步在布局文件中应用自定义样式现在在布局XML中使用这些自定义Drawable。SeekBar android:idid/seekBar android:layout_widthmatch_parent android:layout_heightwrap_content !-- 或一个足够大的值如48dp -- android:max100 android:progress50 android:progressDrawabledrawable/seekbar_custom_track android:thumbdrawable/seekbar_custom_thumb android:minHeight24dp !-- 重要确保触摸区域高度不小于滑块直径 -- android:maxHeight24dp android:paddingStart12dp !-- 重要为滑块留出边距防止滑块溢出视图边界 -- android:paddingEnd12dp/参数与属性深度解读android:layout_heightwrap_content这是最推荐的做法。SeekBar会根据其内容主要是progressDrawable和thumb所需的高度加上minHeight/maxHeight以及padding的约束来自动计算自身高度。系统会取thumb的高度、progressDrawable的高度以及minHeight三者中的最大值。android:minHeight与android:maxHeight这两个属性是控制SeekBar触摸区域高度的关键。即使你的进度条只有4dp高但滑块有24dp用户很难精准点到4dp高的细条。将minHeight和maxHeight设置为不小于滑块直径的值如24dp可以确保整个SeekBar视图的触摸响应区域足够大提升用户体验。minHeight和maxHeight设置相同值可以固定触摸区域高度。android:paddingStart与android:paddingEnd这是极易忽略但至关重要的设置滑块Drawable是有宽度的24dp。如果不设置内边距当滑块拖到最左或最右端时滑块的边缘会超出进度条的起点和终点甚至可能被父布局裁剪。通常左右内边距应设置为滑块半径即thumb宽度 / 2。这样能保证滑块的圆心与进度条的起点和终点对齐视觉和交互都最准确。android:splitTrack这个属性默认为true意味着进度条会在滑块下方被“分开”绘制。如果你自定义的进度条样式在滑块处有特殊效果可以设置为false。在我们的场景中通常保持默认即可。3.4 第四步在代码中设置监听与逻辑样式搞定后功能逻辑就很简单了。// Kotlin 示例 binding.seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { // 进度变化时回调fromUser表示是否由用户拖动触发 if (fromUser) { Log.d(SeekBar, 用户拖动至: $progress) // 更新UI如显示当前进度百分比 binding.tvProgress.text $progress% } } override fun onStartTrackingTouch(seekBar: SeekBar) { // 用户开始触摸滑块时调用 Log.d(SeekBar, 开始拖动) // 可以在这里做一些视觉反馈如放大滑块 } override fun onStopTrackingTouch(seekBar: SeekBar) { // 用户停止触摸滑块时调用 Log.d(SeekBar, 停止拖动最终值: ${seekBar.progress}) // 可以在这里提交最终值如调整音量、保存设置等 applyVolume(seekBar.progress) } }) // 动态设置进度例如来自网络加载 binding.seekBar.progress calculatedProgress // 获取SeekBar当前进度 val currentProgress binding.seekBar.progress4. 高级技巧与疑难杂症排查即使按照上述步骤操作你可能还是会遇到一些奇怪的问题。下面是我在实际项目中踩过坑后总结的经验。4.1 进度条高度“不听话”的几种情况与解决方案问题1设置了自定义progressDrawable但高度看起来还是比4dp粗。排查检查自定义的Drawable XML中是否在shape里明确使用了size android:height4dp。如果没用sizeShapeDrawable可能会尝试拉伸填充。排查检查是否在代码中或通过主题Theme又设置了其他的进度条样式覆盖了你的自定义样式。技巧给你的进度条Shape加一个临时性的stroke边框看看它的实际绘制边界到底在哪这是一个非常有效的调试手段。问题2滑块Thumb没有垂直居中偏上或偏下。原因这通常是因为SeekBar的layout_height、minHeight、progressDrawable的实际绘制高度以及thumb的高度这几者之间的关系不协调。滑块垂直居中的基准线可能是progressDrawable的绘制区域。解决方案确保你的progressDrawable背景和进度在视觉上是垂直居中的。一个更稳健的方法是将SeekBar的layout_height设为wrap_content并设置一个明确的minHeight比如等于滑块高度。然后确保你的自定义progressDrawable中的shape不设置size的height或者将其height设置为match_parent但XML中不支持而是通过SeekBar的layout_height来控制。实际上更常见的做法是接受进度条在垂直方向上的位置通过调整progressDrawable中shape的padding或使用inset包裹来微调其在轨道内的垂直位置。!-- 微调进度条在轨道内的垂直位置示例 -- item android:idandroid:id/progress clip inset android:insetTop2dp android:insetBottom2dp shape corners android:radius1dp/ solid android:color#2196F3/ /shape /inset /clip /item这样进度条会在轨道内上下各留出2dp的空白相当于实现了垂直方向的对齐调整。4.2 触摸灵敏度与滑块“跳动”问题问题用户拖动时滑块会“跳”到触摸点而不是从滑块当前位置开始平滑跟随。原因这是SeekBar的默认行为android:thumbOffset为0且默认触摸模式。当你触摸滑块轨道ThumbTrack的任意位置时SeekBar会尝试将进度立即设置到该点。解决方案如果你希望只有触摸并拖动滑块本身时才改变进度而点击轨道是跳转到该位置这是默认且合理的行为。若想改变可能需要继承SeekBar重写onTouchEvent但这会破坏标准交互需谨慎。通常我们接受这个默认行为因为它符合大多数用户对进度条控件的预期。4.3 在RecyclerView或列表中使用SeekBar的注意事项在可滚动的列表中每个Item持有一个SeekBar时需要特别注意视图复用带来的状态错乱问题。坑点当用户拖动某个Item中的SeekBar后滑动列表被复用的另一个Item中的SeekBar可能自动显示了之前设置的进度值。解决方案在onBindViewHolder中必须为SeekBar重新设置进度值并且最好在设置值之前先移除旧的监听器防止错误回调设置完值后再添加新的监听器。override fun onBindViewHolder(holder: ViewHolder, position: Int) { val item dataList[position] // 先移除旧的监听器避免错乱 holder.seekBar.setOnSeekBarChangeListener(null) // 设置进度值 holder.seekBar.progress item.currentProgress // 设置新的监听器 holder.seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { // ... 监听器实现记得更新数据源item.currentProgress }) // 其他UI绑定... }4.4 性能考量避免在onProgressChanged中执行重操作onProgressChanged回调的频率非常高用户快速拖动时可能每毫秒触发多次。重要提示绝对不要在onProgressChanged中执行网络请求、复杂的数据库操作、频繁的视图布局更新如修改其他View的LayoutParams等重量级操作。这会导致UI卡顿拖动不跟手。正确做法对于实时性要求高的反馈如更新一个TextView显示当前数值这是可以的。对于需要提交的最终操作如调整音量、保存设置应该在onStopTrackingTouch中执行。如果需要在拖动过程中进行一些计算可以考虑使用debounce或throttle操作符借助RxJava或Kotlin Flow来降低回调频率。5. 超越基础仿主流应用SeekBar样式实战让我们挑战一个更复杂的设计仿造某音乐App的播放进度条它具有以下特征极细的灰色背景轨道播放进度为蓝色缓冲进度为浅蓝色且三种进度条高度各不相同缓冲进度最粗播放进度次之背景最细滑块是一个带有阴影的圆形。这个需求的关键在于自定义一个更复杂的progressDrawable它需要包含三个图层背景、二级进度缓冲、主进度。seekbar_music_style.xml:layer-list xmlns:androidhttp://schemas.android.com/apk/res/android !-- 背景轨道 (最细) -- item android:idandroid:id/background shape solid android:color#333333 / size android:height2dp / !-- 高度2dp -- corners android:radius1dp / /shape /item !-- 缓冲进度 (最粗) -- item android:idandroid:id/secondaryProgress clip shape solid android:color#6699CC / !-- 浅蓝色 -- size android:height4dp / !-- 高度4dp -- corners android:radius2dp / /shape /clip /item !-- 播放进度 (中等) -- item android:idandroid:id/progress clip shape solid android:color#2196F3 / !-- 蓝色 -- size android:height3dp / !-- 高度3dp -- corners android:radius1.5dp / /shape /clip /item /layer-list布局中使用SeekBar android:layout_widthmatch_parent android:layout_heightwrap_content android:maxHeight48dp android:minHeight48dp android:paddingStart24dp android:paddingEnd24dp android:progressDrawabledrawable/seekbar_music_style android:thumbdrawable/thumb_with_shadow !-- 一个带阴影的圆形图片或XML -- android:splitTrackfalse/ !-- 这里设为false让进度条在滑块下不被“切开”视觉效果更连贯 --实现要点图层顺序layer-list中的item是叠放的后定义的在上层。所以顺序是背景在下然后是二级进度最后是主进度。这样主进度才能覆盖在二级进度之上。高度差异通过为每个shape设置不同的size android:height来实现。为了让不同高度的进度条视觉上居中你可能需要像前面提到的使用inset或通过精确计算corners的半径和size的高度来手动调整。splitTrack属性在这个设计中我们可能希望滑块下方的进度条是连续的所以将android:splitTrack设置为false。滑块阴影thumb_with_shadow可以是一个带阴影的PNG图片也可以使用LayerDrawable或支持elevation的View但SeekBar的thumb是Drawable不支持elevation。更高级的做法是自定义SeekBar在onDraw方法中为滑块绘制阴影。经过这样一番从原理到实战从基础到进阶的梳理相信你再面对任何SeekBar的定制需求都能游刃有余。核心记住三点一是理解其由progressDrawable和thumb构成的样式系统二是通过size、padding和minHeight协同控制尺寸与触摸区域三是在复杂交互场景如列表中妥善处理状态与监听器。把这些搞透进度条就不再是那个“熟悉的陌生人”而会成为你手中实现精致交互的利器。

相关新闻

STM32开发环境搭建:从零配置VSCode+GCC+OpenOCD+STM32CubeMX

STM32开发环境搭建:从零配置VSCode+GCC+OpenOCD+STM32CubeMX

1. 项目概述:为什么STM32环境配置是第一个“大坑”刚接触STM32的朋友,十有八九会卡在开发环境配置这一步。这感觉就像拿到一把精密的瑞士军刀,却发现没有开刃的工具,空有想法却无从下手。我见过太多人,兴致勃勃地买了第…

2026/10/12 12:07:52 阅读更多 →
通义千问Qwen模型本地部署实战:从LM Studio到LoRA微调全指南

通义千问Qwen模型本地部署实战:从LM Studio到LoRA微调全指南

通义千问(Qwen)系列模型在开源大模型领域一直保持着高频更新和强大的竞争力。今天,我们聚焦于其最新动态: Qwen Live 的正式上线以及即将到来的 EP2 直播 。这不仅仅是一个简单的直播预告,更标志着通义千问在模型部…

2026/10/12 22:26:43 阅读更多 →
TelcoAgent-Bench:电信多语言AI智能体基准测试框架解析与实践

TelcoAgent-Bench:电信多语言AI智能体基准测试框架解析与实践

1. 项目概述:为什么电信行业需要一个多语言AI智能体基准? 如果你在电信行业或者AI应用开发领域待过一段时间,肯定会发现一个现象:关于“AI智能体”的讨论热火朝天,各种模型和框架层出不穷,但当你真的想把一…

2026/10/2 2:05:22 阅读更多 →

最新新闻

面向JSON半结构化数据的字段级加密实践:以安当DBG看嵌套脱敏与函数下推优化

面向JSON半结构化数据的字段级加密实践:以安当DBG看嵌套脱敏与函数下推优化

在关系型数据库占据主流的年代,数据脱敏与加密的落点相对清晰:列是确定的,类型是可枚举的,规则可以按表结构静态下发。但当业务进入图库、文档库与宽表混合存储的阶段,数据形态发生了根本变化。一个客户档案可能被存成…

2026/10/12 22:25:51 阅读更多 →
面向HTAP与读写分离场景的透明数据加密一致性工程:安当TDE在列存副本中的落地拆解

面向HTAP与读写分离场景的透明数据加密一致性工程:安当TDE在列存副本中的落地拆解

一、背景:HTAP 与读写分离为什么让加密变难 近些年,混合事务与分析处理(HTAP)架构在金融、电信与政企核心系统中普及。这类架构的核心特征是:同一份业务数据既要支撑高并发联机事务,又要支撑实时列式分析。…

2026/10/12 22:25:44 阅读更多 →
生物化学实验实战手册:蛋白质定量、电泳与酶动力学要点解析

生物化学实验实战手册:蛋白质定量、电泳与酶动力学要点解析

1. 为什么写这篇“生物化学”实验笔记生物化学这四个字,对刚入门的同学来说往往等于一本八百页的砖头教材,一堆又长又难记的代谢通路,还有动不动就“考前背到凌晨三点”的恐惧。但等你真正走进实验室,你会发现它其实是一门典型的“动手学科”——所有的理论最后都要落到离心管、…

2026/10/12 22:25:42 阅读更多 →
B端产品经理方法论:从业务梳理到汽配商城运营的完整指南

B端产品经理方法论:从业务梳理到汽配商城运营的完整指南

简介:面向B端产品经理的系统化方法论文档,适合从事企业级产品设计、业务梳理、产品规划,或从C端转岗B端的产品从业者阅读。正文从B端业务梳理入手,依次展开产品设计、产品管理和运营策略四大部分,具体涵盖行业调研、UM…

2026/10/12 22:25:36 阅读更多 →
酒店评论中文情感分析系统实战:数据清洗、机器学习建模与避坑指南

酒店评论中文情感分析系统实战:数据清洗、机器学习建模与避坑指南

简介:这是一套使用Python开发的酒店评论中文情感分析系统完整项目,面向计算机相关专业学生的毕业设计、课程设计及实战进阶。项目以酒店评论正负语料为基础,覆盖中文分词、去停用词、特征提取与机器学习建模等环节,实现情感倾向自…

2026/10/12 22:25:19 阅读更多 →
多智能体强化学习框架PyMARL:从架构到实战全解析

多智能体强化学习框架PyMARL:从架构到实战全解析

简介:PyMARL是一个基于PyTorch实现的深度多智能体强化学习框架,面向需要处理多智能体协作、竞争与博弈问题的学习者和研究者,内置多种主流算法,并以《星际争霸II》的SMAC作为标准实验场景。这份压缩包共包含52个文件,以…

2026/10/12 22:24:06 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →