diff --git a/crates/app-iced/src/components/inputs/menu.rs b/crates/app-iced/src/components/inputs/menu.rs index d4acbeb..9dc7050 100644 --- a/crates/app-iced/src/components/inputs/menu.rs +++ b/crates/app-iced/src/components/inputs/menu.rs @@ -287,6 +287,10 @@ fn item_row<'a, M: Clone + 'a>( } row = row.push(label); if let Some(kind) = item.trailing { + // **撑开**:label 与 trailing 之间插一个水平 Fill,trailing 才会被推到行右内边距上 + // (M3 里 trailing 是「快捷键 / 子菜单箭头 / 勾」,必须在一列菜单里成一条竖线)。 + // 没有 trailing 时**不插**:label 仍在左边,不会被居中或右对齐。 + row = row.push(iced::widget::space::horizontal()); row = row.push(layout::fixed( geometry.icon, geometry.icon, @@ -294,6 +298,13 @@ fn item_row<'a, M: Clone + 'a>( )); } + // 行必须撑满 item 宽度:上面的 Fill 空间要有宽度可撑(Q8 的教训:撑开靠容器,不靠子元素)。 + // 顺带把内容垂直居中——`button` 只把内容放在 padding-box 的左上角。 + let content = iced::widget::container(row) + .width(Length::Fill) + .height(Length::Fill) + .align_y(Alignment::Center); + let selected = item.selected; let style = move |_theme: &iced::Theme, status: button::Status| { let state = forced.unwrap_or_else(|| Interaction::from_status(status)); @@ -311,7 +322,7 @@ fn item_row<'a, M: Clone + 'a>( }; let inset = ui.space(Space::X1); - let button = button(row) + let button = button(content) .width(Length::Fill) .height(Length::Fixed(geometry.item_height)) .padding(Padding { diff --git a/crates/app-iced/src/components/inputs/probe/menu.rs b/crates/app-iced/src/components/inputs/probe/menu.rs index 8b6434c..b6ccdd0 100644 --- a/crates/app-iced/src/components/inputs/probe/menu.rs +++ b/crates/app-iced/src/components/inputs/probe/menu.rs @@ -75,5 +75,28 @@ fn menu_container_items_and_divider() { (0.6..=1.4).contains(&ink), "8.x 分组分隔线应 1dp `OutlineVariant`:实测墨量 {ink:.2}" ); + + // trailing 槽位必须靠到**行右内边距**上(视觉 r5 P1:早先它紧贴 label 右边)。 + // + // 位置公式:item 右缘 = menu_right − 4(选中指示器内缩);button 内容右缘 = item 右缘 − + // (pad_h − inset) = menu_right − 12;trailing 图标盒 24 的**墨迹**再内缩 k(`Check` 字形 + // 在 24 viewBox 里右边界 ≈ 5,与 leading 图标「可视边 12、墨迹 16」同一口径)。 + // 所以墨迹右缘 ≈ menu_right − 17。变异(去掉撑开的 Fill)会让它贴着 label ⇒ 差 ~120。 + let trailing_ink_color = rgb(ui.color(Role::OnSecondaryContainer)); + let mut trailing_right = 0usize; + for y in selected_box.top..=selected_box.bottom { + for x in selected_box.left..=selected_box.right { + if matches(shot.at(x, y), trailing_ink_color) { + trailing_right = trailing_right.max(x); + } + } + } + let trailing_offset = menu_right - trailing_right; + assert!( + (16..=18).contains(&trailing_offset), + "8.6/trailing:带 trailing 的项,其 trailing 墨迹右缘应在 item 右内边距上\ + (menu_right − 17,允许 ±1):实测 menu_right={menu_right}、墨迹右缘={trailing_right}\ + ⇒ 偏 {trailing_offset}(贴 label 时会是 ~120)" + ); } }