5 - 创建 ImageGrid

在上一步中,我们创建了一个 ImageRow 来显示一排图片,作为构建应用程序图片网格的一部分。

回顾一下,我们的图片网格结构如下:

  • 每张图片存储在一个 ImageItem 中。
  • 多个 ImageItem 横向排列在一个 ImageRow 中。
  • 多个 ImageRow 纵向排列在一个 ImageGrid 中。

在这一步中,我们将把多个 ImageRow 组合到一个 ImageGrid 中,以显示一个图片网格。ImageGrid 的代码与我们为 ImageRow 编写的代码非常相似,因此我们不会详细讲解。

注意:如果你不想手动输入代码,可以在这里找到本步骤的全部代码:https://github.com/makepad/image_viewer/tree/main/step_5

你将学到的内容

在这一步中,你将学习:

  • 如何垂直排列项目。

定义ImageGrid

让我们开始添加 ImageGrid 的定义。ImageGrid 负责垂直排列多个 ImageRow

app.rs 中,添加以下代码到 live design 块中,位于 ImageRow 定义之后:

1ImageGrid = {{ImageGrid}} {
2        <PortalList> {
3            flow: Down,
4            
5            ImageRow = <ImageRow> {}
6        }
7    }

ImageRow 一样,在 ImageGrid 中,我们使用 PortalList 来列出其行。唯一的区别是我们使用了 flow: Down,这确保其子项从上到下排列。

更新App

现在我们已经有了一个 ImageGrid,让我们更新 App 的定义,使其显示 ImageGrid 而不是 ImageRow

app.rs 中,将 live design 块中的 App 定义替换为下面这个新的定义:

1App = {{App}} {
2        ui: <Root> {
3            <Window> {
4                body = <View> {
5                    <ImageGrid> {}
6                }
7            }
8        }
9    }

增加rust代码

将下面的代码添加到 app.rs:

1#[derive(Live, LiveHook, Widget)]
2pub struct ImageGrid {
3    #[deref]
4    view: View,
5}
6
7impl Widget for ImageGrid {
8    fn draw_walk(
9        &mut self,
10        cx: &mut Cx2d,
11        scope: &mut Scope,
12        walk: Walk,
13    ) -> DrawStep {
14        while let Some(item) = self.view.draw_walk(cx, scope, walk).step() {
15            if let Some(mut list) = item.as_portal_list().borrow_mut() {
16                list.set_item_range(cx, 0, 3);
17                while let Some(row_idx) = list.next_visible_item(cx) {
18                    let row = list.item(cx, row_idx, live_id!(ImageRow));
19                    row.draw_all(cx, &mut Scope::empty());
20                }
21            }
22        }
23        DrawStep::done()
24    }
25
26    fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
27        self.view.handle_event(cx, event, scope)
28    }
29}

这段代码定义了 ImageGrid 结构体,并为其实现了 Widget trait。这段代码和我们之前为 ImageRow 结构体编写的代码非常相似,所以我们不会详细讲解。唯一的区别是,我们不是绘制 4 个 ImageItem,而是绘制了 3 个 ImageRow

检查我们现在的进度

让我们检查一下目前的进展。

确保你在你的包目录下,然后运行:

1cargo run --release

如果一切正常,屏幕上应该会出现一个包含占位图像网格的窗口:

下一步

在这一步中,我们创建了一个 ImageGrid 来显示图像网格。

我们现在已经有了一个图像网格的初始实现。虽然它仍然非常有限 —— 总是显示相同数量的行和每行相同数量的图像,而且只显示占位图像,但这已经是一个不错的开始!

在接下来的几步中,我们将去除这些限制,让图像网格变得更加动态。