[GIO] 如何在Golang中使列表中的所有小部件大小一致?
[GIO] 如何在Golang中使列表中的所有小部件大小一致? 我有一个列表,里面包含一些小部件,我希望它们都具有相同的大小。在Gio中如何实现?
最小可验证示例(列表中的按钮):
package main
import (
"log"
"gioui.org/app"
"gioui.org/font/gofont"
"gioui.org/io/system"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/unit"
"gioui.org/widget"
"gioui.org/widget/material"
)
func main() {
go func() {
w := app.NewWindow(app.Title("MCVE"),
app.Size(unit.Dp(400), unit.Dp(400)))
if err := loop(w); err != nil {
log.Fatal(err)
}
}()
app.Main()
}
func loop(w *app.Window) error {
th := material.NewTheme(gofont.Collection())
labels := []string{"B1", "Button2"}
buttons := make([]widget.Clickable, len(labels))
widgets := make([]layout.Widget, len(labels))
var ops op.Ops
for {
e := <-w.Events()
switch e := e.(type) {
case system.DestroyEvent:
return e.Err
case system.FrameEvent:
gtx := layout.NewContext(&ops, e)
layout.Flex{Axis: layout.Vertical, Spacing: layout.SpaceAround}.Layout(gtx,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return layout.Center.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
list := &layout.List{
Axis: layout.Vertical,
Alignment: layout.Middle,
}
for i, label := range labels {
widgets[i] = material.Button(th, &buttons[i], label).Layout
}
return list.Layout(gtx, len(widgets), func(gtx layout.Context, i int) layout.Dimensions {
return layout.UniformInset(unit.Dp(0)).Layout(gtx, widgets[i])
})
})
}),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return layout.Center.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
return material.H6(th, "Info").Layout(gtx)
})
}),
)
e.Frame(gtx.Ops)
}
}
return nil
}
更多关于[GIO] 如何在Golang中使列表中的所有小部件大小一致?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
5 回复
你是说文档还不够清楚吗? 😂 … 开玩笑的
更多关于[GIO] 如何在Golang中使列表中的所有小部件大小一致?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我是在调侃文档……不是说你。我觉得文档有点让人沮丧。
我只是觉得它还有很多不足之处。我打算这几天好好深入研究一下这个库。
我理解笑话 😛
好吧,他们至少尝试提供了一些东西 - https://gioui.org/doc/architecture
在Gio中使列表中的所有小部件大小一致,可以通过layout.Stack或layout.Rigid约束来实现。以下是两种解决方案:
方案1:使用layout.Stack强制统一尺寸
// 在列表布局函数中修改
return list.Layout(gtx, len(widgets), func(gtx layout.Context, i int) layout.Dimensions {
// 使用Stack强制所有按钮具有相同的最小尺寸
return layout.Stack{}.Layout(gtx,
layout.Expanded(func(gtx layout.Context) layout.Dimensions {
// 设置最小约束
minSize := gtx.Constraints.Min
minSize.X = gtx.Constraints.Max.X // 使用最大可用宽度
minSize.Y = gtx.Dp(50) // 设置统一高度为50dp
gtx.Constraints.Min = minSize
return layout.UniformInset(unit.Dp(10)).Layout(gtx, widgets[i])
}),
)
})
方案2:使用自定义约束包装器
// 创建统一尺寸的包装函数
func uniformSize(gtx layout.Context, minWidth, minHeight unit.Dp, w layout.Widget) layout.Dimensions {
// 保存原始约束
original := gtx.Constraints
// 设置新的最小约束
gtx.Constraints.Min = layout.Pt(
gtx.Dp(minWidth),
gtx.Dp(minHeight),
)
// 执行小部件布局
dims := w(gtx)
// 恢复原始约束
gtx.Constraints = original
return dims
}
// 在列表中使用
return list.Layout(gtx, len(widgets), func(gtx layout.Context, i int) layout.Dimensions {
return uniformSize(gtx, 200, 50, func(gtx layout.Context) layout.Dimensions {
return layout.UniformInset(unit.Dp(10)).Layout(gtx, widgets[i])
})
})
方案3:使用layout.Rigid和统一约束(推荐)
// 修改列表布局部分
for i, label := range labels {
widgets[i] = func(btn *widget.Clickable, lbl string) layout.Widget {
return func(gtx layout.Context) layout.Dimensions {
// 设置统一的约束
gtx.Constraints.Min = layout.Pt(
gtx.Dp(150), // 统一最小宽度
gtx.Dp(40), // 统一最小高度
)
return material.Button(th, btn, lbl).Layout(gtx)
}
}(&buttons[i], label)
}
// 列表布局保持不变
return list.Layout(gtx, len(widgets), func(gtx layout.Context, i int) layout.Dimensions {
return layout.UniformInset(unit.Dp(5)).Layout(gtx, widgets[i])
})
完整修改后的示例
package main
import (
"log"
"gioui.org/app"
"gioui.org/font/gofont"
"gioui.org/io/system"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/unit"
"gioui.org/widget"
"gioui.org/widget/material"
)
func main() {
go func() {
w := app.NewWindow(app.Title("统一尺寸按钮"),
app.Size(unit.Dp(400), unit.Dp(400)))
if err := loop(w); err != nil {
log.Fatal(err)
}
}()
app.Main()
}
func loop(w *app.Window) error {
th := material.NewTheme(gofont.Collection())
labels := []string{"B1", "Button2", "按钮3", "Longer Button Text"}
buttons := make([]widget.Clickable, len(labels))
widgets := make([]layout.Widget, len(labels))
var ops op.Ops
for {
e := <-w.Events()
switch e := e.(type) {
case system.DestroyEvent:
return e.Err
case system.FrameEvent:
gtx := layout.NewContext(&ops, e)
// 创建统一尺寸的小部件
for i, label := range labels {
widgets[i] = func(btn *widget.Clickable, lbl string) layout.Widget {
return func(gtx layout.Context) layout.Dimensions {
// 设置统一的最小尺寸约束
gtx.Constraints.Min = layout.Pt(
gtx.Dp(180), // 统一最小宽度
gtx.Dp(45), // 统一最小高度
)
return material.Button(th, btn, lbl).Layout(gtx)
}
}(&buttons[i], label)
}
layout.Flex{Axis: layout.Vertical, Spacing: layout.SpaceAround}.Layout(gtx,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return layout.Center.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
list := &layout.List{
Axis: layout.Vertical,
Alignment: layout.Middle,
}
return list.Layout(gtx, len(widgets), func(gtx layout.Context, i int) layout.Dimensions {
return layout.UniformInset(unit.Dp(5)).Layout(gtx, widgets[i])
})
})
}),
)
e.Frame(gtx.Ops)
}
}
}
关键点:
- 通过修改
gtx.Constraints.Min设置统一的最小尺寸 - 使用闭包包装小部件以保持状态
layout.Pt()函数用于创建尺寸点gtx.Dp()将设备独立像素转换为实际像素
这种方法确保所有按钮具有相同的最小尺寸,同时允许内容较长的按钮自动扩展。

