Διάταξη
August 16, 2026 · View on GitHub
Τα γραφικά στοιχεία στοιβάζονται κατακόρυφα από προεπιλογή. Όλα τα άλλα είναι opt-in.
Κενό — Βάλτε χώρο μεταξύ πραγμάτων
Η πιο χρησιμοποιούμενη λειτουργία διάταξης. Εισάγει κενό κατακόρυφο χώρο.
proton.H4(ctx, "Section Title")
proton.Gap(ctx, 8)
proton.Label(ctx, "Section content.")
proton.Gap(ctx, 24)
proton.H4(ctx, "Next Section")
proton.Gap(ctx proton.Context, dp float32)
Το 8dp είναι ένα μικρό κενό. 16dp είναι μέτρια. Το 24dp είναι μεγάλο. Αυτά τα τρία καλύπτουν τις περισσότερες περιπτώσεις.
Σειρά — Δίπλα δίπλα
Τοποθετεί τα παιδιά οριζόντια, από αριστερά προς τα δεξιά.
proton.Row(ctx,
func(ctx proton.Context) { proton.Label(ctx, "Name:") },
func(ctx proton.Context) { proton.Gap(ctx, 8) },
func(ctx proton.Context) { proton.Label(ctx, "Alice") },
)
Κάθε παιδί είναι ένα «func(proton.Context)». Καλέστε ό,τι widget θέλετε μέσα σε αυτό.
proton.Row(ctx proton.Context, widgets ...func(proton.Context))
Στήλη — Ρητή κάθετη ομάδα
Στοιβάζει τα παιδιά κάθετα ως ομάδα με όνομα. Σπάνια χρειάζεται στο κορυφαίο επίπεδο (τα γραφικά στοιχεία στοιβάζονται αυτόματα), αλλά χρήσιμα μέσα στη «Σειρά» ή στο «Διαίρεση» όταν το η δεξιά πλευρά πρέπει να είναι πολλά στοιβαγμένα πράγματα.
proton.Row(ctx,
func(ctx proton.Context) {
proton.Label(ctx, "Left side")
},
func(ctx proton.Context) { proton.Gap(ctx, 16) },
func(ctx proton.Context) {
proton.Column(ctx,
func(ctx proton.Context) { proton.Label(ctx, "Right top") },
func(ctx proton.Context) { proton.Gap(ctx, 4) },
func(ctx proton.Context) { proton.Muted(ctx, "Right bottom") },
)
},
)
proton.Column(ctx proton.Context, widgets ...func(proton.Context))
RowSpread — Διάστημα μεταξύ
Όπως το Row αλλά αφήνει εναπομείναν οριζόντιο διάστημα μεταξύ των παιδιών, σπρώχνοντας ο πρώτος στο αριστερό άκρο και ο τελευταίος στη δεξιά.
// title on the left, version on the right
proton.RowSpread(ctx,
func(ctx proton.Context) { proton.H5(ctx, "My App") },
func(ctx proton.Context) { proton.Caption(ctx, "v1.2.0") },
)
proton.RowSpread(ctx proton.Context, widgets ...func(proton.Context))
RowEnd — Όλα στα δεξιά
Σπρώχνει όλα τα παιδιά στη δεξιά άκρη.
proton.RowEnd(ctx,
func(ctx proton.Context) {
proton.Pad(ctx, 4, func(ctx proton.Context) {
if proton.OutlineButton(ctx, &u.cancel, "Cancel") { handleCancel() }
})
},
func(ctx proton.Context) { proton.Gap(ctx, 8) },
func(ctx proton.Context) {
proton.Pad(ctx, 4, func(ctx proton.Context) {
if proton.Button(ctx, &u.save, "Save") { handleSave() }
})
},
)
proton.RowEnd(ctx proton.Context, widgets ...func(proton.Context))
GrowRow και GrowColumn — Strechy Layouts
Όταν ένα παιδί χρειάζεται να γεμίσει όλο τον υπόλοιπο χώρο και τα άλλα μένουν δικά τους φυσικό μέγεθος, χρησιμοποιήστε το "GrowRow" (οριζόντια) ή το "GrowColumn" (κάθετο) με "GrowItem" και "FixedItem".
// search bar: label fixed, input stretches, button fixed
proton.GrowRow(ctx,
proton.FixedItem(ctx, func(ctx proton.Context) {
proton.Label(ctx, "Search:")
}),
proton.GrowItem(ctx, func(ctx proton.Context) {
proton.Input(ctx, &u.search, "Type to search...")
}),
proton.FixedItem(ctx, func(ctx proton.Context) {
proton.Pad(ctx, 4, func(ctx proton.Context) {
if proton.Button(ctx, &u.searchBtn, "Go") { doSearch() }
})
}),
)
Το "GrowItem" καταλαμβάνει όλο τον υπόλοιπο χώρο. Το "FixedItem" παίρνει μόνο ό,τι χρειάζεται. Πολλαπλά «GrowItem» διαχωρίζουν ομοιόμορφα τον υπόλοιπο χώρο.
proton.GrowRow(ctx proton.Context, children ...proton.FlexItem)
proton.GrowColumn(ctx proton.Context, children ...proton.FlexItem)
proton.GrowItem(ctx proton.Context, fn func(proton.Context)) proton.FlexItem
proton.FixedItem(ctx proton.Context, fn func(proton.Context)) proton.FlexItem
FlexSpacer — Απομακρύνετε τα αδέρφια
Ένας ελαστικός κενός χώρος. Τοποθετήστε το ανάμεσα στα «FixedItem» για να τα ωθήσετε στο αντίθετο άκρες χωρίς τη χρήση «RowSpread».
proton.GrowRow(ctx,
proton.FixedItem(ctx, func(ctx proton.Context) { proton.Caption(ctx, "left") }),
proton.FlexSpacer(),
proton.FixedItem(ctx, func(ctx proton.Context) { proton.Caption(ctx, "right") }),
)
proton.FlexSpacer() proton.FlexItem
Διαχωρισμός — Παράθυρα δίπλα-δίπλα
Χωρίζει το διαθέσιμο πλάτος σε δύο τμήματα. Το «αριστερό κλάσμα» είναι η αναλογία το αριστερό παράθυρο γίνεται από 0,0 σε 1,0.
proton.Split(ctx, 0.35,
func(ctx proton.Context) {
// sidebar — gets 35% of the width
proton.Label(ctx, "Sidebar")
},
func(ctx proton.Context) {
// content — gets the remaining 65%
proton.Label(ctx, "Content")
},
)
proton.Split(ctx proton.Context, leftFraction float32, left func(proton.Context), right func(proton.Context))
HSplit — Πάνω και κάτω
Ίδια ιδέα αλλά κάθετη.
proton.HSplit(ctx, 0.7,
func(ctx proton.Context) { proton.Label(ctx, "Main content") },
func(ctx proton.Context) { proton.Label(ctx, "Status bar") },
)
proton.HSplit(ctx proton.Context, topFraction float32, top func(proton.Context), bottom func(proton.Context))
ResizeSplit — Ο χρήστης μπορεί να σύρει το διαχωριστικό
Μου αρέσει το Split αλλά ο χρήστης μπορεί να σύρει τη λαβή ανάμεσα στα δύο παράθυρα σε αλλάξτε το μέγεθός τους. Το «defaultFraction» είναι η αρχική θέση.
type UI struct {
split proton.ResizeSplitState
}
proton.ResizeSplit(ctx, &u.split, 0.30, leftFn, rightFn)
Το "ResizeSplitState.Fraction" ξεκινά από το 0 και ορίζεται σε "defaultFraction" στο πρώτο πλαίσιο. Στη συνέχεια απομνημονεύεται η θέση μεταφοράς του χρήστη.
proton.ResizeSplit(ctx proton.Context, state *proton.ResizeSplitState, defaultFraction float32, left func(proton.Context), right func(proton.Context))
proton.ResizeHSplit(ctx proton.Context, state *proton.ResizeSplitState, defaultFraction float32, top func(proton.Context), bottom func(proton.Context))
Κέντρο
Τοποθετεί το περιεχόμενο στο κέντρο του διαθέσιμου χώρου. Ιδανικό για κενές πολιτείες και οθόνες φόρτωσης.
proton.Center(ctx, func(ctx proton.Context) {
proton.Muted(ctx, "Nothing here yet.")
})
proton.Center(ctx proton.Context, fn func(proton.Context))
Γέμισμα
Μαξιλάρι — Και οι τέσσερις πλευρές
proton.Pad(ctx, 16, func(ctx proton.Context) {
proton.Label(ctx, "16dp of breathing room on all sides")
})
PadH — Μόνο αριστερά και δεξιά
proton.PadH(ctx, 24, func(ctx proton.Context) {
proton.Label(ctx, "horizontal padding only")
})
PadV — Μόνο πάνω και κάτω
proton.PadV(ctx, 12, func(ctx proton.Context) {
proton.Label(ctx, "vertical padding only")
})
PadSides — Κάθε άκρη ξεχωριστά
Τα ορίσματα είναι πάνω, δεξιά, κάτω, αριστερά — ίδια σειρά με το περιθώριο/επένδυση CSS.
proton.PadSides(ctx, 8, 16, 8, 16, func(ctx proton.Context) {
proton.Label(ctx, "8dp top/bottom, 16dp left/right")
})
proton.Pad(ctx proton.Context, dp float32, fn func(proton.Context))
proton.PadH(ctx proton.Context, dp float32, fn func(proton.Context))
proton.PadV(ctx proton.Context, dp float32, fn func(proton.Context))
proton.PadSides(ctx proton.Context, top, right, bottom, left float32, fn func(proton.Context))
Πλέγμα — Πλέγμα σταθερής στήλης
Τακτοποιεί τα παιδιά σε ένα πλέγμα με σταθερό αριθμό στηλών. Κάθε κύτταρο παίρνει ίσο μερίδιο του διαθέσιμου πλάτους.
proton.Grid(ctx, 3, 8, // 3 columns, 8dp gap
func(ctx proton.Context) { proton.Label(ctx, "one") },
func(ctx proton.Context) { proton.Label(ctx, "two") },
func(ctx proton.Context) { proton.Label(ctx, "three") },
func(ctx proton.Context) { proton.Label(ctx, "four") },
func(ctx proton.Context) { proton.Label(ctx, "five") },
)
Τα κελιά αναδιπλώνονται αυτόματα σε νέες σειρές. Εάν η τελευταία σειρά έχει λιγότερα από κελιά "cols", οι υπόλοιπες υποδοχές είναι κενές.
proton.Grid(ctx proton.Context, cols int, gapDp float32, cells ...func(proton.Context))
ZStack — Σχεδιάστε τα πράγματα το ένα πάνω στο άλλο
Επίπεδα πολλαπλών γραφικών στοιχείων στην ίδια θέση. Το πρώτο παιδί είναι στο κάτω? το τελευταίο είναι στην κορυφή.
proton.ZStack(ctx,
func(ctx proton.Context) {
// bottom layer — a background shape
proton.RoundRect(ctx, proton.RGB(0x1e1e2e), 0, 100, 12)
},
func(ctx proton.Context) {
// top layer — text floating over the shape
proton.Center(ctx, func(ctx proton.Context) {
proton.Label(ctx, "Text on top")
})
},
)
proton.ZStack(ctx proton.Context, layers ...func(proton.Context))
MinSize και MaxWidth — Περιορισμοί μεγέθους
// at least 200dp wide and 48dp tall
proton.MinSize(ctx, 200, 48, func(ctx proton.Context) {
if proton.Button(ctx, &u.btn, "OK") { handleOK() }
})
// no wider than 420dp — keeps forms readable on wide windows
proton.MaxWidth(ctx, 420, func(ctx proton.Context) {
proton.Input(ctx, &u.email, "Email address")
proton.Gap(ctx, 8)
proton.Input(ctx, &u.password, "Password")
})
proton.MinSize(ctx proton.Context, widthDp, heightDp float32, fn func(proton.Context))
proton.MaxWidth(ctx proton.Context, widthDp float32, fn func(proton.Context))
Περάστε το 0 για οποιαδήποτε διάσταση του "MinSize" για να αφήσετε αυτόν τον άξονα απεριόριστο.
Μια τυπική εφαρμογή δύο στηλών
func draw(ctx proton.Context, u *UI) {
// header
proton.PadSides(ctx, 0, 0, 12, 0, func(ctx proton.Context) {
proton.RowSpread(ctx,
func(ctx proton.Context) { proton.H5(ctx, "My App") },
func(ctx proton.Context) { proton.Caption(ctx, "v1.0") },
)
})
proton.Divider(ctx)
proton.Gap(ctx, 16)
// body
proton.ResizeSplit(ctx, &u.split, 0.28,
func(ctx proton.Context) {
drawSidebar(ctx, u)
},
func(ctx proton.Context) {
proton.PadH(ctx, 16, func(ctx proton.Context) {
drawContent(ctx, u)
})
},
)
}