自定义 Fyne 自适应网格布局

2024年 2月 12日 77.3k 0

自定义 fyne 自适应网格布局

问题内容

我正在修改fyne库的container.newadaptivegrid(),以便根据我们传递的比例切片渲染小部件的宽度。截至目前,container.newadaptivegrid() 在一行中呈现等宽的小部件。基本上(总行大小/现在的小部件)。

我的代码:

package main

import (
"fmt"
"math"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)

func New(layout fyne.Layout, objects ...fyne.CanvasObject) *fyne.Container {
return fyne.NewContainerWithLayout(layout, objects...)
}

func NewAdaptiveGridWithRatios(ratios []float32, objects ...fyne.CanvasObject) *fyne.Container {
return New(NewAdaptiveGridLayoutWithRatios(ratios), objects...)
}

// Declare conformity with Layout interface
var _ fyne.Layout = (*adaptiveGridLayoutWithRatios)(nil)

type adaptiveGridLayoutWithRatios struct {
ratios []float32
adapt, vertical bool
}

func NewAdaptiveGridLayoutWithRatios(ratios []float32) fyne.Layout {
return &adaptiveGridLayoutWithRatios{ratios: ratios, adapt: true}
}

func (g *adaptiveGridLayoutWithRatios) horizontal() bool {
if g.adapt {
return fyne.IsHorizontal(fyne.CurrentDevice().Orientation())
}

return !g.vertical
}

func (g *adaptiveGridLayoutWithRatios) countRows(objects []fyne.CanvasObject) int {
count := 0
for _, child := range objects {
if child.Visible() {
count++
}
}

return int(math.Ceil(float64(count) / float64(len(g.ratios))))
}

// Get the leading (top or left) edge of a grid cell.
// size is the ideal cell size and the offset is which col or row its on.
func getLeading(size float64, offset int) float32 {
ret := (size + float64(theme.Padding())) * float64(offset)

return float32(ret)
}

// Get the trailing (bottom or right) edge of a grid cell.
// size is the ideal cell size and the offset is which col or row its on.
func getTrailing(size float64, offset int) float32 {
return getLeading(size, offset+1) - theme.Padding()
}

// Layout is called to pack all child objects into a specified size.
// For a GridLayout this will pack objects into a table format with the number
// of columns specified in our constructor.
func (g *adaptiveGridLayoutWithRatios) Layout(objects []fyne.CanvasObject, size fyne.Size) {
rows := g.countRows(objects)
cols := len(g.ratios)
if g.horizontal() {
cols = rows
rows = len(g.ratios)
}

padWidth := float32(cols-1) * theme.Padding()
padHeight := float32(rows-1) * theme.Padding()
var totalRatio float32
for _, r := range g.ratios {
totalRatio += r
}

cellWidth := (float64(size.Width) - float64(padWidth)) / float64(len(g.ratios))
cellHeight := float64(size.Height-padHeight) / float64(rows)

if !g.horizontal() {
cellWidth, cellHeight = cellHeight, cellWidth
cellWidth = float64(size.Width-padWidth) / float64(rows)
cellHeight = float64(size.Height-padHeight) / float64(len(g.ratios))
}

row, col := 0, 0
i := 0
for _, child := range objects {
if !child.Visible() {
continue
}

//ratio := g.ratios[j%len(g.ratios)]
cellSize := fyne.NewSize(float32(cellWidth)*g.ratios[i], float32(cellHeight))

x1 := getLeading(float64(cellSize.Width), col)
y1 := getLeading(float64(cellSize.Height), row)
x2 := getTrailing(float64(cellSize.Width), col)
y2 := getTrailing(float64(cellSize.Height), row)
fmt.Println("1s :", x1, y1)
fmt.Println("2s :", x2, y2)
child.Move(fyne.NewPos(x1, y1))
child.Resize(cellSize)

if g.horizontal() {
if (i+1)%cols == 0 {
row++
col = 0
} else {
col++
}
} else {
if (i+1)%cols == 0 {
col++
row = 0
} else {
row++
}
}
i++
}
fmt.Println("i :", i)
}

func (g *adaptiveGridLayoutWithRatios) MinSize(objects []fyne.CanvasObject) fyne.Size {
minSize := fyne.NewSize(0, 0)
return minSize
}

func main() {
myApp := app.New()
myWindow := myApp.NewWindow("My Windows")
myWindow.Resize(fyne.NewSize(600, 200))

button1 := widget.NewButton("Button 1", func() {
// Handle button click for button 1
})

button2 := widget.NewButton("Button 2", func() {
// Handle button click for button 2
})
button1.Importance = widget.WarningImportance
button2.Importance = widget.DangerImportance
title := widget.NewLabelWithStyle("Custom", fyne.TextAlignCenter, fyne.TextStyle{Bold: true})

myWindow.SetContent(container.NewVBox(title,
NewAdaptiveGridWithRatios([]float32{0.3, 0.7}, button1, button2)))

myWindow.ShowAndRun()
}

登录后复制

我希望按钮并排放置,按钮的相对宽度比例为 3:7。但我得到了两条水平线,一条在另一条之下。
我正在修改:https://github.com/fyne-io/fyne/blob/8c2509518b2df442a6b748d9b07754739592e6d7/layout/gridlayout.go
制作我的定制产品。

解决方法

这有效:

package main

import (
"fmt"
"math"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)

func New(layout fyne.Layout, objects ...fyne.CanvasObject) *fyne.Container {
return fyne.NewContainerWithLayout(layout, objects...)
}

func NewAdaptiveGridWithRatios(ratios []float32, objects ...fyne.CanvasObject) *fyne.Container {
return New(NewAdaptiveGridLayoutWithRatios(ratios), objects...)
}

// Declare conformity with Layout interface
var _ fyne.Layout = (*adaptiveGridLayoutWithRatios)(nil)

type adaptiveGridLayoutWithRatios struct {
ratios []float32
adapt, vertical bool
}

func NewAdaptiveGridLayoutWithRatios(ratios []float32) fyne.Layout {
return &adaptiveGridLayoutWithRatios{ratios: ratios, adapt: true}
}

func (g *adaptiveGridLayoutWithRatios) horizontal() bool {
if g.adapt {
return fyne.IsHorizontal(fyne.CurrentDevice().Orientation())
}

return !g.vertical
}

func (g *adaptiveGridLayoutWithRatios) countRows(objects []fyne.CanvasObject) int {
count := 0
for _, child := range objects {
if child.Visible() {
count++
}
}

return int(math.Ceil(float64(count) / float64(len(g.ratios))))
}

// Layout is called to pack all child objects into a specified size.
// For a GridLayout this will pack objects into a table format with the number
// of columns specified in our constructor.
func (g *adaptiveGridLayoutWithRatios) Layout(objects []fyne.CanvasObject, size fyne.Size) {

rows := g.countRows(objects)
cols := len(g.ratios)

padWidth := float32(cols-1) * theme.Padding()
padHeight := float32(rows-1) * theme.Padding()
tGap := float64(padWidth)
tcellWidth := float64(size.Width) - tGap
cellHeight := float64(size.Height-padHeight) / float64(rows)

fmt.Println(cols, rows)
fmt.Println(cellHeight, tcellWidth+tGap, tGap)
fmt.Println("tcellWidth, cellHeight", tcellWidth, cellHeight)
if !g.horizontal() {
padWidth, padHeight = padHeight, padWidth
tcellWidth = float64(size.Width-padWidth) - tGap
cellHeight = float64(size.Height-padHeight) / float64(cols)
}

row, col := 0, 0
i := 0
var x1, x2, y1, y2 float32 = 0.0, 0.0, 0.0, 0.0
fmt.Println("padWidth, padHeight, tcellWidth, cellHeight, float32(theme.Padding()):", padWidth, padHeight, tcellWidth, cellHeight, float32(theme.Padding()))
for _, child := range objects {
if !child.Visible() {
continue
}

if i == 0 {
x1 = 0
y1 = 0
} else {
x1 = x2 + float32(theme.Padding())*float32(1)
y1 = y2 - float32(cellHeight)
} // float32(tGap/float64(col))
// (size + float64(theme.Padding())) * float64(offset) float32(theme.Padding())*float32(1)
x2 = x1 + float32(tcellWidth*float64(g.ratios[i]))
y2 = float32(cellHeight)

fmt.Println("x1,y1 :", x1, y1)
fmt.Println("x2, y2 :", x2, y2)
fmt.Println("eff width", tcellWidth*float64(g.ratios[i]))

fmt.Println("------")
child.Move(fyne.NewPos(x1, y1))
child.Resize(fyne.NewSize((x2 - x1), y2-y1))

if g.horizontal() {
if (i+1)%cols == 0 {
row++
col = 0
} else {
col++
}
} else {
if (i+1)%cols == 0 {
col++
row = 0
} else {
row++
}
}
i++
}
fmt.Println("i :", i)
}

func (g *adaptiveGridLayoutWithRatios) MinSize(objects []fyne.CanvasObject) fyne.Size {
rows := g.countRows(objects)
minSize := fyne.NewSize(0, 0)
for _, child := range objects {
if !child.Visible() {
continue
}

minSize = minSize.Max(child.MinSize())
}

if g.horizontal() {
minContentSize := fyne.NewSize(minSize.Width*float32(len(g.ratios)), minSize.Height*float32(rows))
return minContentSize.Add(fyne.NewSize(theme.Padding()*fyne.Max(float32(len(g.ratios)-1), 0), theme.Padding()*fyne.Max(float32(rows-1), 0)))
}

minContentSize := fyne.NewSize(minSize.Width*float32(rows), minSize.Height*float32(len(g.ratios)))
return minContentSize.Add(fyne.NewSize(theme.Padding()*fyne.Max(float32(rows-1), 0), theme.Padding()*fyne.Max(float32(len(g.ratios)-1), 0)))
}

func main() {
myApp := app.New()
myWindow := myApp.NewWindow("My Windows Custom UI")
myWindow.Resize(fyne.NewSize(600, 200))

var buttons [16]*widget.Button

for i := 0; i 登录后复制

我以不同的比例添加了多个按钮和其他小部件。

以上就是自定义 Fyne 自适应网格布局的详细内容,更多请关注每日运维网(www.mryunwei.com)其它相关文章!

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论