布局 Builder
布局 Builder 用来在创建控件时配置显示方式、尺寸、间距、定位、Flex/Grid 等布局属性。基本写法是在控件后调用 .layout(|layout| { ... }),在闭包里连续调用布局方法,最后返回修改后的 layout。
基本写法
导入 LayoutBuilder 后,所有控件都可以调用 .layout(...)。还要导入 LayoutResolverExt,这样闭包里的 layout 才能使用 display、size、flex_grow 等布局方法。
下面的示例使用了 flex 相关类型,默认你已经启用 layout-flex feature。
use flor::taffy::{Dimension, Display, FlexDirection, LengthPercentage, Size};
use flor::view::builder::LayoutBuilder;
use flor::view::resolver::{LayoutResolverExt, Unit};
use flor::views;
use flor_lys::div::div;
use flor_lys::label::label;
let panel = div(views![label("内容")])
.layout(|layout| {
layout
.display(Display::Flex)
.flex_direction(FlexDirection::Column)
.size(
Size {
width: Dimension::Percent(1.0),
height: Dimension::Auto,
},
Size {
width: Unit::Px,
height: Unit::Px,
},
)
.gap(
Size {
width: LengthPercentage::Length(8.0),
height: LengthPercentage::Length(8.0),
},
Size {
width: Unit::Px,
height: Unit::Px,
},
)
});
闭包必须返回修改后的 layout。如果闭包捕获外部 signal 或变量,通常需要写成 move |layout| { ... }。
Flor 当前没有直接的 .width(100)、.height(40)、.x(10)、.y(20) 这类布局 builder 方法。尺寸、位置、边距都通过 size、inset、margin 等布局参数表达。
链式写法和 set 写法
大多数时候直接链式调用即可:
layout
.display(Display::Flex)
.flex_grow(1.0)
每个布局方法还有一个同名的 set_ 版本,例如 display(...) 对应 set_display(...),flex_grow(...) 对应 set_flex_grow(...)。这组 set_ 方法适合在 if、match 里分支修改同一个 layout。
这些方法由 Flor 自动生成,所以命名保持统一:布局项名用 snake_case 写成方法名,set_ 版本在前面加 set_。你按下面表格里的方法名使用即可。
use flor::taffy::Display;
use flor::view::builder::LayoutBuilder;
use flor::view::resolver::LayoutResolverExt;
use flor_lys::label::label;
let item = label("可切换")
.layout(move |mut layout| {
if true {
layout.set_display(Display::None);
} else {
layout.set_display(Display::Flex);
}
layout
});
set_ 方法主要用作控件开发时,解析原子类赋值时使用
状态布局
布局也可以按控件状态分别设置。调用 hover()、focus()、active() 等状态方法后,后续布局设置会写入对应状态;调用 normal() 或 base() 可以切回普通状态。
use flor::taffy::{Display, FlexDirection};
use flor::view::builder::LayoutBuilder;
use flor::view::resolver::LayoutResolverExt;
use flor::views;
use flor_lys::div::div;
use flor_lys::label::label;
let view = div(views![label("内容")])
.layout(|layout| {
layout
.display(Display::Flex)
.flex_direction(FlexDirection::Column)
.hover()
.display(Display::None)
});
单位参数怎么读
布局值主要来自 flor::taffy,单位类型来自 flor::view::resolver::Unit。
Unit 是长度单位。它只在布局值是 length 时参与换算,最终会解析成 px 交给布局系统。
凡是方法里同时出现布局值和 Unit,规则都是:布局值负责表达 length、percent 或 auto,Unit 只在值是 length 时决定如何解析这个数值。比如 Dimension::Length(12.0) 搭配 Unit::Px 表示 12px;Dimension::Percent(0.5) 和 Dimension::Auto 不依赖单位。
核心布局参数
这些方法不受 layout-flex、layout-grid、layout-block feature 影响。
示例:
use flor::taffy::{Dimension, LengthPercentageAuto, Rect, Size};
use flor::view::builder::LayoutBuilder;
use flor::view::resolver::{LayoutResolverExt, Unit};
use flor::views;
use flor_lys::div::div;
use flor_lys::label::label;
let view = div(views![label("内容")])
.layout(|layout| {
layout
.size(
Size {
width: Dimension::Length(320.0),
height: Dimension::Auto,
},
Size {
width: Unit::Px,
height: Unit::Px,
},
)
.margin(
Rect {
left: LengthPercentageAuto::Length(12.0),
right: LengthPercentageAuto::Length(12.0),
top: LengthPercentageAuto::Length(8.0),
bottom: LengthPercentageAuto::Length(8.0),
},
Rect {
left: Unit::Px,
right: Unit::Px,
top: Unit::Px,
bottom: Unit::Px,
},
)
});
Flex 和 Grid 共享参数
这些方法在启用 layout-flex 或 layout-grid 任意一个 feature 后可用。
Block 参数
这些方法需要启用 layout-block feature。
Flex 参数
这些方法需要启用 layout-flex feature。
示例:
use flor::taffy::{AlignItems, Display, FlexDirection, JustifyContent};
use flor::view::builder::LayoutBuilder;
use flor::view::resolver::LayoutResolverExt;
use flor::views;
use flor_lys::div::div;
use flor_lys::label::label;
let toolbar = div(views![label("左侧"), label("右侧")])
.layout(|layout| {
layout
.display(Display::Flex)
.flex_direction(FlexDirection::Row)
.align_items(AlignItems::Center)
.justify_content(JustifyContent::SpaceBetween)
});
Grid 参数
这些方法需要启用 layout-grid feature。
可用性速查