01 · 类体系与模块分工

基线:MiCarSupport @ dev 52a51649(micarx 3.2.8)。 MAT = material/src/main/java/com/mi/car/material/slider/, ABW = androidbasewidget/src/main/java/micarx/androidbasewidget/, PREF = preference/src/main/java/micarx/preference/。

1. 全局地图:三套互不同源的滑块实现

flowchart TB
    subgraph MaterialFork["float 值域体系(fork 自 Google Material Slider)"]
        BaseSlider["BaseSlider&lt;S,L,T&gt; (abstract)<br/>MAT/BaseSlider.java:211<br/>3297 行,全部手势/绘制核心"]
        Slider["Slider<br/>MAT/Slider.java:50<br/>单值定版 + SliderAnimation"]
        IconSlider["IconSlider<br/>ABW/IconSlider.java:34<br/>thumb 文字/图标 + 自研按压动画"]
        PlayerProgressbar["PlayerProgressbar<br/>appcompat/.../player/PlayerProgressbar.java:21<br/>播放进度"]
    end

    subgraph SeekBarFamily["int progress 体系(原生 SeekBar 生态)"]
        AppCompatSeekBarX["micarx.appcompat.widget.AppCompatSeekBar<br/>MAT/micarx/appcompat/widget/AppCompatSeekBar.java:29<br/>主题 clip + 按压动画 + ignoreClick"]
        IconSeekBar["IconSeekBar<br/>ABW/IconSeekBar.java:35<br/>thumb 文字/图标 + 双组按压动画"]
        LegacySeekBar["ABW SeekBar (已废弃)<br/>ABW/SeekBar.java:15 @Deprecated<br/>零引用,仅画前导 icon"]
    end

    subgraph Vertical["垂直体系(独立自绘)"]
        VerticalSlider["VerticalSlider<br/>ABW/VerticalSlider.java:45<br/>extends View,拷贝 BaseSlider 骨架"]
    end

    BaseSlider -->|extends View| ViewA["android.view.View"]
    Slider --> BaseSlider
    IconSlider --> Slider
    PlayerProgressbar --> Slider
    AppCompatSeekBarX -->|extends| AndroidxSB["androidx.appcompat.widget.AppCompatSeekBar"]
    IconSeekBar --> AppCompatSeekBarX
    LegacySeekBar -->|extends(注意:不是 micarx 版)| AndroidxSB
    VerticalSlider -->|extends View(不继承 BaseSlider)| ViewB["android.view.View"]

    style BaseSlider fill:#ffe1e1
    style AppCompatSeekBarX fill:#ffe1e1
    style VerticalSlider fill:#e1f0ff

铁律:IconSlider 与 BaseSlider 是继承关系,不是包装;IconSeekBar 与 BaseSlider 族 零共享代码。两族的主题 delegate 也是两套独立接口(见 03 篇)。

2. 三模块分工

模块角色关键类特征
material基础滑杆 + 主题 delegate 接口BaseSlider/Slider、SliderThemeDelegate、SeekBarThemeDelegate、micarx AppCompatSeekBarfloat 值域、stepSize 吸附、TooltipDrawable label
androidbasewidget车机定制壳(thumb 文字/图标/按压动画)IconSlider、IconSeekBar、VerticalSlider、*IconSliderThemeDelegate在 material 之上加 thumb 内容绘制与 Folme 弹簧动画
preference设置项封装(Settings 未使用)SeekBarPreference、SliderPreference、SeekBarPreferenceCompat详见 05 篇

3. 选型矩阵(什么场景用哪个)

需求选型实证
纯滑杆(如播放进度)material SliderMiCarSettings micarMedia VideoPlayerActivity + exo_player_control_view.xml:91
thumb 带当前值/图标、两端文案、float 生态IconSlider能量回收/限速弹窗(Settings 经 MiCarIconSlider 包装)
同上但 int/SeekBar 生态IconSeekBar车门高度、音量(Settings 经 MiCarIconSeekBar 包装)
垂直调节(屏幕俯仰角)VerticalSlidercatalog VerticalSliderActivity;Settings 后屏角度
裸 SeekBar preference组件库 SeekBarPreference(绑框架 SeekBar)Settings 未使用,Settings 全部走自建 settingsBaseUi 体系

Settings 侧完整使用地图见 05 篇 §7。

4. 主题 delegate 策略模式总览

flowchart LR
    ThemeAttr["theme attr<br/>micarxThemeStyleName"] --> Factory["静态工厂 create()"]
    Factory --> Normal["NormalXxxThemeDelegate<br/>原样直通/no-op 为主"]
    Factory --> GT["GtXxxThemeDelegate<br/>竖条 thumb + 点击抑制 + 扩张动画"]
    Factory --> Ultra["UltraXxxThemeDelegate<br/>与 GT 逐行相同(预留独立演进)"]

    subgraph ThreeSets["三套独立 delegate 接口(互不继承)"]
        S1["SliderThemeDelegate (MAT)<br/>服务 BaseSlider/Slider"]
        S2["IconSliderThemeDelegate (ABW)<br/>服务 IconSlider"]
        S3["SeekBarThemeDelegate (MAT)<br/>服务 AppCompatSeekBar + IconSeekBar"]
        S4["VerticalSliderThemeDelegate (ABW)<br/>服务 VerticalSlider,仅 3 方法"]
    end

    Factory -.分派.-> ThreeSets
  • 主题来源:ThemeStyleUtil.getThemeNameFromAttr(context, micarxThemeStyleName) (BaseSlider.java:591-592、IconSlider 经 BaseSlider 构造、IconSeekBar.java:125、 VerticalSlider.java:152-156)。
  • 一个 IconSlider 实例内部同时存在两个 delegate:BaseSlider 构造创建的 mThemeDelegate(SliderThemeDelegate,管轨道几何/padding)+ IconSlider 自建的 mIconSliderThemeDelegate(IconSliderThemeDelegate,管图标/文字/按压/点击抑制)。 IconSeekBar 同理有两份 SeekBarThemeDelegate 实例(父类 AppCompatSeekBar:87 一份, IconSeekBar:125 一份,遮蔽父类字段,各管各的绘制)。
  • GT 与 Ultra 的四个 delegate 实现均逐行相同,注释声明 “Separate from GtXxx for independent extensibility”(如 UltraSliderThemeDelegate.java:9-13)——改 GT 行为时 务必检查 Ultra 是否要同步。

5. 值模型差异(两个世界的分水岭)

维度Slider 族(BaseSlider)SeekBar 族(IconSeekBar)
值类型float values[](多 thumb 能力,单 thumb 取 [0])int progress(ProgressBar)
范围valueFrom/valueTomin/max(IconSeekBar 校验 max≠min 否则 IAE,IconSeekBar.java:212-216)
离散化stepSize>0 时 snapPosition 档位吸附(BaseSlider:2335-2342)原生 SeekBar 天然 int 取整
程序设值回调dispatchOnChangedProgrammatically,fromUser=false(BaseSlider:2642-2648)框架语义
触摸回调onValueChange(Slider, float, fromUser=true)OnSeekBarChangeListener(框架)
程序设值校验setValue 不校验,非法值在下次 onDraw 抛 ISE(BaseSlider:741-752)框架 clamp

6. 本仓库内的死/旧代码(排障时别被骗)

  • ABW/SeekBar.java:@Deprecated、全仓零引用,纯历史遗留。
  • BaseSlider.mSeekBarLocation(:326):声明后从未使用(死字段);同名活字段在 micarx AppCompatSeekBar(:34,参与 computeTouchOffset)。grep 时勿混淆。
  • BaseSlider.mPressThumbEnlargeEnable(:346):读出后无消费方,用途未确认。
  • SliderThemeDelegate.adjustActiveTrackEndPixel:BaseSlider 内无调用,唯一消费方是 PlayerProgressbar.java:112。