前言源码来源xilem/examples/flex.rs适配版本Xilem 0.4 / Masonry 0.4一、官方完整源码// Copyright 2024 the Xilem Authors// SPDX-License-Identifier: Apache-2.0//! Flex properties can be set in Xilem.usemasonry::layout::AsUnit;usemasonry::properties::types::{CrossAxisAlignment,MainAxisAlignment};usewinit::error::EventLoopError;usexilem::style::Style;usexilem::view::{FlexExtas_,FlexSpacer,Label,button,flex_row,label,sized_box};usexilem::{EventLoop,TextAlign,WidgetView,WindowOptions,Xilem};/// A component to make a bigger than usual button.fnbig_buttonF:Fn(muti32)SendSyncstatic(label:implIntoLabel,callback:F,)-implWidgetViewi32{sized_box(button(label.into(),callback)).dims(40.px())}fnapp_logic(data:muti32)-implWidgetViewi32use{// This is the flex view, alternatives are flex_col or flex which allows dynamically switching the axisflex_row((FlexSpacer::Flex(1.0),big_button(-,|data|{*data-1;}),FlexSpacer::Fixed(30.px()),label(format!(count: {data})).text_size(32.).text_alignment(TextAlign::Center).flex(5.0),FlexSpacer::Fixed(30.px()),big_button(,|data|{*data1;}),FlexSpacer::Flex(1.0),)).cross_axis_alignment(CrossAxisAlignment::Center).main_axis_alignment(MainAxisAlignment::Center)}fnmain()-Result(),EventLoopError{letappXilem::new_simple(0,app_logic,WindowOptions::new(Centered Flex));app.run_in(EventLoop::with_user_event())?;Ok(())}二、程序核心功能本示例演示 Flex弹性布局横向布局 flex_row 实现一个居中计数器界面从左到右弹性空白区域 → 减号按钮 → 固定间距 → 计数字文本 → 固定间距 → 加号按钮 → 弹性空白区域点击 - / 修改计数器数值状态是简单i32重点演示两种间距FlexSpacer弹性占位、固定像素间距以及子元素 .flex() 权重分配核心概念flex_row 水平方向弹性布局主轴水平交叉轴垂直flex_col 垂直方向弹性布局主轴垂直交叉轴水平FlexSpacer 弹性空白占位组件用于分配空白空间三、逐模块深度解析1. big_button 封装复用组件fnbig_buttonF:Fn(muti32)SendSyncstatic(label:implIntoLabel,callback:F,)-implWidgetViewi32{sized_box(button(label.into(),callback)).dims(40.px())}泛型函数接收标签文本、点击回调sized_box 固定尺寸容器 .dims(40.px()) 宽高都设置为40px正方形按钮Xilem组件就是普通Rust函数无宏直接复用2. app_logic 视图构建 flex_rowflex_row((FlexSpacer::Flex(1.0),big_button(-,|data|*data-1),FlexSpacer::Fixed(30.px()),label(format!(count: {data})).text_size(32.).text_alignment(TextAlign::Center).flex(5.0),FlexSpacer::Fixed(30.px()),big_button(,|data|*data1),FlexSpacer::Flex(1.0),)).cross_axis_alignment(CrossAxisAlignment::Center).main_axis_alignment(MainAxisAlignment::Center)FlexSpacer 两种类型FlexSpacer::Flex(1.0) 弹性占位权重1自动瓜分容器剩余空白。左右两边各放一份会把中间内容整体挤到窗口水平居中。FlexSpacer::Fixed(30.px()) 固定像素占位固定30像素间距不会随窗口缩放变化用来隔开按钮和文字。label文本的 .flex(5.0)给标签设置flex权重5。如果窗口变宽这个文本区域会分到5份弹性空间相比Spacer的权重1它能拿到更多可用宽度。text_size(32.) 文字字号32text_alignment(TextAlign::Center) 文本在自身容器内部居中布局对齐设置.main_axis_alignment(MainAxisAlignment::Center) 主轴水平居中.cross_axis_alignment(CrossAxisAlignment::Center) 交叉轴垂直居中flex_row主轴水平交叉轴垂直flex_col主轴垂直交叉轴水平。3. 状态与数据流状态极简 i32 初始值0直接传给 new_simple点击按钮闭包直接修改 mut i32 状态状态变更 → app_logic重新执行生成新视图树Xilem做diff增量更新UI4. main入口letappXilem::new_simple(0,app_logic,WindowOptions::new(Centered Flex));初始状态直接写字面量 0 不需要复杂结构体简单状态可以直接使用基础类型窗口标题 Centered Flex四、生产拓展代码拓展1改成flex_col垂直布局版本fnapp_logic(data:muti32)-implWidgetViewi32use{flex_col((FlexSpacer::Flex(1.0),big_button(-,|data|*data-1),FlexSpacer::Fixed(20.px()),label(format!(count: {data})).text_size(32.).text_alignment(TextAlign::Center).flex(5.0),FlexSpacer::Fixed(20.px()),big_button(,|data|*data1),FlexSpacer::Flex(1.0),)).cross_axis_alignment(CrossAxisAlignment::Center).main_axis_alignment(MainAxisAlignment::Center)}拓展2修改弹性权重文本占据更多空间label(format!(count: {data})).text_size(32.).text_alignment(TextAlign::Center).flex(10.0),// 权重改为10五、本课核心知识点总结flex_row 水平弹性布局 flex_col 垂直弹性布局主轴/交叉轴随布局方向改变。FlexSpacer 两种模式 Flex(权重) 弹性空白 Fixed(px) 固定像素间距。子视图调用 .flex(权重) 设置元素在flex容器内分配剩余空间的比例。MainAxisAlignment 主轴对齐 CrossAxisAlignment 交叉轴对齐。Xilem简单状态不需要结构体可以直接使用基础类型i32作为全局状态。sized_box 固定宽高的容器用来约束组件尺寸。六、课后习题练习1 填空flex_row 的主轴方向是 ______交叉轴方向是 ______。FlexSpacer::Flex(1.0) 代表 ______ 空白占位。设置子元素弹性权重调用视图的 ____ 方法。CrossAxisAlignment::Center 是在 ____ 轴方向居中。填空题参考答案水平、垂直弹性按权重分配剩余空间.flex()交叉练习2 判断FlexSpacer::Fixed(30.px()) 会随窗口大小自动拉伸。❌错误flex_row 使用 MainAxisAlignment::Center 代表水平居中。✅正确Xilem状态必须用struct不能直接用i32。❌错误sized_box可以给组件设置固定宽高。✅正确练习3 简答题目FlexSpacer::Flex 和子视图调用 .flex() 的作用有什么异同参考答案相同都使用flex权重分配容器剩余空间。区别 FlexSpacer::Flex 是空白占位组件只用来撑开空白区域没有内容子视图调用 .flex(权重) 是让这个有UI内容的组件参与弹性空间分配组件本身会拉伸占用对应比例的空间。
