Skip to content
On this page

绑定自定义布局

在Fyne应用程序中,每个Container使用简单的布局算法排列其子元素。Fyne定义了Fyne.io/Fyne/v2/layout包中可用的许多布局。如果您查看代码,就会发现它们都实现了Layout接口。

go
type Layout interface {
	Layout([]CanvasObject, Size)
	MinSize(objects []CanvasObject) Size
}

任何应用程序都可以提供自定义布局,以非标准方式排列小部件。为此,您需要在自己的代码中实现上面的接口。为了说明这一点,我们将创建一个新布局,该布局以对角线排列元素,并将其排列在容器的左下方

首先,我们将定义一个新的类型,对角线,并定义它的最小大小。为了计算它,我们只需将所有子元素的宽度和高度(指定为[]fyne.CanvasObject参数)添加到MinSize。

go
import "fyne.io/fyne/v2"

type diagonal struct {
}

func (d *diagonal) MinSize(objects []fyne.CanvasObject) fyne.Size {
	w, h := float32(0), float32(0)
	for _, o := range objects {
		childSize := o.MinSize()

		w += childSize.Width
		h += childSize.Height
	}
	return fyne.NewSize(w, h)
}

对于此类型,我们添加了一个Layout()函数,该函数应将所有指定对象移动到第二个参数中指定的fyne.Size中。

在我们的实现中,我们计算小部件的左上角(这是0 x参数,具有y位置,即容器的高度减去所有子项高度的总和)。从顶部位置开始,我们只需将每个项目的位置前移上一个子项目的大小。

go
func (d *diagonal) Layout(objects []fyne.CanvasObject, containerSize fyne.Size) {
	pos := fyne.NewPos(0, containerSize.Height - d.MinSize(objects).Height)
	for _, o := range objects {
		size := o.MinSize()
		o.Resize(size)
		o.Move(pos)

		pos = pos.Add(fyne.NewPos(size.Width, size.Height))
	}
}

这就是创建自定义布局的全部内容。现在代码已经全部编写完毕,我们可以将其用作container.New的布局参数。下面的代码设置了3个Label小部件,并将它们放置在具有新布局的容器中。如果您运行此应用程序,您将看到对角小部件排列,并且在调整窗口大小时,它们将与可用空间的左下角对齐。

go
package main

import (
	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/widget"
)

func main() {
	a := app.New()
	w := a.NewWindow("Diagonal")

	text1 := widget.NewLabel("topleft")
	text2 := widget.NewLabel("Middle Label")
	text3 := widget.NewLabel("bottomright")

	w.SetContent(container.New(&diagonal{}, text1, text2, text3))
	w.ShowAndRun()
}