如何设置窗口中按钮的准确位置?

问题描述 投票:0回答:1

我对 Go 很满意,我正在尝试开始使用 Gio(或 Gioui),所以我是 Gio 的初学者。 我有一个在窗口上绘制文本和按钮的代码(代码和屏幕截图)。我有两个问题:

  • 如何将窗口分割为2个位置
  • 并将按钮放置在右上角 如下图所示。

我的代码是


import (
    "fmt"
    "log"
    "os"

    "gioui.org/app"
    "gioui.org/layout"
    "gioui.org/op"
    "gioui.org/text"
    "gioui.org/unit"
    "gioui.org/widget"
    "gioui.org/widget/material"
)

func main() {
    go func() {
        w := new(app.Window)
        w.Option(app.Title("Hello World"))
        w.Option(app.MaxSize(unit.Dp(400), unit.Dp(600)))
        if err := draw(w); err != nil {
            log.Fatal(err)
        }
        os.Exit(0)
    }()
    app.Main()
}

func draw(w *app.Window) error {
    var ops op.Ops
    var lblButton widget.Clickable
    var btnClickArea widget.Clickable

    th := material.NewTheme()
    btn := layout.Rigid(
        func(gtx layout.Context) layout.Dimensions {
            btn := material.Button(th, &btnClickArea, "Button1")
            return btn.Layout(gtx)
        },
    )
    columns := layout.Flex{Axis: layout.Horizontal, Spacing: layout.SpaceAround}
    for {
        switch e := w.Event().(type) {
        case app.FrameEvent:
            gtx := app.NewContext(&ops, e)

            if lblButton.Clicked(gtx) {
                fmt.Println("the label was clicked")
            }
            if btnClickArea.Clicked(gtx) {
                fmt.Println("button1 was clicked")
            }

            layout.Flex{
                Axis:    layout.Vertical,
                Spacing: layout.SpaceStart,
            }.Layout(gtx,
                layout.Rigid(
                    layout.Spacer{Height: unit.Dp(250)}.Layout,
                ),
                layout.Rigid(
                    func(gtx layout.Context) layout.Dimensions {
                        lbl := material.Label(th, unit.Sp(50), "hello world")
                        lbl.Alignment = text.Middle
                        lblButton.Layout(gtx, lbl.Layout)
                        return lbl.Layout(gtx)
                    },
                ),
                layout.Rigid(
                    func(gtx layout.Context) layout.Dimensions {
                        return columns.Layout(gtx, btn)
                    },
                ),
            )
            e.Frame(gtx.Ops)
        case app.DestroyEvent:
            return e.Err
        }
    }
    return nil
}

代码将产生以下窗口 Code's result

我怎样才能有以下窗口(我的上述2个问题) What I want

go go-gio
1个回答
0
投票

您似乎想要的是两个嵌套的

layout.Flex
。顶层窗口将窗口垂直划分为用于文本的刚性区域和用于其余空间的灵活区域。然后水平弯曲将底部区域分为两个窗格。然后,您可以在右侧窗格内使用插图和方向来定位按钮。这是一个工作示例:

package main

import (
    "fmt"
    "image"
    "log"
    "os"

    "gioui.org/app"
    "gioui.org/layout"
    "gioui.org/op"
    "gioui.org/text"
    "gioui.org/unit"
    "gioui.org/widget"
    "gioui.org/widget/material"
)

func main() {
    go func() {
        w := new(app.Window)
        w.Option(app.Title("Hello World"))
        w.Option(app.MaxSize(unit.Dp(400), unit.Dp(600)))
        if err := draw(w); err != nil {
            log.Fatal(err)
        }
        os.Exit(0)
    }()
    app.Main()
}

func draw(w *app.Window) error {
    var ops op.Ops
    var lblButton widget.Clickable
    var btnClickArea widget.Clickable

    th := material.NewTheme()
    for {
        switch e := w.Event().(type) {
        case app.FrameEvent:
            gtx := app.NewContext(&ops, e)

            if lblButton.Clicked(gtx) {
                fmt.Println("the label was clicked")
            }
            if btnClickArea.Clicked(gtx) {
                fmt.Println("button1 was clicked")
            }

            // This flex splits the window vertically.
            layout.Flex{
                Axis: layout.Vertical,
            }.Layout(gtx,
                layout.Rigid(func(gtx layout.Context) layout.Dimensions {
                    lbl := material.Label(th, unit.Sp(50), "hello world")
                    lbl.Alignment = text.Middle
                    // Here we use the material.Clickable wrapper func to animate button clicks.
                    return material.Clickable(gtx, &lblButton, lbl.Layout)
                }),
                layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
                    // This flex splits the bottom pane horizontally.
                    return layout.Flex{}.Layout(gtx,
                        layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
                            // This returns an empty left-hand pane.
                            return layout.Dimensions{Size: gtx.Constraints.Min}
                        }),
                        layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
                            // Here we position the button at the "north" or top-center of the available space.
                            return layout.N.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
                                // Here we set the minimum constraints to zero. This allows our button to be smaller
                                // than the entire right-side pane in the UI. Without this change, the button is forced
                                // to occupy all of the space.
                                gtx.Constraints.Min = image.Point{}
                                // Here we inset the button a little bit on all sides.
                                return layout.UniformInset(8).Layout(gtx,
                                    material.Button(th, &btnClickArea, "Button1").Layout,
                                )
                            })

                        }),
                    )
                }),
            )
            e.Frame(gtx.Ops)
        case app.DestroyEvent:
            return e.Err
        }
    }
    return nil
}
© www.soinside.com 2019 - 2024. All rights reserved.