gioui.org: gioui.org/layout Index | Examples | Files

package layout

import "gioui.org/layout"

Package layout implements layouts common to GUI programs.

Constraints and dimensions

Constraints and dimensions form the interface between layouts and interface child elements. This package operates on Widgets, functions that compute Dimensions from a a set of constraints for acceptable widths and heights. Both the constraints and dimensions are maintained in an implicit Context to keep the Widget declaration short.

For example, to add space above a widget:

gtx := &layout.Context{...}
gtx.Reset(...)

// Configure a top inset.
inset := layout.Inset{Top: unit.Dp(8), ...}
// Use the inset to lay out a widget.
inset.Layout(gtx, func() {
	// Lay out widget and determine its size given the constraints.
	...
	dims := layout.Dimensions{...}
	gtx.Dimensions = dims
})

Note that the example does not generate any garbage even though the Inset is transient. Layouts that don't accept user input are designed to not escape to the heap during their use.

Layout operations are recursive: a child in a layout operation can itself be another layout. That way, complex user interfaces can be created from a few generic layouts.

This example both aligns and insets a child:

inset := layout.Inset{...}
inset.Layout(gtx, func() {
	align := layout.Align(...)
	align.Layout(gtx, func() {
		widget.Layout(gtx, ...)
	})
})

More complex layouts such as Stack and Flex lay out multiple children, and stateful layouts such as List accept user input.

Index

Examples

Package Files

doc.go flex.go layout.go list.go stack.go

type Align Uses

type Align Direction

Align aligns a widget in the available space.

Code:

gtx := &layout.Context{Queue: q}
// Rigid constraints with both minimum and maximum set.
gtx.Reset(cfg, image.Point{X: 100, Y: 100})

align := layout.Align(layout.Center)
align.Layout(gtx, func() {
    // Lay out a 50x50 sized widget.
    layoutWidget(gtx, 50, 50)
    fmt.Println(gtx.Dimensions.Size)
})

fmt.Println(gtx.Dimensions.Size)

Output:

(50,50)
(100,100)

func (Align) Layout Uses

func (a Align) Layout(gtx *Context, w Widget)

Layout a widget.

type Alignment Uses

type Alignment uint8

Alignment is the mutual alignment of a list of widgets.

const (
    Start Alignment = iota
    End
    Middle
    Baseline
)

func (Alignment) String Uses

func (a Alignment) String() string

type Axis Uses

type Axis uint8

Axis is the Horizontal or Vertical direction.

const (
    Horizontal Axis = iota
    Vertical
)

func (Axis) String Uses

func (a Axis) String() string

type Constraint Uses

type Constraint struct {
    Min, Max int
}

Constraint is a range of acceptable sizes in a single dimension.

func (Constraint) Constrain Uses

func (c Constraint) Constrain(v int) int

Constrain a value to the range [Min; Max].

type Constraints Uses

type Constraints struct {
    Width  Constraint
    Height Constraint
}

Constraints represent a set of acceptable ranges for a widget's width and height.

func RigidConstraints Uses

func RigidConstraints(size image.Point) Constraints

RigidConstraints returns the constraints that can only be satisfied by the given dimensions.

func (Constraints) Constrain Uses

func (c Constraints) Constrain(size image.Point) image.Point

Constrain a size to the Width and Height ranges.

type Context Uses

type Context struct {
    // Constraints track the constraints for the active widget or
    // layout.
    Constraints Constraints
    // Dimensions track the result of the most recent layout
    // operation.
    Dimensions Dimensions

    system.Config
    event.Queue
    *op.Ops
}

Context carry the state needed by almost all layouts and widgets.

func (*Context) Reset Uses

func (c *Context) Reset(cfg system.Config, size image.Point)

Reset the context. The constraints' minimum and maximum values are set to the size.

type Dimensions Uses

type Dimensions struct {
    Size     image.Point
    Baseline int
}

Dimensions are the resolved size and baseline for a widget.

type Direction Uses

type Direction uint8

Direction is the alignment of widgets relative to a containing space.

const (
    NW  Direction = iota
    N
    NE
    E
    SE
    S
    SW
    W
    Center
)

func (Direction) String Uses

func (d Direction) String() string

type Flex Uses

type Flex struct {
    // Axis is the main axis, either Horizontal or Vertical.
    Axis Axis
    // Spacing controls the distribution of space left after
    // layout.
    Spacing Spacing
    // Alignment is the alignment in the cross axis.
    Alignment Alignment
    // contains filtered or unexported fields
}

Flex lays out child elements along an axis, according to alignment and weights.

Code:

gtx := &layout.Context{Queue: q}
gtx.Reset(cfg, image.Point{X: 100, Y: 100})

flex := layout.Flex{}

// Rigid 10x10 widget.
child1 := flex.Rigid(gtx, func() {
    fmt.Printf("Rigid: %v\n", gtx.Constraints.Width)
    layoutWidget(gtx, 10, 10)
})

// Child with 50% space allowance.
child2 := flex.Flex(gtx, 0.5, func() {
    fmt.Printf("50%%: %v\n", gtx.Constraints.Width)
    layoutWidget(gtx, 10, 10)
})

flex.Layout(gtx, child1, child2)

Output:

Rigid: {0 100}
50%: {45 45}

func (*Flex) Flex Uses

func (f *Flex) Flex(gtx *Context, weight float32, w Widget) FlexChild

Flex is like Rigid, where the main axis size is also constrained to a fraction of the space not taken up by Rigid children.

func (*Flex) Layout Uses

func (f *Flex) Layout(gtx *Context, children ...FlexChild)

Layout a list of children. The order of the children determines their laid out order.

func (*Flex) Rigid Uses

func (f *Flex) Rigid(gtx *Context, w Widget) FlexChild

Rigid lays out a widget with the main axis constrained to the range from 0 to the remaining space.

type FlexChild Uses

type FlexChild struct {
    // contains filtered or unexported fields
}

FlexChild is the layout result of a call End.

type Inset Uses

type Inset struct {
    Top, Right, Bottom, Left unit.Value
}

Inset adds space around a widget.

Code:

gtx := &layout.Context{Queue: q}
gtx.Reset(cfg, image.Point{X: 100, Y: 100})
// Loose constraints with no minimal size.
gtx.Constraints.Width.Min = 0
gtx.Constraints.Height.Min = 0

// Inset all edges by 10.
inset := layout.UniformInset(unit.Dp(10))
inset.Layout(gtx, func() {
    // Lay out a 50x50 sized widget.
    layoutWidget(gtx, 50, 50)
    fmt.Println(gtx.Dimensions.Size)
})

fmt.Println(gtx.Dimensions.Size)

Output:

(50,50)
(70,70)

func UniformInset Uses

func UniformInset(v unit.Value) Inset

UniformInset returns an Inset with a single inset applied to all edges.

func (Inset) Layout Uses

func (in Inset) Layout(gtx *Context, w Widget)

Layout a widget.

type List Uses

type List struct {
    Axis Axis
    // ScrollToEnd instructs the list to stay scrolled to the far end position
    // once reahed. A List with ScrollToEnd enabled also align its content to
    // the end.
    ScrollToEnd bool
    // Alignment is the cross axis alignment of list elements.
    Alignment Alignment
    // contains filtered or unexported fields
}

List displays a subsection of a potentially infinitely large underlying list. List accepts user input to scroll the subsection.

Code:

gtx := &layout.Context{Queue: q}
gtx.Reset(cfg, image.Point{X: 100, Y: 100})

// The list is 1e6 elements, but only 5 fit the constraints.
const listLen = 1e6

var list layout.List
count := 0
list.Layout(gtx, listLen, func(i int) {
    count++
    layoutWidget(gtx, 20, 20)
})

fmt.Println(count)

Output:

5

func (*List) Dragging Uses

func (l *List) Dragging() bool

Dragging reports whether the List is being dragged.

func (*List) Layout Uses

func (l *List) Layout(gtx *Context, len int, w ListElement)

Layout the List.

type ListElement Uses

type ListElement func(index int)

ListElement is a function that computes the dimensions of a list element.

type Spacing Uses

type Spacing uint8

Spacing determine the spacing mode for a Flex.

const (
    // SpaceEnd leaves space at the end.
    SpaceEnd Spacing = iota
    // SpaceStart leaves space at the start.
    SpaceStart
    // SpaceSides shares space between the start and end.
    SpaceSides
    // SpaceAround distributes space evenly between children,
    // with half as much space at the start and end.
    SpaceAround
    // SpaceBetween distributes space evenly between children,
    // leaving no space at the start and end.
    SpaceBetween
    // SpaceEvenly distributes space evenly between children and
    // at the start and end.
    SpaceEvenly
)

func (Spacing) String Uses

func (s Spacing) String() string

type Stack Uses

type Stack struct {
    // Alignment is the direction to align children
    // smaller than the available space.
    Alignment Direction
    // contains filtered or unexported fields
}

Stack lays out child elements on top of each other, according to an alignment direction.

Code:

gtx := &layout.Context{Queue: q}
gtx.Reset(cfg, image.Point{X: 100, Y: 100})

stack := layout.Stack{}

// Rigid 50x50 widget.
child1 := stack.Rigid(gtx, func() {
    layoutWidget(gtx, 50, 50)
})

// Force widget to the same size as the first.
child2 := stack.Expand(gtx, func() {
    fmt.Printf("Expand: %v\n", gtx.Constraints)
    layoutWidget(gtx, 10, 10)
})

stack.Layout(gtx, child1, child2)

Output:

Expand: {{50 100} {50 100}}

func (*Stack) Expand Uses

func (s *Stack) Expand(gtx *Context, w Widget) StackChild

Expand lays out a widget.

func (*Stack) Layout Uses

func (s *Stack) Layout(gtx *Context, children ...StackChild)

Layout a list of children. The order of the children determines their laid out order.

func (*Stack) Rigid Uses

func (s *Stack) Rigid(gtx *Context, w Widget) StackChild

Rigid lays out a widget with the same constraints that were passed to Init.

type StackChild Uses

type StackChild struct {
    // contains filtered or unexported fields
}

StackChild is the layout result of a call to End.

type Widget Uses

type Widget func()

Widget is a function scope for drawing, processing events and computing dimensions for a user interface element.

Package layout imports 9 packages (graph) and is imported by 8 packages. Updated 2019-11-19. Refresh now. Tools for package owners.