pub struct View { /* private fields */ }Expand description
A SwiftUI view with chainable modifiers.
Implementations§
Source§impl View
impl View
Sourcepub fn a11y_hint(self, hint: &str) -> Self
pub fn a11y_hint(self, hint: &str) -> Self
.accessibilityHint(_:) — what happens if the user activates this.
Examples found in repository?
77fn row(i: usize) -> View {
78 let m = &MESSAGES[i];
79 hstack_spacing(
80 &[
81 // An unread dot, or the space where one would be.
82 view_if!(
83 m.unread,
84 circle_shape().fill_system(SystemColor::Blue).frame(8.0, 8.0),
85 empty().frame(8.0, 8.0)
86 ),
87 vstack_aligned(
88 &[
89 text(m.from).bold(),
90 text(m.subject).font_size(12.0).fg_system(SystemColor::Gray),
91 ],
92 HorizontalAlignment::Leading,
93 ),
94 spacer(),
95 ],
96 8.0,
97 )
98 .padding_edges(EdgeSet::Vertical, Some(4.0))
99 .a11y_label(&format!("{}, {}", m.from, m.subject))
100 .a11y_hint(if m.unread { "Unread" } else { "Read" })
101}More examples
43fn body() -> View {
44 let s = settings();
45
46 form![
47 section![header: text("Account");
48 hstack![
49 text("Name"),
50 spacer(),
51 textfield_bound("Your name", &s.name).text_field_style(
52 views::TextFieldStyle::RoundedBorderTextFieldStyle,
53 ),
54 ],
55 toggle_bound("Notifications", &s.notify),
56 ],
57 section![header: text("Playback");
58 vstack_aligned(&[
59 hstack![
60 text("Volume"),
61 spacer(),
62 text!("{:.0}%", s.volume.get() * 100.0).fg_system(SystemColor::Gray),
63 ],
64 slider_bound(&s.volume, 0.0, 1.0),
65 ], HorizontalAlignment::Leading),
66 stepper_bound("Refresh every", &s.refresh, 1.0, 60.0, 1.0),
67 ],
68 section![header: text("Appearance");
69 picker_bound!(
70 "Theme",
71 &s.theme,
72 text(THEMES[0]).tag_int(0),
73 text(THEMES[1]).tag_int(1),
74 text(THEMES[2]).tag_int(2),
75 )
76 .picker_style(PickerStyle::InlinePickerStyle),
77 ],
78 section![
79 button("About", show_about)
80 .a11y_hint("Opens a panel describing this app"),
81 ],
82 ]
83 .form_style(FormStyle::GroupedFormStyle)
84 .sheet_bound(&s.about, about_panel())
85}Sourcepub fn a11y_value(self, value: &str) -> Self
pub fn a11y_value(self, value: &str) -> Self
.accessibilityValue(_:) — what the control currently reads as, for one
whose value is not its label.
Examples found in repository?
28fn tile(i: usize) -> View {
29 let value = reading(i);
30 vstack_spacing(
31 &[
32 zstack![
33 circle_shape().stroke_system(SystemColor::Gray, 6.0).opacity(0.25),
34 // The filled part: the same circle trimmed to the fraction, and
35 // turned so the arc starts at the top rather than at three
36 // o'clock.
37 circle_shape()
38 .trim(0.0, value)
39 .stroke_system(TINTS[i], 6.0)
40 .rotate(-90.0),
41 text!("{:.0}", value * 100.0).text_style(TextStyle::Title2).bold(),
42 ]
43 .frame(72.0, 72.0),
44 text(LABELS[i]).font_size(12.0).fg_system(SystemColor::Gray),
45 ],
46 8.0,
47 )
48 .padding(12.0)
49 .a11y_element(AccessibilityChildBehavior::Combine)
50 .a11y_label(LABELS[i])
51 .a11y_value(&format!("{:.0} percent", value * 100.0))
52}More examples
59fn row(i: usize, it: &Item) -> View {
60 hstack_spacing(
61 &[
62 // The checkmark is the button, so the whole symbol is the target.
63 button_labelled(
64 system_image(if it.done { "checkmark.circle.fill" } else { "circle" })
65 .symbol_rendering_mode(Some(views::SymbolRenderingMode::Hierarchical))
66 .view()
67 .fg_system(if it.done { SystemColor::Green } else { SystemColor::Gray }),
68 move || toggle(i),
69 )
70 .button_style(views::ButtonStyle::Bordered),
71 text(&it.title)
72 .strikethrough_styled(it.done, LinePattern::Solid, None)
73 .fg_system(if it.done { SystemColor::Gray } else { SystemColor::Primary }),
74 spacer(),
75 ],
76 10.0,
77 )
78 .padding_edges(EdgeSet::Vertical, Some(6.0))
79 .a11y_label(&it.title)
80 .a11y_value(if it.done { "Done" } else { "Not done" })
81}Sourcepub fn a11y_identifier(self, id: &str) -> Self
pub fn a11y_identifier(self, id: &str) -> Self
.accessibilityIdentifier(_:) — the name a UI test finds this by, not
something VoiceOver speaks.
Sourcepub fn a11y_add_traits(self, traits: &[AccessibilityTrait]) -> Self
pub fn a11y_add_traits(self, traits: &[AccessibilityTrait]) -> Self
.accessibilityAddTraits(_:)
Sourcepub fn a11y_remove_traits(self, traits: &[AccessibilityTrait]) -> Self
pub fn a11y_remove_traits(self, traits: &[AccessibilityTrait]) -> Self
.accessibilityRemoveTraits(_:)
Sourcepub fn a11y_heading(self, level: HeadingLevel) -> Self
pub fn a11y_heading(self, level: HeadingLevel) -> Self
.accessibilityHeading(_:) — which heading level this is, so VoiceOver
can navigate by them.
Sourcepub fn a11y_sort_priority(self, priority: f64) -> Self
pub fn a11y_sort_priority(self, priority: f64) -> Self
.accessibilitySortPriority(_:) — higher is read first.
Sourcepub fn a11y_input_labels(self, labels: &[&str]) -> Self
pub fn a11y_input_labels(self, labels: &[&str]) -> Self
.accessibilityInputLabels(_:) — the phrases Voice Control accepts for
this, when the visible label is awkward to say.
Sourcepub fn a11y_responds_to_interaction(self, responds: bool) -> Self
pub fn a11y_responds_to_interaction(self, responds: bool) -> Self
.accessibilityRespondsToUserInteraction(_:)
Sourcepub fn a11y_text_content_type(self, kind: TextContentType) -> Self
pub fn a11y_text_content_type(self, kind: TextContentType) -> Self
.accessibilityTextContentType(_:) — what kind of text this is, which
changes how VoiceOver reads it.
Sourcepub fn a11y_action(self, kind: ActionKind, action: impl Fn() + 'static) -> Self
pub fn a11y_action(self, kind: ActionKind, action: impl Fn() + 'static) -> Self
.accessibilityAction(_:_:) — an action VoiceOver can perform without a
visible control for it.
Sourcepub fn a11y_actions(self, category: ActionCategory, content: View) -> Self
pub fn a11y_actions(self, category: ActionCategory, content: View) -> Self
.accessibilityActions(category:content:) — several, as a group.
Sourcepub fn a11y_adjustable_action(self, action: impl Fn(i64) + 'static) -> Self
pub fn a11y_adjustable_action(self, action: impl Fn(i64) + 'static) -> Self
.accessibilityAdjustableAction(_:) — what a swipe up or down does,
which is how VoiceOver drives a slider or stepper.
Sourcepub fn a11y_scroll_action(self, action: impl Fn(i64) + 'static) -> Self
pub fn a11y_scroll_action(self, action: impl Fn(i64) + 'static) -> Self
.accessibilityScrollAction(_:)
Sourcepub fn a11y_zoom_action(self, action: impl Fn() + 'static) -> Self
pub fn a11y_zoom_action(self, action: impl Fn() + 'static) -> Self
.accessibilityZoomAction(_:)
Sourcepub fn a11y_element(self, children: AccessibilityChildBehavior) -> Self
pub fn a11y_element(self, children: AccessibilityChildBehavior) -> Self
.accessibilityElement(children:) — whether descendants are merged into
one element, kept as a container, or dropped.
Examples found in repository?
28fn tile(i: usize) -> View {
29 let value = reading(i);
30 vstack_spacing(
31 &[
32 zstack![
33 circle_shape().stroke_system(SystemColor::Gray, 6.0).opacity(0.25),
34 // The filled part: the same circle trimmed to the fraction, and
35 // turned so the arc starts at the top rather than at three
36 // o'clock.
37 circle_shape()
38 .trim(0.0, value)
39 .stroke_system(TINTS[i], 6.0)
40 .rotate(-90.0),
41 text!("{:.0}", value * 100.0).text_style(TextStyle::Title2).bold(),
42 ]
43 .frame(72.0, 72.0),
44 text(LABELS[i]).font_size(12.0).fg_system(SystemColor::Gray),
45 ],
46 8.0,
47 )
48 .padding(12.0)
49 .a11y_element(AccessibilityChildBehavior::Combine)
50 .a11y_label(LABELS[i])
51 .a11y_value(&format!("{:.0} percent", value * 100.0))
52}Sourcepub fn a11y_children(self, children: View) -> Self
pub fn a11y_children(self, children: View) -> Self
.accessibilityChildren(children:) — a different subtree for VoiceOver
than the one on screen.
Sourcepub fn a11y_representation(self, representation: View) -> Self
pub fn a11y_representation(self, representation: View) -> Self
.accessibilityRepresentation(representation:) — stand in for this view
with a description of a standard control.
Sourcepub fn a11y_labeled_pair(
self,
role: LabeledPairRole,
id: HashableValue<'_>,
) -> Self
pub fn a11y_labeled_pair( self, role: LabeledPairRole, id: HashableValue<'_>, ) -> Self
.accessibilityLabeledPair(role:id:) — tie a label to the thing it
labels, so they are read together.
Sourcepub fn a11y_linked_group<'h>(self, id: impl IntoHashable<'h>) -> Self
pub fn a11y_linked_group<'h>(self, id: impl IntoHashable<'h>) -> Self
.accessibilityLinkedGroup(id:)
Sourcepub fn a11y_custom_content(
self,
key_label: &str,
id: &str,
value: &str,
importance: CustomContentImportance,
) -> Self
pub fn a11y_custom_content( self, key_label: &str, id: &str, value: &str, importance: CustomContentImportance, ) -> Self
.accessibilityCustomContent(_:_:importance:) — extra detail VoiceOver
reads on request rather than always.
Sourcepub fn a11y_activation_point(self, x: f64, y: f64) -> Self
pub fn a11y_activation_point(self, x: f64, y: f64) -> Self
.accessibilityActivationPoint(_:) — where a VoiceOver double-tap lands,
for a control whose centre is not where it should be pressed.
Sourcepub fn a11y_drag_point(self, x: f64, y: f64, description: &str) -> Self
pub fn a11y_drag_point(self, x: f64, y: f64, description: &str) -> Self
.accessibilityDragPoint(_:description:)
Sourcepub fn a11y_drop_point(self, x: f64, y: f64, description: &str) -> Self
pub fn a11y_drop_point(self, x: f64, y: f64, description: &str) -> Self
.accessibilityDropPoint(_:description:)
Sourcepub fn a11y_direct_touch(
self,
enabled: bool,
options: &[DirectTouchOption],
) -> Self
pub fn a11y_direct_touch( self, enabled: bool, options: &[DirectTouchOption], ) -> Self
.accessibilityDirectTouch(_:options:) — for a view that handles raw
touches itself, like an instrument or a drawing canvas.
Sourcepub fn a11y_scroll_status(self, status: &str) -> Self
pub fn a11y_scroll_status(self, status: &str) -> Self
.accessibilityScrollStatus(_:) — what to announce after a scroll.
Sourcepub fn a11y_shows_large_content_viewer(self) -> Self
pub fn a11y_shows_large_content_viewer(self) -> Self
.accessibilityShowsLargeContentViewer()
Source§impl View
impl View
Sourcepub fn accessibility_action(
self,
kind: ActionKind,
action: impl Fn() + 'static,
) -> Self
pub fn accessibility_action( self, kind: ActionKind, action: impl Fn() + 'static, ) -> Self
Apply .accessibilityAction(_:_:).
Sourcepub fn accessibility_actions(
self,
category: ActionCategory,
content: View,
) -> Self
pub fn accessibility_actions( self, category: ActionCategory, content: View, ) -> Self
Apply .accessibilityActions(category:_:).
Sourcepub fn accessibility_activation_point(self, x: f64, y: f64) -> Self
pub fn accessibility_activation_point(self, x: f64, y: f64) -> Self
Apply .accessibilityActivationPoint(_:).
A UnitPoint is two CGFloats and frozen, so it arrives in d0 and d1
rather than by address.
Sourcepub fn accessibility_add_traits(self, traits: &[AccessibilityTrait]) -> Self
pub fn accessibility_add_traits(self, traits: &[AccessibilityTrait]) -> Self
Apply .accessibilityAddTraits(_:).
Sourcepub fn accessibility_adjustable_action(
self,
action: impl Fn(i64) + 'static,
) -> Self
pub fn accessibility_adjustable_action( self, action: impl Fn(i64) + 'static, ) -> Self
Apply .accessibilityAdjustableAction(_:).
The direction reaches the callback as a case number: 0 is .increment,
1 is .decrement.
Sourcepub fn accessibility_chart_descriptor(self) -> Self
pub fn accessibility_chart_descriptor(self) -> Self
Apply .accessibilityChartDescriptor(_:) with a synthesized representable.
No public SwiftUI type conforms to AXChartDescriptorRepresentable — the
protocol exists for applications to adopt — so the conformance is built at
run time and hung on EdgeInsets, which the reference can name too.
Sourcepub fn accessibility_children(self, children: View) -> Self
pub fn accessibility_children(self, children: View) -> Self
Apply .accessibilityChildren(children:).
Sourcepub fn accessibility_custom_content(
self,
key_label: &str,
id: &str,
value: &str,
importance: CustomContentImportance,
) -> Self
pub fn accessibility_custom_content( self, key_label: &str, id: &str, value: &str, importance: CustomContentImportance, ) -> Self
Apply .accessibilityCustomContent(_:_:importance:).
The key is built first, through AccessibilityCustomContentKey.init(_:id:)
— four words of LocalizedStringKey and two of String, returning the key
through x8 because it is resilient. The modifier then takes that key by
address, its own label as another LocalizedStringKey, and the importance
in a register.
Sourcepub fn accessibility_default_focus(self, value: bool) -> Self
pub fn accessibility_default_focus(self, value: bool) -> Self
Apply .accessibilityDefaultFocus(_:_:).
The binding’s Value is generic here, which makes FocusState<A>.Binding
address-only — unlike the concrete focused(_:), where it travels in three
registers.
Sourcepub fn accessibility_deprecated_identifier(self, id: &str) -> Self
pub fn accessibility_deprecated_identifier(self, id: &str) -> Self
Apply .accessibility(identifier:), the pre-accessibilityIdentifier name.
Sourcepub fn accessibility_direct_touch(
self,
enabled: bool,
options: &[DirectTouchOption],
) -> Self
pub fn accessibility_direct_touch( self, enabled: bool, options: &[DirectTouchOption], ) -> Self
Apply .accessibilityDirectTouch(_:options:).
Sourcepub fn accessibility_drag_point(
self,
x: f64,
y: f64,
description: &str,
enabled: bool,
) -> Self
pub fn accessibility_drag_point( self, x: f64, y: f64, description: &str, enabled: bool, ) -> Self
Apply .accessibilityDragPoint(_:description:isEnabled:).
Sourcepub fn accessibility_drop_point(
self,
x: f64,
y: f64,
description: &str,
enabled: bool,
) -> Self
pub fn accessibility_drop_point( self, x: f64, y: f64, description: &str, enabled: bool, ) -> Self
Apply .accessibilityDropPoint(_:description:isEnabled:).
Sourcepub fn accessibility_element(self, v0: AccessibilityChildBehavior) -> Self
pub fn accessibility_element(self, v0: AccessibilityChildBehavior) -> Self
Apply .accessibilityElement(_:).
Sourcepub fn accessibility_focused(self) -> Self
pub fn accessibility_focused(self) -> Self
Apply .accessibilityFocused(_:).
Sourcepub fn accessibility_heading(self, level: HeadingLevel) -> Self
pub fn accessibility_heading(self, level: HeadingLevel) -> Self
Apply .accessibilityHeading(_:).
Apply .accessibilityHidden(_:).
Sourcepub fn accessibility_hint(self, hint: &str) -> Self
pub fn accessibility_hint(self, hint: &str) -> Self
Apply .accessibilityHint(_:).
Sourcepub fn accessibility_identifier(self, id: &str) -> Self
pub fn accessibility_identifier(self, id: &str) -> Self
Apply .accessibilityIdentifier(_:).
Sourcepub fn accessibility_ignores_invert_colors(self, value: bool) -> Self
pub fn accessibility_ignores_invert_colors(self, value: bool) -> Self
Apply .accessibilityIgnoresInvertColors(_:).
pub fn accessibility_input_labels(self, labels: &[&str], enabled: bool) -> Self
Sourcepub fn accessibility_label(self, label: &str) -> Self
pub fn accessibility_label(self, label: &str) -> Self
Apply .accessibilityLabel(_:).
Sourcepub fn accessibility_labeled_pair<'h>(
self,
role: LabeledPairRole,
id: impl IntoHashable<'h>,
) -> Self
pub fn accessibility_labeled_pair<'h>( self, role: LabeledPairRole, id: impl IntoHashable<'h>, ) -> Self
Apply .accessibilityLabeledPair(role:id:in:).
Sourcepub fn accessibility_linked_group<'h>(self, id: impl IntoHashable<'h>) -> Self
pub fn accessibility_linked_group<'h>(self, id: impl IntoHashable<'h>) -> Self
Apply .accessibilityLinkedGroup(id:in:).
Sourcepub fn accessibility_remove_traits(self, traits: &[AccessibilityTrait]) -> Self
pub fn accessibility_remove_traits(self, traits: &[AccessibilityTrait]) -> Self
Apply .accessibilityRemoveTraits(_:).
Sourcepub fn accessibility_representation(self, representation: View) -> Self
pub fn accessibility_representation(self, representation: View) -> Self
Apply .accessibilityRepresentation(representation:).
Sourcepub fn accessibility_responds_to_user_interaction(self, responds: bool) -> Self
pub fn accessibility_responds_to_user_interaction(self, responds: bool) -> Self
Apply .accessibilityRespondsToUserInteraction(_:).
Sourcepub fn accessibility_rotor(self, label: &str, text: &str) -> Self
pub fn accessibility_rotor(self, label: &str, text: &str) -> Self
Apply .accessibilityRotor(_:textRanges:).
The ranges are real Range<String.Index> values taken from text — one
spanning the whole string. Range is frozen and its two bounds are stored
back to back, so the array elements are built directly rather than through an
initialiser.
Sourcepub fn accessibility_rotor_entry<'h>(self, id: impl IntoHashable<'h>) -> Self
pub fn accessibility_rotor_entry<'h>(self, id: impl IntoHashable<'h>) -> Self
Apply .accessibilityRotorEntry(id:in:).
Sourcepub fn accessibility_scroll_action(self, action: impl Fn(i64) + 'static) -> Self
pub fn accessibility_scroll_action(self, action: impl Fn(i64) + 'static) -> Self
Apply .accessibilityScrollAction(_:).
The edge reaches the callback as a case number, in Edge’s declared order:
top, leading, bottom, trailing.
Sourcepub fn accessibility_scroll_status(self, status: &str, enabled: bool) -> Self
pub fn accessibility_scroll_status(self, status: &str, enabled: bool) -> Self
Apply .accessibilityScrollStatus(_:isEnabled:).
Sourcepub fn accessibility_selection_identifier<'h>(
self,
id: impl IntoHashable<'h>,
) -> Self
pub fn accessibility_selection_identifier<'h>( self, id: impl IntoHashable<'h>, ) -> Self
.accessibility(selectionIdentifier:) — which item of a selectable group
this is, for assistive technologies.
Deprecated in Swift, with no modern replacement — accessibilityIdentifier
is a different thing (a test hook). Bound because it is the one member of
that family the crate could not otherwise reach.
The argument is AnyHashable, which is three words: the boxed value, its
metadata and its Hashable witness.
Sourcepub fn accessibility_shows_large_content_viewer(self) -> Self
pub fn accessibility_shows_large_content_viewer(self) -> Self
Apply .accessibilityShowsLargeContentViewer(_:).
Sourcepub fn accessibility_sort_priority(self, priority: f64) -> Self
pub fn accessibility_sort_priority(self, priority: f64) -> Self
Apply .accessibilitySortPriority(_:).
Sourcepub fn accessibility_text_content_type(self, kind: TextContentType) -> Self
pub fn accessibility_text_content_type(self, kind: TextContentType) -> Self
Apply .accessibilityTextContentType(_:).
Sourcepub fn accessibility_value(self, value: &str, enabled: bool) -> Self
pub fn accessibility_value(self, value: &str, enabled: bool) -> Self
Apply .accessibilityValue(_:isEnabled:).
Sourcepub fn accessibility_zoom_action(self, action: impl Fn() + 'static) -> Self
pub fn accessibility_zoom_action(self, action: impl Fn() + 'static) -> Self
Apply .accessibilityZoomAction(_:).
Sourcepub fn allowed_dynamic_range(self, range: DynamicRange) -> Self
pub fn allowed_dynamic_range(self, range: DynamicRange) -> Self
Apply .allowedDynamicRange(_:).
Sourcepub fn allows_hit_testing(self, value: bool) -> Self
pub fn allows_hit_testing(self, value: bool) -> Self
Apply .allowsHitTesting(_:).
Sourcepub fn allows_tightening(self, value: bool) -> Self
pub fn allows_tightening(self, value: bool) -> Self
Apply .allowsTightening(_:).
Sourcepub fn allows_window_activation_events(self, allows: Option<bool>) -> Self
pub fn allows_window_activation_events(self, allows: Option<bool>) -> Self
Apply .allowsWindowActivationEvents(_:).
Sourcepub fn animation_kind(self, kind: AnimationKind, value: i64) -> Self
pub fn animation_kind(self, kind: AnimationKind, value: i64) -> Self
.animation(_:value:) with the curve named.
Sourcepub fn aspect_ratio_content_mode(
self,
ratio: Option<f64>,
mode: ContentMode,
) -> Self
pub fn aspect_ratio_content_mode( self, ratio: Option<f64>, mode: ContentMode, ) -> Self
.aspectRatio(_:contentMode:) with the mode named rather than spelled as a
bool.
None for the ratio means “keep whatever the content already has”, which is
not the same as Some(1.0).
Sourcepub fn background(self, r: f64, g: f64, b: f64, a: f64) -> Self
pub fn background(self, r: f64, g: f64, b: f64, a: f64) -> Self
Apply .background(_:) with a Color.
Sourcepub fn background_any_gradient(self, color: u64) -> Self
pub fn background_any_gradient(self, color: u64) -> Self
Apply .background(_:) with an AnyGradient — what .indigo.gradient is.
Sourcepub fn background_content(self, content: View, alignment: Alignment) -> Self
pub fn background_content(self, content: View, alignment: Alignment) -> Self
Apply .background(alignment:content:).
The same call as .overlay(alignment:content:) with a different symbol:
an Alignment in x0/x1, the content closure and its context in x2/x3, four
generic words after that. The colour-taking background next door is a
different overload entirely — that one is generic over ShapeStyle, this
one over View.
Sourcepub fn background_extension_effect(self) -> Self
pub fn background_extension_effect(self) -> Self
Apply .backgroundExtensionEffect(_:).
Sourcepub fn background_in_circle(self) -> Self
pub fn background_in_circle(self) -> Self
Apply .background(in:fillStyle:) — the background style, clipped to a shape.
The shape must be InsettableShape, not merely Shape, so its witness is a
different table from the one super::Shape carries.
Sourcepub fn background_linear_gradient(
self,
colors: &[Color],
start: (f64, f64),
end: (f64, f64),
) -> Self
pub fn background_linear_gradient( self, colors: &[Color], start: (f64, f64), end: (f64, f64), ) -> Self
Apply .background(LinearGradient(colors:startPoint:endPoint:)).
Sourcepub fn background_material(self, kind: MaterialKind) -> Self
pub fn background_material(self, kind: MaterialKind) -> Self
Apply .background(_: Material) — the blur materials.
Sourcepub fn background_radial_gradient(
self,
colors: &[Color],
center: (f64, f64),
start_radius: f64,
end_radius: f64,
) -> Self
pub fn background_radial_gradient( self, colors: &[Color], center: (f64, f64), start_radius: f64, end_radius: f64, ) -> Self
Apply .background(RadialGradient(colors:center:startRadius:endRadius:)).
Sourcepub fn background_style_color(self, r: f64, g: f64, b: f64, a: f64) -> Self
pub fn background_style_color(self, r: f64, g: f64, b: f64, a: f64) -> Self
.backgroundStyle(_:) with a Color.
background_style_of takes the style as raw bytes and a witness, which
is what an arbitrary ShapeStyle needs and what nothing can call without
building one first. These three name the styles that have a Rust spelling,
so the modifier is reachable the way the documentation writes it.
Not .background(_:): that draws behind this view, while this says what
style the views inside should use for their own backgrounds.
Sourcepub fn background_style_hierarchical(self, level: Hierarchical) -> Self
pub fn background_style_hierarchical(self, level: Hierarchical) -> Self
.backgroundStyle(_:) with one of the hierarchical levels.
Sourcepub fn background_style_value(self, color: u64) -> Self
pub fn background_style_value(self, color: u64) -> Self
.backgroundStyle(_:) with an already-resolved Color word.
Sourcepub fn border_value(self, color: u64, width: f64) -> Self
pub fn border_value(self, color: u64, width: f64) -> Self
Apply .border(_:width:) with a Color that is already built.
For one of SwiftUI’s named colours: Color.gray is semantic and no set of
components spells it. See system_color.
Apply .buttonStyle(.glass(.clear)).
.glass(_:) is a static on a PrimitiveButtonStyle extension constrained
to GlassButtonStyle — the shape that has been inlinable every other time
in this file. This one is exported, which is only knowable by looking.
Sourcepub fn clip_rounded_rect(self, radius: f64) -> Self
pub fn clip_rounded_rect(self, radius: f64) -> Self
Apply .clipShape(RoundedRectangle(cornerRadius:)).
Sourcepub fn clip_rounded_rect_styled(self, radius: f64, continuous: bool) -> Self
pub fn clip_rounded_rect_styled(self, radius: f64, continuous: bool) -> Self
Apply .clipShape(RoundedRectangle(cornerRadius:style:)).
As with super::rounded_rectangle_styled, the style is not optional here
even though Swift source can leave it out: leaving it out means
.continuous, and writing case 0 builds the other shape.
Sourcepub fn color_effect(self, shader: &Shader) -> Self
pub fn color_effect(self, shader: &Shader) -> Self
Apply .colorEffect(_:) — recolours each pixel.
Sourcepub fn color_invert(self) -> Self
pub fn color_invert(self) -> Self
Apply .colorInvert(_:).
Sourcepub fn confirmation_message(
self,
title: &str,
actions: View,
message: View,
presented: bool,
) -> Self
pub fn confirmation_message( self, title: &str, actions: View, message: View, presented: bool, ) -> Self
confirmationDialog(…actions:message:) with a fixed flag, which cannot be
dismissed — see confirmation_dialog.
Sourcepub fn container_value<T: KeyValue>(
self,
key: &CustomContainerKey<T>,
value: impl IntoKeyValue<T>,
) -> Self
pub fn container_value<T: KeyValue>( self, key: &CustomContainerKey<T>, value: impl IntoKeyValue<T>, ) -> Self
.containerValue(\.key, value) for a key defined here.
What the @_alwaysEmitIntoClient modifier’s body does, since the modifier
itself exports no symbol: build a _ContainerValueWritingModifier and apply
it with .modifier(_:).
Sourcepub fn corner_radius(self, radius: f64) -> Self
pub fn corner_radius(self, radius: f64) -> Self
Apply .cornerRadius(_:).
Examples found in repository?
632fn decorate(mut v: View, node: &Node) -> Result<View, String> {
633 if let Some(p) = node.f64_attr("pad") {
634 v = v.padding(p);
635 }
636 if let Some(size) = node.attr("frame") {
637 let (w, h) = parse_size(size, node.line)?;
638 v = v.frame(w, h);
639 }
640 if let Some(o) = node.f64_attr("opacity") {
641 v = v.opacity(o);
642 }
643 if let Some(c) = node.attr("bg") {
644 let c = parse_color(c, node.line)?;
645 v = v.bg(c);
646 }
647 if let Some(r) = node.f64_attr("corner") {
648 v = v.corner_radius(r);
649 }
650 Ok(v)
651}Sourcepub fn custom_animation(self, curve: &CustomAnimationCurve, value: i64) -> Self
pub fn custom_animation(self, curve: &CustomAnimationCurve, value: i64) -> Self
.animation(Animation(curve), value:) with a curve written in Rust.
.buttonStyle(_:) with a style written in Rust.
Sourcepub fn custom_label_style(self, style: &CustomLabelStyle) -> Self
pub fn custom_label_style(self, style: &CustomLabelStyle) -> Self
.labelStyle(_:) with a style written in Rust.
Sourcepub fn custom_modifier(self, modifier: &CustomModifier) -> Self
pub fn custom_modifier(self, modifier: &CustomModifier) -> Self
.modifier(_:) with a modifier written in Rust.
The result is ModifiedContent<Self, RustModifier> — a concrete type, not an
opaque one, because modifier<T>(_:) says so. T is unconstrained there, so
no witness table is passed at the call: SwiftUI finds the conformance by
lookup when it renders, which is exactly why registering it matters.
Sourcepub fn custom_transition(self, transition: &CustomTransition) -> Self
pub fn custom_transition(self, transition: &CustomTransition) -> Self
.transition(_:) with a transition written in Rust.
Wrapped in an AnyTransition on the way, because that is what
transition<T: Transition>(_:) does: it is @_alwaysEmitIntoClient and
exports no symbol, so the binding calls what its body calls.
Sourcepub fn delete_disabled(self, value: bool) -> Self
pub fn delete_disabled(self, value: bool) -> Self
Apply .deleteDisabled(_:).
Sourcepub fn dialog_icon(self, system_name: Option<&str>) -> Self
pub fn dialog_icon(self, system_name: Option<&str>) -> Self
Apply .dialogIcon(_:).
Sourcepub fn dialog_prevents_app_termination(self, prevents: Option<bool>) -> Self
pub fn dialog_prevents_app_termination(self, prevents: Option<bool>) -> Self
Apply .dialogPreventsAppTermination(_:).
pub fn dialog_severity(self, value: DialogSeverity) -> Self
Sourcepub fn dialog_suppression_toggle(self, state: &BoundState<bool>) -> Self
pub fn dialog_suppression_toggle(self, state: &BoundState<bool>) -> Self
Apply .dialogSuppressionToggle(isSuppressed:).
Sourcepub fn dialog_suppression_toggle_labelled(
self,
label: &str,
state: &BoundState<bool>,
) -> Self
pub fn dialog_suppression_toggle_labelled( self, label: &str, state: &BoundState<bool>, ) -> Self
Apply .dialogSuppressionToggle(_:isSuppressed:) with a label.
Seven integer arguments — four for the key, three for the binding — so
Self.Type and the witness table travel on the stack rather than in
registers.
Sourcepub fn disable_autocorrection(self, disable: Option<bool>) -> Self
pub fn disable_autocorrection(self, disable: Option<bool>) -> Self
Apply .disableAutocorrection(_:).
Sourcepub fn distortion_effect(self, shader: &Shader, max_w: f64, max_h: f64) -> Self
pub fn distortion_effect(self, shader: &Shader, max_w: f64, max_h: f64) -> Self
Apply .distortionEffect(_:maxSampleOffset:) — warps geometry.
Sourcepub fn drag_gesture(self, minimum_distance: f64) -> Self
pub fn drag_gesture(self, minimum_distance: f64) -> Self
Attach a DragGesture.
Sourcepub fn draggable_text(self, text: &str) -> Self
pub fn draggable_text(self, text: &str) -> Self
Apply .draggable(_:) with a String payload.
The overload everything else calls draggable: drag this view and a piece
of text comes out, droppable anywhere that takes one. The
containerItemID: binding next door is a different modifier for a
different job — reordering within a container.
String because it is the Transferable conformer that needs no bridging:
its witness is exported from CoreTransferable, and its value is two loadable
words. A Data or a URL payload would each need their own.
Sourcepub fn environment_model(self, model: &Model) -> Self
pub fn environment_model(self, model: &Model) -> Self
.environment(model) — put the model where every view below can read it.
The Observable overload. A body that reads a property of the model through
Model::get while SwiftUI is tracking it is re-run when that property
changes; one that reads a different property is not.
Sourcepub fn environment_value<T: KeyValue>(
self,
key: &CustomEnvKey<T>,
value: impl IntoKeyValue<T>,
) -> Self
pub fn environment_value<T: KeyValue>( self, key: &CustomEnvKey<T>, value: impl IntoKeyValue<T>, ) -> Self
.environment(\.key, value) for a key defined here.
Sourcepub fn equatable(self) -> Self
pub fn equatable(self) -> Self
.equatable() — wrap a view in EquatableView, whatever its type.
equatable_text does this for a Text and nothing else, because the
mangled name it resolves names Text. The constraint is
Content: Equatable & View, and whether a given type satisfies it is a
question the runtime can answer — so this asks, instead of the binding
deciding in advance which one type is allowed.
The bound is genuine, not a limitation here: a view erased into AnyView
is not Equatable and cannot be made so. That is what the panic says, and
it is the same thing Swift’s type checker would say at the call site.
Wrapping is the whole of it — equatable() is @inlinable with the body
EquatableView(content: self), and EquatableView stores only its
content, so the value is the content’s own bytes copied through its value
witness. A raw memcpy would work for a Text and leak a reference for
anything holding one.
pub fn file_dialog_browser_options( self, value: FileDialogBrowserOptions, ) -> Self
Sourcepub fn file_dialog_confirmation_label(self, value: &str) -> Self
pub fn file_dialog_confirmation_label(self, value: &str) -> Self
Apply .fileDialogConfirmationLabel(_:).
Sourcepub fn file_dialog_customization_id(self, value: &str) -> Self
pub fn file_dialog_customization_id(self, value: &str) -> Self
Apply .fileDialogCustomizationID(_:).
Sourcepub fn file_dialog_default_directory(self, path: Option<&str>) -> Self
pub fn file_dialog_default_directory(self, path: Option<&str>) -> Self
Apply .fileDialogDefaultDirectory(_:).
Sourcepub fn file_dialog_imports_unresolved_aliases(self, value: bool) -> Self
pub fn file_dialog_imports_unresolved_aliases(self, value: bool) -> Self
Apply .fileDialogImportsUnresolvedAliases(_:).
Sourcepub fn file_dialog_message(self, value: &str) -> Self
pub fn file_dialog_message(self, value: &str) -> Self
Apply .fileDialogMessage(_:).
Sourcepub fn file_dialog_url_enabled(self, enabled: bool) -> Self
pub fn file_dialog_url_enabled(self, enabled: bool) -> Self
Apply .fileDialogURLEnabled(_:).
The argument is a Foundation.Predicate<Pack{URL}>, which the #Predicate
macro normally builds from an expression tree at compile time. Predicate
also exposes .true and .false as statics, and those are values rather
than syntax — so they are reachable from here, where an arbitrary predicate
is not.
The type is generic over a parameter pack, whose mangling closes with
_QP rather than directly; see crate::mangle::pack.
Sourcepub fn file_exporter_filename_label(self, value: &str) -> Self
pub fn file_exporter_filename_label(self, value: &str) -> Self
Apply .fileExporterFilenameLabel(_:).
Sourcepub fn find_disabled(self, value: bool) -> Self
pub fn find_disabled(self, value: bool) -> Self
Apply .findDisabled(_:).
Sourcepub fn flips_for_right_to_left_layout_direction(self, value: bool) -> Self
pub fn flips_for_right_to_left_layout_direction(self, value: bool) -> Self
Apply .flipsForRightToLeftLayoutDirection(_:).
Sourcepub fn focus_effect_disabled(self, value: bool) -> Self
pub fn focus_effect_disabled(self, value: bool) -> Self
Apply .focusEffectDisabled(_:).
Sourcepub fn focus_section(self) -> Self
pub fn focus_section(self) -> Self
Apply .focusSection(_:).
Sourcepub fn focused_on(self, projection: [u64; 3]) -> Self
pub fn focused_on(self, projection: [u64; 3]) -> Self
Apply .focused(_:) with a real, installed @FocusState.
focused applies the same modifier with a FocusState built on the spot,
which is what SwiftUI stores either way but leaves nothing to read or move.
This takes the projection of a property SwiftUI has installed, so
crate::state::ComposedView::focus reports whether the field has focus
and crate::state::ComposedView::set_focus puts it there.
Sourcepub fn focused_scene_object(self) -> Self
pub fn focused_scene_object(self) -> Self
Apply .focusedSceneObject(_:).
Sourcepub fn focused_scene_value<T: KeyValue>(
self,
key: &FocusKey<T>,
value: impl IntoKeyValue<T>,
) -> Self
pub fn focused_scene_value<T: KeyValue>( self, key: &FocusKey<T>, value: impl IntoKeyValue<T>, ) -> Self
.focusedSceneValue(keyPath, value) — publish a value for the whole scene.
What a window tells the menu bar about its selection. The scene form is the
one commands read; focused_value_keyed is the same thing scoped to
whatever currently has focus.
Examples found in repository?
48fn main_window() -> ViewHandle {
49 vstack(&[
50 text("A SwiftUI app, no Swift source")
51 .font_size(20.0)
52 .padding(8.0),
53 divider(),
54 text(&format!("count: {}", counter().get()))
55 .font_size(34.0)
56 .padding(12.0),
57 hstack(&[
58 button("−", || counter().set(counter().get() - 1)),
59 button("+", || counter().set(counter().get() + 1)),
60 ]),
61 spacer(),
62 text("⌘, for Settings · the ★ in the menu bar has a menu")
63 .font_size(11.0)
64 .opacity(0.6),
65 ])
66 .padding(24.0)
67 .frame(420.0, 300.0)
68 .focused_scene_value(counter_focus_key(), counter().get())
69 .into_handle()
70}Sourcepub fn focused_value_keyed<T: KeyValue>(
self,
key: &FocusKey<T>,
value: impl IntoKeyValue<T>,
) -> Self
pub fn focused_value_keyed<T: KeyValue>( self, key: &FocusKey<T>, value: impl IntoKeyValue<T>, ) -> Self
.focusedValue(keyPath, value) — publish a value for the focused view.
Sourcepub fn focused_value_model(self, model: &Model) -> Self
pub fn focused_value_model(self, model: &Model) -> Self
.focusedValue(model) — publish the model for the commands above it.
The object form of what crate::views::focused_scene_value does with a key
path, and the one Apple now recommends: a key is a type, and an @Observable
object already is one.
Sourcepub fn font_apply(self, font: u64) -> Self
pub fn font_apply(self, font: u64) -> Self
Apply an already-built raw Font value with .font(_:).
Sourcepub fn font_custom(self, name: &str, size: f64) -> Self
pub fn font_custom(self, name: &str, size: f64) -> Self
Apply .font(.custom(_:size:)).
Sourcepub fn font_system(
self,
size: f64,
weight: Option<Weight>,
design: Option<Design>,
) -> Self
pub fn font_system( self, size: f64, weight: Option<Weight>, design: Option<Design>, ) -> Self
Apply .font(.system(size:weight:design:)).
Sourcepub fn font_text_style(self, style: TextStyle) -> Self
pub fn font_text_style(self, style: TextStyle) -> Self
Apply .font(_:) with one of the built-in text styles.
Sourcepub fn font_weight(self, weight: Weight) -> Self
pub fn font_weight(self, weight: Weight) -> Self
Apply .fontWeight(_:).
Sourcepub fn foreground_color(self, color: Option<Color>) -> Self
pub fn foreground_color(self, color: Option<Color>) -> Self
Apply .foregroundColor(_:).
Sourcepub fn foreground_color_value(self, color: u64) -> Self
pub fn foreground_color_value(self, color: u64) -> Self
Apply .foregroundColor(_:), the deprecated environment-writing one.
Not foreground_style_color: this produces
_EnvironmentKeyWritingModifier<Color?> and that produces
_ForegroundStyleModifier<Color>. They render the same.
Apply .foregroundColor(_:) to a Color that is already built.
For one of SwiftUI’s named colours, which no set of components can spell.
See super::system_color.
Sourcepub fn foreground_style_color(self, r: f64, g: f64, b: f64, a: f64) -> Self
pub fn foreground_style_color(self, r: f64, g: f64, b: f64, a: f64) -> Self
Apply .foregroundStyle(_:) with a colour.
Named for what it does, not for .foregroundColor(_:) — which is deprecated
and a different thing: it writes an environment key, producing
_EnvironmentKeyWritingModifier<Color?> where this produces
_ForegroundStyleModifier<Color>. The two render alike, so only a
type-level comparison tells them apart. See foreground_color for the
other one.
Sourcepub fn foreground_style_hierarchical(self, level: Hierarchical) -> Self
pub fn foreground_style_hierarchical(self, level: Hierarchical) -> Self
Apply .foregroundStyle(.linearGradient(colors:startPoint:endPoint:)).
The shorthand in Swift source is a protocol-extension static marked
@inlinable, so it has no symbol; the LinearGradient it builds does.
Apply .foregroundStyle(_:) with one of the hierarchical levels —
.secondary and friends.
pub fn foreground_style_linear_gradient( self, colors: &[u64], start: (f64, f64), end: (f64, f64), ) -> Self
Sourcepub fn foreground_style_pair(self, primary: u64, secondary: u64) -> Self
pub fn foreground_style_pair(self, primary: u64, secondary: u64) -> Self
Apply .foregroundStyle(_:_:) — a primary and a secondary style.
What symbolRenderingMode(.palette) needs: a palette symbol takes its
layers from successive styles, and with only one it renders as monochrome.
Sourcepub fn foreground_style_triple(
self,
primary: u64,
secondary: u64,
tertiary: u64,
) -> Self
pub fn foreground_style_triple( self, primary: u64, secondary: u64, tertiary: u64, ) -> Self
Apply .foregroundStyle(_:_:_:) — three styles.
A palette symbol takes its layers from successive styles.
foreground_style_pair covers the two-layer symbols; the three-layer
ones — and there are plenty in SF Symbols — rendered their third layer in
the secondary colour, because there was no way to say what it should be.
Eleven words of arguments, so three spill: the three style addresses and
Self.Type fill x0–x3, the three style types and the Self: View witness
take x4–x7, and all three ShapeStyle witnesses go to the stack.
Spilling only two of them — which is easy to do, since the pair version next
door fits in eight words exactly and spills none — left the callee reading a
stale word as a witness table. It did not fault there: it faulted much later
inside swift::MetadataCacheKey::operator==, recursing on a type built from
the garbage, which is what an argument-count mistake looks like from the
outside.
Sourcepub fn foreground_style_value(self, color: u64) -> Self
pub fn foreground_style_value(self, color: u64) -> Self
Apply .foregroundStyle(_:) to a Color that is already built.
The components overload above cannot express Color.blue: SwiftUI’s named
colours are semantic, not literal, and resolve per appearance — the aqua
Color.blue is nowhere near (0, 0, 1). This takes the value a static
getter handed back instead. See super::system_color.
Sourcepub fn frame_max_infinity(self, alignment: Alignment) -> Self
pub fn frame_max_infinity(self, alignment: Alignment) -> Self
Apply .frame(maxWidth:maxHeight:alignment:) with .infinity for both.
Six Optional<CGFloat>s — min, ideal and max for each axis — then an
Alignment, then the two generic words. Each optional is payload and tag,
so that is sixteen words in all: x0 through x7 carry the first four
optionals and the remaining eight go on the stack. The generic arguments
come after every formal parameter, which is what makes them spill; putting
them in x6 and x7 builds a frame out of the metadata pointers.
Sourcepub fn frame_max_width(self, alignment: Alignment) -> Self
pub fn frame_max_width(self, alignment: Alignment) -> Self
Apply .frame(maxWidth: .infinity) — the width only.
Not frame_max_infinity, which sets both axes. Swift’s
.frame(maxWidth: .infinity) leaves maxHeight nil, so the view keeps its
content’s height; setting both stretched a card to fill its canvas and moved
everything in it.
Six Optional<CGFloat>s — min, ideal and max for each axis — then an
Alignment, then the two generic words. Each optional is payload and tag,
so that is sixteen words in all: x0 through x7 carry the first four
optionals and the remaining eight go on the stack. The generic arguments
come after every formal parameter, which is what makes them spill; putting
them in x6 and x7 builds a frame out of the metadata pointers.
Sourcepub fn gesture<V: GestureData>(
self,
g: &GestureValue<V>,
mask: GestureMask,
) -> Self
pub fn gesture<V: GestureData>( self, g: &GestureValue<V>, mask: GestureMask, ) -> Self
.gesture(_:including:).
Sourcepub fn glass_effect(self) -> Self
pub fn glass_effect(self) -> Self
Apply .glassEffect() — Liquid Glass, in its default shape.
The result type is a StaticIf<GlassEnabledPredicate, ...>: SwiftUI picks
between the glass-modified view and the original at runtime depending on
whether the platform has Liquid Glass enabled.
Sourcepub fn glass_effect_id<'h>(self, id: Option<impl IntoHashable<'h>>) -> Self
pub fn glass_effect_id<'h>(self, id: Option<impl IntoHashable<'h>>) -> Self
Apply .glassEffectID(_:in:).
Sourcepub fn glass_effect_kind(self, glass: Glass) -> Self
pub fn glass_effect_kind(self, glass: Glass) -> Self
The same, with the variant named.
Identity is the no-op: it still builds the StaticIf, so the view’s type
is the one a glass effect gives it, with nothing drawn. That is what makes
it usable as the “off” end of a condition without the two branches
disagreeing about their type.
pub fn glass_effect_transition(self, value: GlassEffectTransition) -> Self
Sourcepub fn glass_effect_union<'h>(self, id: Option<impl IntoHashable<'h>>) -> Self
pub fn glass_effect_union<'h>(self, id: Option<impl IntoHashable<'h>>) -> Self
Apply .glassEffectUnion(id:namespace:).
Sourcepub fn grid_cell_columns(self, value: i64) -> Self
pub fn grid_cell_columns(self, value: i64) -> Self
Apply .gridCellColumns(_:).
Sourcepub fn high_priority_gesture_of<V: GestureData>(
self,
g: &GestureValue<V>,
mask: GestureMask,
) -> Self
pub fn high_priority_gesture_of<V: GestureData>( self, g: &GestureValue<V>, mask: GestureMask, ) -> Self
.highPriorityGesture(_:including:) — this gesture wins over the view’s own.
Sourcepub fn horizontal_radio_group_layout(self) -> Self
pub fn horizontal_radio_group_layout(self) -> Self
Apply .horizontalRadioGroupLayout(_:).
Sourcepub fn interaction_activity_tracking_tag(self, value: &str) -> Self
pub fn interaction_activity_tracking_tag(self, value: &str) -> Self
Apply .interactionActivityTrackingTag(_:).
Sourcepub fn interactive_dismiss_disabled(self, value: bool) -> Self
pub fn interactive_dismiss_disabled(self, value: bool) -> Self
Apply .interactiveDismissDisabled(_:).
Sourcepub fn invalidatable_content(self, value: bool) -> Self
pub fn invalidatable_content(self, value: bool) -> Self
Apply .invalidatableContent(_:).
Sourcepub fn label_icon_to_title_spacing(self, value: f64) -> Self
pub fn label_icon_to_title_spacing(self, value: f64) -> Self
Apply .labelIconToTitleSpacing(_:).
Sourcepub fn label_reserved_icon_width(self, value: f64) -> Self
pub fn label_reserved_icon_width(self, value: f64) -> Self
Apply .labelReservedIconWidth(_:).
Apply .labelsHidden(_:).
Sourcepub fn layer_effect(self, shader: &Shader, max_w: f64, max_h: f64) -> Self
pub fn layer_effect(self, shader: &Shader, max_w: f64, max_h: f64) -> Self
Apply .layerEffect(_:maxSampleOffset:) — can sample neighbouring pixels.
Sourcepub fn layout_priority(self, value: f64) -> Self
pub fn layout_priority(self, value: f64) -> Self
Apply .layoutPriority(_:).
Sourcepub fn layout_value_int(self, value: i64) -> Self
pub fn layout_value_int(self, value: i64) -> Self
Apply .layoutValue(key:value:) with a runtime-synthesized key.
A second protocol through the same machinery as preference_int, to show
nothing about it is specific to PreferenceKey.
Sourcepub fn list_item_tint(self, tint: Option<ListItemTint>) -> Self
pub fn list_item_tint(self, tint: Option<ListItemTint>) -> Self
Apply .listItemTint(_:).
None clears the tint, which is the nil the modifier’s ListItemTint?
parameter takes.
Sourcepub fn long_press_gesture(self, duration: f64, max_distance: f64) -> Self
pub fn long_press_gesture(self, duration: f64, max_distance: f64) -> Self
Attach a LongPressGesture with .gesture(_:including:).
Sourcepub fn luminance_to_alpha(self) -> Self
pub fn luminance_to_alpha(self) -> Self
Apply .luminanceToAlpha(_:).
Sourcepub fn magnify_gesture(self, minimum_scale_delta: f64) -> Self
pub fn magnify_gesture(self, minimum_scale_delta: f64) -> Self
Attach a MagnifyGesture.
Sourcepub fn minimum_scale_factor(self, value: f64) -> Self
pub fn minimum_scale_factor(self, value: f64) -> Self
Apply .minimumScaleFactor(_:).
Sourcepub fn monospaced_digit(self) -> Self
pub fn monospaced_digit(self) -> Self
Apply .monospacedDigit(_:).
Sourcepub fn move_disabled(self, value: bool) -> Self
pub fn move_disabled(self, value: bool) -> Self
Apply .moveDisabled(_:).
Sourcepub fn multiline_alignment(self, align: TextAlign) -> Self
pub fn multiline_alignment(self, align: TextAlign) -> Self
Apply .multilineTextAlignment(_:).
Apply .navigationBarBackButtonHidden(_:).
Apply .navigationSplitViewStyle(_:).
Apply .navigationSubtitle(_:).
Apply .navigationSubtitle(_:).
.navigationViewStyle(.columns) — the two-column split.
The witness is looked up at run time rather than named: a
NavigationViewStyle conformance mangles its substitutions against the
words in its own type name, so ColumnNavigationViewStyle’s is not
DefaultNavigationViewStyle’s with a letter changed. Copying one has
produced a witness for the wrong protocol in this crate before.
.navigationViewStyle(.doubleColumn) — sidebar plus detail.
Sourcepub fn on_continuous_hover(
self,
space: CoordinateSpace,
perform: impl Fn(HoverPhase) + 'static,
) -> Self
pub fn on_continuous_hover( self, space: CoordinateSpace, perform: impl Fn(HoverPhase) + 'static, ) -> Self
Apply .onContinuousHover(coordinateSpace:perform:).
Sourcepub fn on_drag_ended_value(
self,
minimum_distance: f64,
action: impl Fn(DragValue) + 'static,
) -> Self
pub fn on_drag_ended_value( self, minimum_distance: f64, action: impl Fn(DragValue) + 'static, ) -> Self
The same, with the value SwiftUI delivered.
on_drag_gesture’s handler is told only that a drag ended. This one is
told where it started, where it finished and how fast it was going — see
DragValue.
Sourcepub fn on_drag_gesture(
self,
minimum_distance: f64,
action: impl Fn() + 'static,
) -> Self
pub fn on_drag_gesture( self, minimum_distance: f64, action: impl Fn() + 'static, ) -> Self
Attach a DragGesture with an onEnded handler.
drag_gesture attaches a bare DragGesture with nothing listening, which
builds the same value Swift would but can never be seen to fire. This wires
the action SwiftUI calls when the drag ends, so the gesture is observable.
The result type is taken from .gesture’s opaque-result-type descriptor
rather than a hand-written mangling: the type is
ModifiedContent<AnyView, AddGestureModifier<_EndedGesture<DragGesture>, _>>,
and spelling that out by hand is how earlier bindings resolved to null.
Sourcepub fn on_long_press_gesture(
self,
duration: f64,
max_distance: f64,
action: impl Fn() + 'static,
) -> Self
pub fn on_long_press_gesture( self, duration: f64, max_distance: f64, action: impl Fn() + 'static, ) -> Self
Apply .onLongPressGesture(minimumDuration:maximumDistance:pressing:perform:).
Unlike long_press_gesture, which attaches a bare LongPressGesture with
nothing listening, this takes the action SwiftUI runs when the press
completes — so the gesture can be observed rather than only built.
Sourcepub fn on_magnify_ended(
self,
minimum_scale_delta: f64,
action: impl Fn(MagnifyValue) + 'static,
) -> Self
pub fn on_magnify_ended( self, minimum_scale_delta: f64, action: impl Fn(MagnifyValue) + 'static, ) -> Self
Attach a MagnifyGesture with an onEnded handler.
Sourcepub fn on_pencil_double_tap(self, action: impl Fn() + 'static) -> Self
pub fn on_pencil_double_tap(self, action: impl Fn() + 'static) -> Self
Apply .onPencilDoubleTap(perform:).
Sourcepub fn on_pencil_squeeze(self, action: impl Fn() + 'static) -> Self
pub fn on_pencil_squeeze(self, action: impl Fn() + 'static) -> Self
Apply .onPencilSqueeze(perform:).
Sourcepub fn on_preference_change_int(self) -> Self
pub fn on_preference_change_int(self) -> Self
Apply .onPreferenceChange(_:perform:), recording the value.
The value is read back through observed_preference. K.Value must also
be Equatable here, so the call carries two witness tables for the one
generic parameter.
Sourcepub fn on_rotate_ended(
self,
minimum_degrees: f64,
action: impl Fn(RotateValue) + 'static,
) -> Self
pub fn on_rotate_ended( self, minimum_degrees: f64, action: impl Fn(RotateValue) + 'static, ) -> Self
Attach a RotateGesture with an onEnded handler.
Sourcepub fn on_tap_gesture(self, count: i64, action: impl Fn() + 'static) -> Self
pub fn on_tap_gesture(self, count: i64, action: impl Fn() + 'static) -> Self
Apply .onTapGesture(count:perform:).
The action may capture, as super::button’s may — a tap handler that
cannot know which row it is on is one every list has to route around.
Sourcepub fn padding_insets(self, insets: EdgeInsets) -> Self
pub fn padding_insets(self, insets: EdgeInsets) -> Self
.padding(_: EdgeInsets) — a different inset per edge.
padding_set takes one length for a set of edges; this takes four. The
insets go in d0–d3, being a homogeneous float aggregate.
Sourcepub fn padding_set(self, edges: EdgeSet, length: Option<f64>) -> Self
pub fn padding_set(self, edges: EdgeSet, length: Option<f64>) -> Self
Apply .padding(_:_:) — chosen edges, an explicit length.
edges is an Edge.Set bit pattern: 1 top, 2 leading, 4 bottom, 8 trailing,
so .vertical is 5 and .all is 15. A None length means the system’s own
inset, as in padding_default.
.padding(_:_:) with the edges named rather than spelled as a bitmask.
padding_edges takes the raw option-set bits, which a caller has to know;
this reads the member out of SwiftUI’s own Edge.Set instead.
Sourcepub fn preference_int(self, value: i64) -> Self
pub fn preference_int(self, value: i64) -> Self
Apply .preference(key:value:) with a runtime-synthesized key.
The key type carries a PreferenceKey conformance built by
crate::conformance at run time, and its Value is Int. No Swift
source declares it, which is the whole point: this is the one family of
modifiers that expects the client to supply a conformance.
Sourcepub fn preferred_color_scheme(self, scheme: ColorScheme) -> Self
pub fn preferred_color_scheme(self, scheme: ColorScheme) -> Self
Apply .preferredColorScheme(_:) — light or dark for this subtree.
Sourcepub fn presented_window_style(self, style: WindowStyle) -> Self
pub fn presented_window_style(self, style: WindowStyle) -> Self
Apply .presentedWindowStyle(_:).
Sourcepub fn presented_window_toolbar_style(self, style: WindowToolbarStyle) -> Self
pub fn presented_window_toolbar_style(self, style: WindowToolbarStyle) -> Self
Apply .presentedWindowToolbarStyle(_:).
Sourcepub fn preview_context(self) -> Self
pub fn preview_context(self) -> Self
Apply .previewContext(_:).
Sourcepub fn preview_device(self, name: Option<&str>) -> Self
pub fn preview_device(self, name: Option<&str>) -> Self
Apply .previewDevice(_:).
Sourcepub fn preview_display_name(self, name: Option<&str>) -> Self
pub fn preview_display_name(self, name: Option<&str>) -> Self
Apply .previewDisplayName(_:).
pub fn preview_interface_orientation(self, value: InterfaceOrientation) -> Self
Sourcepub fn preview_layout(self, layout: PreviewLayout) -> Self
pub fn preview_layout(self, layout: PreviewLayout) -> Self
Apply .previewLayout(_:).
Sourcepub fn privacy_sensitive(self, value: bool) -> Self
pub fn privacy_sensitive(self, value: bool) -> Self
Apply .privacySensitive(_:).
Sourcepub fn progress_view_style(self, style: ProgressStyle) -> Self
pub fn progress_view_style(self, style: ProgressStyle) -> Self
Apply .progressViewStyle(_:).
Not missing after all. Searching the export table for progressViewStyle
finds nothing because the mangling compresses ViewStyle to
08progressC5Style — C substitutes the View of the enclosing
SwiftUI.View — so the spelled-out name never appears. The SIL for one line
of Swift names it outright.
.linear and .automatic are @_alwaysEmitIntoClient statics with no
symbol of their own; the structs they return have plain initialisers, which
is what this needs.
Sourcepub fn replace_disabled(self, value: bool) -> Self
pub fn replace_disabled(self, value: bool) -> Self
Apply .replaceDisabled(_:).
Sourcepub fn rotate_gesture(self, minimum_degrees: f64) -> Self
pub fn rotate_gesture(self, minimum_degrees: f64) -> Self
Attach a RotateGesture. The minimum delta is an Angle, i.e. radians.
Sourcepub fn rotation(self, degrees: f64, anchor_x: f64, anchor_y: f64) -> Self
pub fn rotation(self, degrees: f64, anchor_x: f64, anchor_y: f64) -> Self
Apply .rotationEffect(.degrees(_), anchor:).
Sourcepub fn rotation_3d(self, degrees: f64, ax: f64, ay: f64, az: f64) -> Self
pub fn rotation_3d(self, degrees: f64, ax: f64, ay: f64, az: f64) -> Self
Apply .rotation3DEffect(_:axis:).
Sourcepub fn scaled_to_fill(self) -> Self
pub fn scaled_to_fill(self) -> Self
Apply .scaledToFill(_:).
Sourcepub fn scaled_to_fit(self) -> Self
pub fn scaled_to_fit(self) -> Self
Apply .scaledToFit(_:).
Sourcepub fn scene_padding(self, v0: ScenePadding, v1: EdgeSet) -> Self
pub fn scene_padding(self, v0: ScenePadding, v1: EdgeSet) -> Self
Apply .scenePadding(_:).
Sourcepub fn scroll_clip_disabled(self, value: bool) -> Self
pub fn scroll_clip_disabled(self, value: bool) -> Self
Apply .scrollClipDisabled(_:).
Sourcepub fn scroll_disabled(self, value: bool) -> Self
pub fn scroll_disabled(self, value: bool) -> Self
Apply .scrollDisabled(_:).
Sourcepub fn scroll_position_edge(self, edge: Edge) -> Self
pub fn scroll_position_edge(self, edge: Edge) -> Self
.scrollPosition(_:anchor:) — scroll to an edge, and stay bound to it.
scroll_position_id is the other overload, which scrolls to a row by its
identity. This one takes a whole ScrollPosition, which is what
“scrolled to the top” is: there is no row to name.
The position lives in the binding for the life of the view. SwiftUI writes back as the user scrolls, so it has to be somewhere that outlives the call that made it.
Sourcepub fn search_completion(self, value: &str) -> Self
pub fn search_completion(self, value: &str) -> Self
Apply .searchCompletion(_:).
.signInWithAppleButtonStyle(_:).
Declared on View in the overlay, so its mangled name says SwiftUI.View
with the overlay as the extension’s module — which is why it resolves in the
overlay’s image and not in SwiftUI’s.
Sourcepub fn simultaneous_gesture_of<V: GestureData>(
self,
g: &GestureValue<V>,
mask: GestureMask,
) -> Self
pub fn simultaneous_gesture_of<V: GestureData>( self, g: &GestureValue<V>, mask: GestureMask, ) -> Self
.simultaneousGesture(_:including:) — both this and the view’s own run.
Sourcepub fn speech_adjusted_pitch(self, value: f64) -> Self
pub fn speech_adjusted_pitch(self, value: f64) -> Self
Apply .speechAdjustedPitch(_:).
Sourcepub fn speech_always_includes_punctuation(self, value: bool) -> Self
pub fn speech_always_includes_punctuation(self, value: bool) -> Self
Apply .speechAlwaysIncludesPunctuation(_:).
Sourcepub fn speech_announcements_queued(self, value: bool) -> Self
pub fn speech_announcements_queued(self, value: bool) -> Self
Apply .speechAnnouncementsQueued(_:).
Sourcepub fn speech_spells_out_characters(self, value: bool) -> Self
pub fn speech_spells_out_characters(self, value: bool) -> Self
Apply .speechSpellsOutCharacters(_:).
Sourcepub fn submit_scope(self, value: bool) -> Self
pub fn submit_scope(self, value: bool) -> Self
Apply .submitScope(_:).
Sourcepub fn symbol_color_rendering_mode(self, mode: SymbolColorRendering) -> Self
pub fn symbol_color_rendering_mode(self, mode: SymbolColorRendering) -> Self
Apply .symbolColorRenderingMode(_:).
Sourcepub fn symbol_effect(self, effect: SymbolEffect) -> Self
pub fn symbol_effect(self, effect: SymbolEffect) -> Self
.symbolEffect(_:) with any of the indefinite effects.
The case tag is read from the enum’s reflection rather than written down:
SymbolEffectConfiguration.Effect numbers its cases in declaration order,
which is not the order the documentation lists them — .variableColor is 2
and .scale is 3, where reading down the page would say otherwise. A wrong
tag builds a valid value of the wrong case, which renders, and renders
wrongly. See abi::enum_case_index.
Sourcepub fn symbol_variable_value_mode(self, mode: SymbolVariableValue) -> Self
pub fn symbol_variable_value_mode(self, mode: SymbolVariableValue) -> Self
Apply .symbolVariableValueMode(_:).
Sourcepub fn tab_view_customization(self) -> Self
pub fn tab_view_customization(self) -> Self
.tabViewCustomization(_:) with a live customization, not nil.
tab_view_customization_none passes nil, which is the “do not persist
anything” case and the only one that needed no value. This builds a real
TabViewCustomization and hands SwiftUI a binding to it, so the user’s
reordering and hiding of tabs is kept — the whole point of the modifier.
The value lives in the binding’s closures for the life of the process: a customization SwiftUI can write back to has to outlive the call that made it, and there is nowhere else to put it.
Sourcepub fn tab_view_search_activation(self, activation: TabSearchActivation) -> Self
pub fn tab_view_search_activation(self, activation: TabSearchActivation) -> Self
.tabViewSearchActivation(_:).
Sourcepub fn tab_view_style(self, style: TabStyle) -> Self
pub fn tab_view_style(self, style: TabStyle) -> Self
Apply .tabViewStyle(_:).
Sourcepub fn task_once(
self,
priority: TaskPriority,
file: &str,
line: i64,
action: impl Fn() + Send + Sync + 'static,
) -> Self
pub fn task_once( self, priority: TaskPriority, file: &str, line: i64, action: impl Fn() + Send + Sync + 'static, ) -> Self
Apply .task { … } — the spelling with no id:.
A different modifier from task, not a default-argument version of it:
that one builds _TaskValueModifier2<ID> and re-runs when the id changes,
this one builds _TaskModifier2 and runs once. _TaskModifier2 is not
generic, so there are no generic words to spill.
The name carries the call site — SwiftUI records View.task @ file:line —
so a value comparison against a reference only agrees if the caller passes
the reference’s own file and line, which is why they are parameters.
Sourcepub fn text_baseline_offset(self, amount: f64) -> Self
pub fn text_baseline_offset(self, amount: f64) -> Self
Text.baselineOffset(_:)
Sourcepub fn text_bold(self) -> Self
pub fn text_bold(self) -> Self
Text.bold() — the one that returns Text.
Returns the View extension’s result if this is not a Text: that is what a
caller wants there, and it is what every one of these used to do.
Sourcepub fn text_font(self, font: Option<&Font>) -> Self
pub fn text_font(self, font: Option<&Font>) -> Self
Text.font(_:) — the overload that returns Text.
Text("x").font(.body).bold() stays a Text all the way through in Swift
precisely because this returns one; going through the View extension for
the font is what made the rest of the chain fall back to the environment
forms. None clears the font.
Sourcepub fn text_font_weight(self, weight: Option<Weight>) -> Self
pub fn text_font_weight(self, weight: Option<Weight>) -> Self
Text.fontWeight(_:) — the overload that returns Text.
Font.Weight? lowers to two words, a payload and a tag, which land ahead of
self — so this is the one shape the single-word helper cannot serve.
None clears the weight.
Sourcepub fn text_foreground_color(self, color: Color) -> Self
pub fn text_foreground_color(self, color: Color) -> Self
Text.foregroundColor(_:) — the overload that returns Text.
Sourcepub fn text_foreground_hierarchical(self, level: Hierarchical) -> Self
pub fn text_foreground_hierarchical(self, level: Hierarchical) -> Self
Text.foregroundStyle(_:) with one of the hierarchical styles.
Sourcepub fn text_foreground_linear_gradient(
self,
colors: &[u64],
start: (f64, f64),
end: (f64, f64),
) -> Self
pub fn text_foreground_linear_gradient( self, colors: &[u64], start: (f64, f64), end: (f64, f64), ) -> Self
Text.foregroundStyle(LinearGradient(...)).
Sourcepub fn text_input_completion(self, value: &str) -> Self
pub fn text_input_completion(self, value: &str) -> Self
Apply .textInputCompletion(_:).
Sourcepub fn text_italic(self) -> Self
pub fn text_italic(self) -> Self
Text.italic()
Sourcepub fn text_kerning(self, amount: f64) -> Self
pub fn text_kerning(self, amount: f64) -> Self
Text.kerning(_:) — space added between every pair of characters.
Sourcepub fn text_monospaced(self) -> Self
pub fn text_monospaced(self) -> Self
Text.monospaced(_:)
Sourcepub fn text_tracking(self, amount: f64) -> Self
pub fn text_tracking(self, amount: f64) -> Self
Text.tracking(_:) — like kerning, but not suppressed between the pairs the
font has a ligature for.
Sourcepub fn tint_color(self, color: u64) -> Self
pub fn tint_color(self, color: u64) -> Self
Apply .tint(_:) through the Color? overload.
View.tint has two: one generic over ShapeStyle, which tint calls and
which yields _EnvironmentKeyWritingModifier<AnyShapeStyle?>, and one taking
a plain Color?, which yields …<Color?>. Swift picks the second for
.tint(.white), so a reference written that way disagrees with the first on
both type and value.
Sourcepub fn toolbar_customizable_placed(
self,
toolbar_id: &str,
item_id: &str,
placement: ToolbarItemPlacement,
shows_by_default: bool,
content: View,
) -> Self
pub fn toolbar_customizable_placed( self, toolbar_id: &str, item_id: &str, placement: ToolbarItemPlacement, shows_by_default: bool, content: View, ) -> Self
The same, with the item placed somewhere other than .automatic.
Apply .toolbarItemHidden(_:).
Sourcepub fn toolbar_placed(
self,
placement: ToolbarItemPlacement,
content: View,
) -> Self
pub fn toolbar_placed( self, placement: ToolbarItemPlacement, content: View, ) -> Self
Apply .toolbar { ToolbarItem(placement:) { content } }.
toolbar above is this with .automatic, which is what the placement
argument defaults to in Swift.
Sourcepub fn touch_bar_customization_label(self, value: &str) -> Self
pub fn touch_bar_customization_label(self, value: &str) -> Self
Apply .touchBarCustomizationLabel(_:).
Sourcepub fn touch_bar_item_presence(
self,
presence: TouchBarItemPresence,
identifier: &str,
) -> Self
pub fn touch_bar_item_presence( self, presence: TouchBarItemPresence, identifier: &str, ) -> Self
Apply .touchBarItemPresence(_:).
The enum holds a String, which makes it larger than four words and so
address-only: the argument is a pointer to a buffer this builds, with the
string’s two words written first and the tag injected by the enum’s own
witness afterwards.
Sourcepub fn touch_bar_item_principal(self, value: bool) -> Self
pub fn touch_bar_item_principal(self, value: bool) -> Self
Apply .touchBarItemPrincipal(_:).
Sourcepub fn transform_preference_double(self) -> Self
pub fn transform_preference_double(self) -> Self
Apply .transformPreference(_:_:), doubling the value in place.
Sourcepub fn transition_opacity(self) -> Self
pub fn transition_opacity(self) -> Self
Apply .transition(.opacity).
AnyTransition is eight bytes — a single class reference — so it is
loadable: its static getters return it in x0 and it is passed by value.
Reading it through an indirect (x8) return, as the larger resilient types
like Material and Glass require, yields an uninitialised buffer whose
contents are then released as if they were an object.
Sourcepub fn transition_slide(self) -> Self
pub fn transition_slide(self) -> Self
Apply .transition(.slide) — in from the leading edge, out to the trailing.
Sourcepub fn typesetting_language(self, v0: TypesettingLanguage, v1: bool) -> Self
pub fn typesetting_language(self, v0: TypesettingLanguage, v1: bool) -> Self
Apply .typesettingLanguage(_:).
Sourcepub fn unredacted(self) -> Self
pub fn unredacted(self) -> Self
Apply .unredacted(_:).
Sourcepub fn view_opacity(self, value: f64) -> Self
pub fn view_opacity(self, value: f64) -> Self
.opacity(_:), taking Color’s own overload when the receiver is a Color.
Color.opacity(_:) returns Color — the same shape as Text.bold() and
Image.resizable(), and the reason Apple’s Color.primary.opacity(0.1)
types as a plain Color where the View extension gives
ModifiedContent<Color, _OpacityEffect>. Both render identically; only one
is the type the listing has.
pub fn window_dismiss_behavior(self, value: WindowInteractionBehavior) -> Self
pub fn window_full_screen_behavior( self, value: WindowInteractionBehavior, ) -> Self
pub fn window_minimize_behavior(self, value: WindowInteractionBehavior) -> Self
pub fn window_resize_behavior(self, value: WindowInteractionBehavior) -> Self
pub fn window_toolbar_full_screen_visibility( self, value: WindowToolbarFullScreenVisibility, ) -> Self
Sourcepub fn writing_direction(self, strategy: WritingDirectionStrategy) -> Self
pub fn writing_direction(self, strategy: WritingDirectionStrategy) -> Self
Apply .writingDirection(strategy:).
Sourcepub fn writing_tools_affordance_visibility(self, value: Visibility) -> Self
pub fn writing_tools_affordance_visibility(self, value: Visibility) -> Self
Apply .writingToolsAffordanceVisibility(_:).
pub fn writing_tools_behavior(self, value: WritingToolsBehavior) -> Self
Source§impl View
impl View
Sourcepub fn foreground_style<S: ShapeStyleArg>(self, style: S) -> Self
pub fn foreground_style<S: ShapeStyleArg>(self, style: S) -> Self
.foregroundStyle(_:) — one spelling for every style.
The argument’s type picks the binding, the way its conformance does in
Swift. See ShapeStyleArg.
Source§impl View
impl View
Sourcepub fn background_style<S: BackgroundStyleArg>(self, style: S) -> Self
pub fn background_style<S: BackgroundStyleArg>(self, style: S) -> Self
.backgroundStyle(_:) — one spelling for every style.
The style the views inside this one use for their backgrounds, which
is a different question from what View::background draws
behind this one. See BackgroundStyleArg.
Source§impl View
impl View
Sourcepub fn environment<V: EnvironmentArg>(self, value: V) -> Self
pub fn environment<V: EnvironmentArg>(self, value: V) -> Self
.environment(_:_:) — one spelling for every property.
See EnvironmentArg. The leading-dot caveat from ShapeStyleArg
applies: name the value’s type rather than writing .environment(.large).
.navigationViewStyle(_:).
Sourcepub unsafe fn modifier(self, modifier_meta: *const c_void, bytes: &[u8]) -> Self
pub unsafe fn modifier(self, modifier_meta: *const c_void, bytes: &[u8]) -> Self
.modifier(_:) — apply a ViewModifier this crate has no name for.
The escape hatch. Every bound modifier goes through this internally; exposing it means a SwiftUI modifier type the crate has never heard of can still be applied, given its metadata and the bytes of a value.
§Safety
modifier_meta must be metadata for a type conforming to
ViewModifier, and bytes a live value of exactly that type. Neither
is checked: a mismatch hands SwiftUI a value of the wrong shape and it
writes through it.
Sourcepub fn accessibility(self, what: Accessibility<'_>) -> Self
pub fn accessibility(self, what: Accessibility<'_>) -> Self
.accessibility(…) — the deprecated family, under its Swift name.
See Accessibility. New code should prefer the modern spellings,
which are separate methods here as they are in Swift.
Sourcepub fn draggable(self, payload: Draggable<'_>) -> Self
pub fn draggable(self, payload: Draggable<'_>) -> Self
.draggable(_:) — what comes out when this view is dragged.
Sourcepub fn scroll_position(self, target: ScrollTarget<'_>) -> Self
pub fn scroll_position(self, target: ScrollTarget<'_>) -> Self
.scrollPosition(_:) — where the scroll view should sit.
Sourcepub fn transform_environment<K: EnvKey>(
self,
action: impl Fn(K::Value) -> K::Value + 'static,
) -> Self
pub fn transform_environment<K: EnvKey>( self, action: impl Fn(K::Value) -> K::Value + 'static, ) -> Self
.transformEnvironment(_:transform:) — read a property, change it,
write it back for everything below.
The key is the type parameter, the way the key path is the argument in Swift:
text("x").transform_environment::<ColorSchemeKey>(|_| ColorScheme::Dark);Sourcepub fn default_app_storage(self, store: AppStorageStore<'_>) -> Self
pub fn default_app_storage(self, store: AppStorageStore<'_>) -> Self
.defaultAppStorage(_:).
Panics on a suite name UserDefaults refuses — the app’s own bundle
identifier, or the global domain. views::default_app_storage_suite
returns the None instead, for a caller that wants to handle it.
Source§impl View
impl View
Sourcepub fn rotation_effect(self, degrees: f64) -> Self
pub fn rotation_effect(self, degrees: f64) -> Self
.rotationEffect(_:) — View::rotation about the centre, which is
the anchor SwiftUI defaults to.
Sourcepub fn rotation_3d_effect(self, degrees: f64, ax: f64, ay: f64, az: f64) -> Self
pub fn rotation_3d_effect(self, degrees: f64, ax: f64, ay: f64, az: f64) -> Self
.rotation3DEffect(_:axis:) — View::rotation_3d under SwiftUI’s
name.
Sourcepub fn scale_effect(self, sx: f64, sy: f64) -> Self
pub fn scale_effect(self, sx: f64, sy: f64) -> Self
.scaleEffect(x:y:) — View::scale under SwiftUI’s name.
Sourcepub fn multiline_text_alignment(self, align: TextAlign) -> Self
pub fn multiline_text_alignment(self, align: TextAlign) -> Self
.multilineTextAlignment(_:) — View::multiline_alignment under
SwiftUI’s name.
Source§impl View
impl View
Sourcepub fn clip_shape<S: ClipShapeArg>(self, shape: S) -> Self
pub fn clip_shape<S: ClipShapeArg>(self, shape: S) -> Self
.clipShape(_:) — one spelling for every shape.
v.clip_shape(ClipShape::Circle)
.clip_shape(ClipShape::RoundedRect(8.0));Source§impl View
impl View
Sourcepub fn bg(self, c: Color) -> Self
pub fn bg(self, c: Color) -> Self
Apply .background(_:) with a color.
Examples found in repository?
9fn main() {
10 run(|| {
11 vstack(&[
12 text("Hello from Rust! 🦀")
13 .padding(12.0)
14 .bg(Color::BLUE)
15 .rounded(8.0)
16 .opacity(0.95),
17 spacer(),
18 hstack(&[
19 image("star.fill"),
20 text("No Swift compiler needed"),
21 ]),
22 divider(),
23 text("Pure dlsym + arm64 asm → SwiftUI")
24 .padding(8.0),
25 ])
26 .padding(40.0)
27 .into_handle()
28 });
29}More examples
632fn decorate(mut v: View, node: &Node) -> Result<View, String> {
633 if let Some(p) = node.f64_attr("pad") {
634 v = v.padding(p);
635 }
636 if let Some(size) = node.attr("frame") {
637 let (w, h) = parse_size(size, node.line)?;
638 v = v.frame(w, h);
639 }
640 if let Some(o) = node.f64_attr("opacity") {
641 v = v.opacity(o);
642 }
643 if let Some(c) = node.attr("bg") {
644 let c = parse_color(c, node.line)?;
645 v = v.bg(c);
646 }
647 if let Some(r) = node.f64_attr("corner") {
648 v = v.corner_radius(r);
649 }
650 Ok(v)
651}Sourcepub fn bg_view(self, content: View) -> Self
pub fn bg_view(self, content: View) -> Self
.background { … } — an arbitrary view behind this one, centred.
SwiftUI has two background overloads and they are different
modifiers, not one with a convenience: View::bg reaches the one
generic over ShapeStyle, this reaches the one generic over View.
So the argument here can be a whole subtree, not only a colour.
Sourcepub fn bg_view_aligned(self, content: View, alignment: Alignment) -> Self
pub fn bg_view_aligned(self, content: View, alignment: Alignment) -> Self
.background(alignment:) { … }
Sourcepub fn bg_material(self, kind: MaterialKind) -> Self
pub fn bg_material(self, kind: MaterialKind) -> Self
.background(.regularMaterial) and its neighbours — a blur of
whatever is behind the view rather than a colour over it.
Sourcepub fn bg_linear_gradient(
self,
colors: &[Color],
start: (f64, f64),
end: (f64, f64),
) -> Self
pub fn bg_linear_gradient( self, colors: &[Color], start: (f64, f64), end: (f64, f64), ) -> Self
.background(LinearGradient(colors:startPoint:endPoint:))
The points are unit points: (0, 0) is top-leading and (1, 1)
bottom-trailing, so a top-to-bottom gradient is (0.5, 0)→(0.5, 1).
Sourcepub fn bg_radial_gradient(
self,
colors: &[Color],
center: (f64, f64),
start_radius: f64,
end_radius: f64,
) -> Self
pub fn bg_radial_gradient( self, colors: &[Color], center: (f64, f64), start_radius: f64, end_radius: f64, ) -> Self
.background(RadialGradient(colors:center:startRadius:endRadius:))
Sourcepub fn opacity(self, value: f64) -> Self
pub fn opacity(self, value: f64) -> Self
Apply .opacity(_:).
On a Color this is Color.opacity(_:), which returns Color — the
same concrete-overload story as Text.bold().
Examples found in repository?
9fn main() {
10 run(|| {
11 vstack(&[
12 text("Hello from Rust! 🦀")
13 .padding(12.0)
14 .bg(Color::BLUE)
15 .rounded(8.0)
16 .opacity(0.95),
17 spacer(),
18 hstack(&[
19 image("star.fill"),
20 text("No Swift compiler needed"),
21 ]),
22 divider(),
23 text("Pure dlsym + arm64 asm → SwiftUI")
24 .padding(8.0),
25 ])
26 .padding(40.0)
27 .into_handle()
28 });
29}More examples
632fn decorate(mut v: View, node: &Node) -> Result<View, String> {
633 if let Some(p) = node.f64_attr("pad") {
634 v = v.padding(p);
635 }
636 if let Some(size) = node.attr("frame") {
637 let (w, h) = parse_size(size, node.line)?;
638 v = v.frame(w, h);
639 }
640 if let Some(o) = node.f64_attr("opacity") {
641 v = v.opacity(o);
642 }
643 if let Some(c) = node.attr("bg") {
644 let c = parse_color(c, node.line)?;
645 v = v.bg(c);
646 }
647 if let Some(r) = node.f64_attr("corner") {
648 v = v.corner_radius(r);
649 }
650 Ok(v)
651}48fn main_window() -> ViewHandle {
49 vstack(&[
50 text("A SwiftUI app, no Swift source")
51 .font_size(20.0)
52 .padding(8.0),
53 divider(),
54 text(&format!("count: {}", counter().get()))
55 .font_size(34.0)
56 .padding(12.0),
57 hstack(&[
58 button("−", || counter().set(counter().get() - 1)),
59 button("+", || counter().set(counter().get() + 1)),
60 ]),
61 spacer(),
62 text("⌘, for Settings · the ★ in the menu bar has a menu")
63 .font_size(11.0)
64 .opacity(0.6),
65 ])
66 .padding(24.0)
67 .frame(420.0, 300.0)
68 .focused_scene_value(counter_focus_key(), counter().get())
69 .into_handle()
70}
71
72/// The focused-value key the window publishes its count under.
73///
74/// `.focusedSceneValue(\.key, value)` is how a window tells the commands above
75/// it what is selected. Both halves are synthesised at run time: the
76/// `FocusedValueKey` conformance *and* the `WritableKeyPath<FocusedValues, Int?>`
77/// — `FocusedValues` exports no properties, so unlike `EnvironmentValues` there
78/// is no SwiftUI modifier holding a key path to borrow.
79///
80/// The menu cannot *read* it yet: that needs `@FocusedValue`, a `DynamicProperty`
81/// SwiftUI instantiates itself, which is a different mechanism from anything
82/// here. What this demonstrates is the publishing half, in a real app.
83fn counter_focus_key() -> &'static views::FocusKey {
84 static K: std::sync::OnceLock<views::FocusKey> = std::sync::OnceLock::new();
85 K.get_or_init(|| views::focus_key("sceneCounter"))
86}
87
88fn settings_pane() -> ViewHandle {
89 vstack(&[
90 text("Preferences").font_size(18.0),
91 divider(),
92 text("This pane is a `Settings` scene — the one ⌘, opens."),
93 text(&format!("It sees the same state: {}", counter().get()))
94 .opacity(0.7),
95 ])
96 .padding(24.0)
97 .frame(360.0, 200.0)
98 .into_handle()
99}
100
101fn utility_window() -> ViewHandle {
102 vstack(&[
103 text("Utility").font_size(16.0),
104 text("A `Window`, not a `WindowGroup`: one of it, addressed by id.")
105 .opacity(0.7),
106 ])
107 .padding(20.0)
108 .frame(320.0, 140.0)
109 .into_handle()
110}28fn tile(i: usize) -> View {
29 let value = reading(i);
30 vstack_spacing(
31 &[
32 zstack![
33 circle_shape().stroke_system(SystemColor::Gray, 6.0).opacity(0.25),
34 // The filled part: the same circle trimmed to the fraction, and
35 // turned so the arc starts at the top rather than at three
36 // o'clock.
37 circle_shape()
38 .trim(0.0, value)
39 .stroke_system(TINTS[i], 6.0)
40 .rotate(-90.0),
41 text!("{:.0}", value * 100.0).text_style(TextStyle::Title2).bold(),
42 ]
43 .frame(72.0, 72.0),
44 text(LABELS[i]).font_size(12.0).fg_system(SystemColor::Gray),
45 ],
46 8.0,
47 )
48 .padding(12.0)
49 .a11y_element(AccessibilityChildBehavior::Combine)
50 .a11y_label(LABELS[i])
51 .a11y_value(&format!("{:.0} percent", value * 100.0))
52}Sourcepub fn rounded(self, radius: f64) -> Self
pub fn rounded(self, radius: f64) -> Self
Apply .cornerRadius(_:).
Examples found in repository?
9fn main() {
10 run(|| {
11 vstack(&[
12 text("Hello from Rust! 🦀")
13 .padding(12.0)
14 .bg(Color::BLUE)
15 .rounded(8.0)
16 .opacity(0.95),
17 spacer(),
18 hstack(&[
19 image("star.fill"),
20 text("No Swift compiler needed"),
21 ]),
22 divider(),
23 text("Pure dlsym + arm64 asm → SwiftUI")
24 .padding(8.0),
25 ])
26 .padding(40.0)
27 .into_handle()
28 });
29}Sourcepub fn border(self, c: Color, width: f64) -> Self
pub fn border(self, c: Color, width: f64) -> Self
Apply .border(_:width:).
Through views::border_value rather than views::border, because
the latter takes components and pins alpha to 1 — so a translucent border
came out opaque and nothing said so.
Sourcepub fn border_system(self, c: SystemColor, width: f64) -> Self
pub fn border_system(self, c: SystemColor, width: f64) -> Self
.border(_:width:) with one of SwiftUI’s own colours.
Sourcepub fn when(self, condition: bool, f: impl FnOnce(Self) -> Self) -> Self
pub fn when(self, condition: bool, f: impl FnOnce(Self) -> Self) -> Self
Apply f only when condition holds.
Modifier chains often need a branch, and an if in the middle of a
builder chain otherwise forces a temporary binding.
text("hi").when(selected, |v| v.bold().fg(Color::RED))Sourcepub fn when_some<T>(
self,
value: Option<T>,
f: impl FnOnce(Self, T) -> Self,
) -> Self
pub fn when_some<T>( self, value: Option<T>, f: impl FnOnce(Self, T) -> Self, ) -> Self
Apply f with the contained value when value is Some.
Sourcepub fn either(
self,
condition: bool,
yes: impl FnOnce(Self) -> Self,
no: impl FnOnce(Self) -> Self,
) -> Self
pub fn either( self, condition: bool, yes: impl FnOnce(Self) -> Self, no: impl FnOnce(Self) -> Self, ) -> Self
Apply one of two branches.
Sourcepub fn card(self, pad: f64, bg: Color, radius: f64) -> Self
pub fn card(self, pad: f64, bg: Color, radius: f64) -> Self
Shorthand: padding + background + corner radius.
Sourcepub fn shadow(self, c: Color, radius: f64, dx: f64, dy: f64) -> Self
pub fn shadow(self, c: Color, radius: f64, dx: f64, dy: f64) -> Self
.shadow(color:radius:x:y:)
Sourcepub fn rotate(self, degrees: f64) -> Self
pub fn rotate(self, degrees: f64) -> Self
.rotationEffect(.degrees(_)) about the centre.
Examples found in repository?
28fn tile(i: usize) -> View {
29 let value = reading(i);
30 vstack_spacing(
31 &[
32 zstack![
33 circle_shape().stroke_system(SystemColor::Gray, 6.0).opacity(0.25),
34 // The filled part: the same circle trimmed to the fraction, and
35 // turned so the arc starts at the top rather than at three
36 // o'clock.
37 circle_shape()
38 .trim(0.0, value)
39 .stroke_system(TINTS[i], 6.0)
40 .rotate(-90.0),
41 text!("{:.0}", value * 100.0).text_style(TextStyle::Title2).bold(),
42 ]
43 .frame(72.0, 72.0),
44 text(LABELS[i]).font_size(12.0).fg_system(SystemColor::Gray),
45 ],
46 8.0,
47 )
48 .padding(12.0)
49 .a11y_element(AccessibilityChildBehavior::Combine)
50 .a11y_label(LABELS[i])
51 .a11y_value(&format!("{:.0} percent", value * 100.0))
52}Sourcepub fn rotate_anchored(self, degrees: f64, anchor: (f64, f64)) -> Self
pub fn rotate_anchored(self, degrees: f64, anchor: (f64, f64)) -> Self
.rotationEffect(.degrees(_), anchor:) — the point the view turns
about, as a unit point: (0, 0) is top-leading, (0.5, 0.5) the centre.
Not a detail: a dial hand turns about its base and a card flips about an edge, and neither is expressible by rotating about the middle.
Sourcepub fn scale_anchored(self, sx: f64, sy: f64, anchor: (f64, f64)) -> Self
pub fn scale_anchored(self, sx: f64, sy: f64, anchor: (f64, f64)) -> Self
.scaleEffect(_:anchor:) — grow from a unit point rather than the middle.
Sourcepub fn brightness(self, amount: f64) -> Self
pub fn brightness(self, amount: f64) -> Self
.brightness(_:)
Sourcepub fn saturation(self, amount: f64) -> Self
pub fn saturation(self, amount: f64) -> Self
.saturation(_:)
Sourcepub fn material(self, kind: MaterialKind) -> Self
pub fn material(self, kind: MaterialKind) -> Self
.background(_: Material)
Sourcepub fn gradient(
self,
colors: &[Color],
start: (f64, f64),
end: (f64, f64),
) -> Self
pub fn gradient( self, colors: &[Color], start: (f64, f64), end: (f64, f64), ) -> Self
.background(LinearGradient(…))
Sourcepub fn radial_gradient(
self,
colors: &[Color],
center: (f64, f64),
start_radius: f64,
end_radius: f64,
) -> Self
pub fn radial_gradient( self, colors: &[Color], center: (f64, f64), start_radius: f64, end_radius: f64, ) -> Self
.background(RadialGradient(…))
Sourcepub fn color_scheme(self, scheme: ColorScheme) -> Self
pub fn color_scheme(self, scheme: ColorScheme) -> Self
.preferredColorScheme(_:)
Sourcepub fn control_size(self, size: ControlSize) -> Self
pub fn control_size(self, size: ControlSize) -> Self
.controlSize(_:)
.buttonStyle(_:)
Examples found in repository?
89fn about_panel() -> View {
90 let s = settings();
91 vstack_spacing(
92 &[
93 system_image("gearshape.fill")
94 .symbol_rendering_mode(Some(views::SymbolRenderingMode::Hierarchical))
95 .view()
96 .font_size(48.0)
97 .fg_system(SystemColor::Blue),
98 text("Settings").text_style(TextStyle::Title).bold(),
99 text!("Signed in as {}", s.name.get()).fg_system(SystemColor::Gray),
100 spacer(),
101 button("Done", hide_about).button_style(views::ButtonStyle::BorderedProminent),
102 ],
103 16.0,
104 )
105 .padding(24.0)
106 .presentation_detents(&[views::PresentationDetent::Medium])
107 .presentation_drag_indicator(Visibility::Visible)
108}More examples
59fn row(i: usize, it: &Item) -> View {
60 hstack_spacing(
61 &[
62 // The checkmark is the button, so the whole symbol is the target.
63 button_labelled(
64 system_image(if it.done { "checkmark.circle.fill" } else { "circle" })
65 .symbol_rendering_mode(Some(views::SymbolRenderingMode::Hierarchical))
66 .view()
67 .fg_system(if it.done { SystemColor::Green } else { SystemColor::Gray }),
68 move || toggle(i),
69 )
70 .button_style(views::ButtonStyle::Bordered),
71 text(&it.title)
72 .strikethrough_styled(it.done, LinePattern::Solid, None)
73 .fg_system(if it.done { SystemColor::Gray } else { SystemColor::Primary }),
74 spacer(),
75 ],
76 10.0,
77 )
78 .padding_edges(EdgeSet::Vertical, Some(6.0))
79 .a11y_label(&it.title)
80 .a11y_value(if it.done { "Done" } else { "Not done" })
81}
82
83fn body() -> View {
84 let todos = items().lock().unwrap().clone();
85 let remaining = todos.iter().filter(|i| !i.done).count();
86
87 vstack_aligned_spacing(
88 &[
89 hstack![
90 text("Todo").text_style(TextStyle::LargeTitle).bold(),
91 spacer(),
92 text!("{remaining} left").fg_system(SystemColor::Gray),
93 ],
94 hstack_spacing(
95 &[
96 textfield_bound("What needs doing?", draft())
97 .text_field_style(views::TextFieldStyle::RoundedBorderTextFieldStyle)
98 .on_submit(SubmitTrigger::Text, add)
99 .submit_label(SubmitLabel::Done),
100 button("Add", add).button_style(views::ButtonStyle::BorderedProminent),
101 ],
102 8.0,
103 ),
104 // The empty state is a branch, so it arrives and leaves rather than
105 // appearing from nothing.
106 view_if!(
107 todos.is_empty(),
108 vstack_spacing(
109 &[
110 system_image("checkmark.seal").view().font_size(40.0)
111 .fg_system(SystemColor::Green),
112 text("Nothing left to do").fg_system(SystemColor::Gray),
113 ],
114 8.0,
115 )
116 .frame_optional(None, Some(160.0), Alignment::Center)
117 .transition(Transition::ScaleWithOpacity { scale: 0.8, anchor: (0.5, 0.5) }),
118 list(for_each_items(
119 &todos.iter().cloned().enumerate().collect::<Vec<_>>(),
120 |(i, it)| row(*i, it),
121 ))
122 .list_style(views::ListStyle::PlainListStyle)
123 ),
124 ],
125 HorizontalAlignment::Leading,
126 Some(14.0),
127 )
128 .padding(20.0)
129}129fn body() -> View {
130 let colour = COLORS[COLOR.load(Ordering::Relaxed) % COLORS.len()];
131
132 vstack![
133 // Text("Why not try…").font(.largeTitle.bold())
134 text("Why not try…").text_style(TextStyle::LargeTitle).bold(),
135 vstack![
136 // Circle().fill(colors.randomElement() ?? .blue).padding().overlay(…)
137 circle_shape().fill_system(colour).padding(16.0).overlay(
138 // Image(systemName: "figure.\(selected.lowercased())")
139 // .font(.system(size: 144)).foregroundColor(.white)
140 image!("figure.{}", selected().to_lowercase())
141 .font_size(144.0)
142 .fg(Color::WHITE),
143 ),
144 // Text("\(selected)!").font(.title)
145 text!("{}!", selected()).text_style(TextStyle::Title),
146 ]
147 .transition(Transition::Slide)
148 .id(ID.load(Ordering::Relaxed)),
149 spacer(),
150 // Button("Try again") { … }.buttonStyle(.borderedProminent)
151 button("Try again", try_again).button_style(ButtonStyle::BorderedProminent),
152 ]
153}54fn body() -> View {
55 vstack_aligned_spacing(
56 &[
57 text("System").text_style(TextStyle::LargeTitle).bold(),
58 grid(&[grid_row(&[tile(0), tile(1), tile(2)])]),
59 divider(),
60 // A gauge over the busiest reading, which is a different control
61 // from the rings and reads the same state.
62 vstack_aligned(
63 &[
64 text("Busiest").font_size(12.0).fg_system(SystemColor::Gray),
65 gauge(reading(1), 0.0, 1.0, text("Memory"))
66 .gauge_style(views::GaugeStyle::AccessoryLinearCapacityGaugeStyle)
67 .tint_system(SystemColor::Orange),
68 ],
69 HorizontalAlignment::Leading,
70 ),
71 spacer(),
72 button("Refresh", refresh)
73 .button_style(views::ButtonStyle::BorderedProminent)
74 .keyboard_shortcut(KeyboardShortcut::DefaultAction),
75 ],
76 HorizontalAlignment::Leading,
77 Some(16.0),
78 )
79 .padding(20.0)
80 // Animate whatever changed, rather than snapping to the new reading.
81 .animation(LOAD[0].load(Ordering::Relaxed) as i64)
82}Sourcepub fn background_shape_style(self, style: ShapeStyle) -> Self
pub fn background_shape_style(self, style: ShapeStyle) -> Self
.backgroundStyle(_:) with one of SwiftUI’s semantic styles.
Sourcepub fn bg_auto_gradient(self, c: Color) -> Self
pub fn bg_auto_gradient(self, c: Color) -> Self
.background(_.gradient) — the automatic gradient derived from a colour.
Sourcepub fn bg_in_circle(self) -> Self
pub fn bg_in_circle(self) -> Self
.background(in: .circle)
Sourcepub fn container_background(
self,
placement: ContainerBackgroundPlacement,
alignment: Alignment,
content: View,
) -> Self
pub fn container_background( self, placement: ContainerBackgroundPlacement, alignment: Alignment, content: View, ) -> Self
.containerBackground(for:alignment:content:) — the background a
container hands to its whole area, not just this view’s bounds.
See views::ContainerBackgroundPlacement: two of its cases trap on
macOS, which is SwiftUI’s own availability rather than anything here.
Sourcepub fn fg_value(self, color: u64) -> Self
pub fn fg_value(self, color: u64) -> Self
.foregroundStyle(_:) with an already-built colour, which is how a
system colour is passed — see views::system_color_value.
Sourcepub fn fg_pair(self, primary: u64, secondary: u64) -> Self
pub fn fg_pair(self, primary: u64, secondary: u64) -> Self
.foregroundStyle(_:_:) — primary and secondary, for a symbol drawn in
two tones.
Sourcepub fn fg_triple(self, primary: u64, secondary: u64, tertiary: u64) -> Self
pub fn fg_triple(self, primary: u64, secondary: u64, tertiary: u64) -> Self
.foregroundStyle(_:_:_:) — three tones.
A palette symbol takes its layers from successive styles.
fg_pair covers the two-layer symbols; the three-layer
ones — and there are plenty in SF Symbols — drew their third layer in
the secondary colour, because there was no way to say what it should be.
Sourcepub fn tint_value(self, tint: u64) -> Self
pub fn tint_value(self, tint: u64) -> Self
.tint(_:) with an already-built colour.
Sourcepub fn color_scheme_forced(self, value: ColorScheme) -> Self
pub fn color_scheme_forced(self, value: ColorScheme) -> Self
.colorScheme(_:) — force light or dark for this subtree, as distinct
from View::color_scheme’s preferred scheme, which asks the whole
window.
Sourcepub fn edges_ignoring_safe_area(self, edges: EdgeSet) -> Self
pub fn edges_ignoring_safe_area(self, edges: EdgeSet) -> Self
.edgesIgnoringSafeArea(_:) — the older spelling; see
View::ignores_safe_area for the one that takes regions too.
Sourcepub fn persistent_system_overlays(self, visibility: Visibility) -> Self
pub fn persistent_system_overlays(self, visibility: Visibility) -> Self
.persistentSystemOverlays(_:) — the home indicator and its neighbours.
Sourcepub fn symbol_variant(self, variant: SymbolVariants) -> Self
pub fn symbol_variant(self, variant: SymbolVariants) -> Self
.symbolVariant(_:) — .fill, .circle and so on, without renaming the
symbol.
Sourcepub fn symbol_rendering_mode(self, mode: Option<SymbolRenderingMode>) -> Self
pub fn symbol_rendering_mode(self, mode: Option<SymbolRenderingMode>) -> Self
.symbolRenderingMode(_:) — None restores the default.
Sourcepub fn label_style(self, style: LabelStyle) -> Self
pub fn label_style(self, style: LabelStyle) -> Self
.labelStyle(_:) — icon only, title only, or both.
.menuStyle(_:)
.buttonBorderShape(_:)
Sourcepub fn scroll_target_behavior(self, behavior: ScrollTargetBehavior) -> Self
pub fn scroll_target_behavior(self, behavior: ScrollTargetBehavior) -> Self
.scrollTargetBehavior(_:) — .paging and friends.
Sourcepub fn scroll_content_background(self, visibility: Visibility) -> Self
pub fn scroll_content_background(self, visibility: Visibility) -> Self
.scrollContentBackground(_:) — hiding it is how a List loses its
grouped backdrop.
Sourcepub fn symbol_effect_pulse(self) -> Self
pub fn symbol_effect_pulse(self) -> Self
.symbolEffect(.pulse)
Sourcepub fn symbol_effects_removed(self, removed: bool) -> Self
pub fn symbol_effects_removed(self, removed: bool) -> Self
.symbolEffectsRemoved(_:) — stop inherited effects at this view.
Sourcepub fn symbol_color_rendering_mode_flat(self) -> Self
pub fn symbol_color_rendering_mode_flat(self) -> Self
.symbolColorRenderingMode(.flat)
Sourcepub fn symbol_variable_value_mode_color(self) -> Self
pub fn symbol_variable_value_mode_color(self) -> Self
.symbolVariableValueMode(.color)
Sourcepub fn keyframe_animator(
self,
initial: f64,
to: f64,
repeating: bool,
content: View,
) -> Self
pub fn keyframe_animator( self, initial: f64, to: f64, repeating: bool, content: View, ) -> Self
.keyframeAnimator(initialValue:repeating:content:) — drive a value
through keyframes and rebuild the content from it.
Sourcepub fn phase_animator(
self,
phases: &[i64],
content: View,
animated: bool,
) -> Self
pub fn phase_animator( self, phases: &[i64], content: View, animated: bool, ) -> Self
.phaseAnimator(_:content:) — step through phases, rebuilding at each.
Sourcepub fn transaction(self, action: impl Fn(TransactionRef) + 'static) -> Self
pub fn transaction(self, action: impl Fn(TransactionRef) + 'static) -> Self
.transaction(_:) — reach the transaction driving the current change,
which is how an animation is suppressed for one update.
Sourcepub fn geometry_group(self) -> Self
pub fn geometry_group(self) -> Self
.geometryGroup() — animate this subtree’s geometry as one, rather than
letting each child interpolate independently and pull apart.
Sourcepub fn transform_effect(
self,
a: f64,
b: f64,
c: f64,
d: f64,
tx: f64,
ty: f64,
) -> Self
pub fn transform_effect( self, a: f64, b: f64, c: f64, d: f64, tx: f64, ty: f64, ) -> Self
.transformEffect(_:) — an affine transform, as [a b c d tx ty].
Sourcepub fn visual_effect(self) -> Self
pub fn visual_effect(self) -> Self
.visualEffect(_:)
Source§impl View
impl View
Sourcepub fn toggle_style(self, style: ToggleStyle) -> Self
pub fn toggle_style(self, style: ToggleStyle) -> Self
.toggleStyle(_:)
Sourcepub fn picker_style(self, style: PickerStyle) -> Self
pub fn picker_style(self, style: PickerStyle) -> Self
.pickerStyle(_:)
Examples found in repository?
43fn body() -> View {
44 let s = settings();
45
46 form![
47 section![header: text("Account");
48 hstack![
49 text("Name"),
50 spacer(),
51 textfield_bound("Your name", &s.name).text_field_style(
52 views::TextFieldStyle::RoundedBorderTextFieldStyle,
53 ),
54 ],
55 toggle_bound("Notifications", &s.notify),
56 ],
57 section![header: text("Playback");
58 vstack_aligned(&[
59 hstack![
60 text("Volume"),
61 spacer(),
62 text!("{:.0}%", s.volume.get() * 100.0).fg_system(SystemColor::Gray),
63 ],
64 slider_bound(&s.volume, 0.0, 1.0),
65 ], HorizontalAlignment::Leading),
66 stepper_bound("Refresh every", &s.refresh, 1.0, 60.0, 1.0),
67 ],
68 section![header: text("Appearance");
69 picker_bound!(
70 "Theme",
71 &s.theme,
72 text(THEMES[0]).tag_int(0),
73 text(THEMES[1]).tag_int(1),
74 text(THEMES[2]).tag_int(2),
75 )
76 .picker_style(PickerStyle::InlinePickerStyle),
77 ],
78 section![
79 button("About", show_about)
80 .a11y_hint("Opens a panel describing this app"),
81 ],
82 ]
83 .form_style(FormStyle::GroupedFormStyle)
84 .sheet_bound(&s.about, about_panel())
85}Sourcepub fn date_picker_style(self, style: DatePickerStyle) -> Self
pub fn date_picker_style(self, style: DatePickerStyle) -> Self
.datePickerStyle(_:)
Sourcepub fn gauge_style(self, style: GaugeStyle) -> Self
pub fn gauge_style(self, style: GaugeStyle) -> Self
.gaugeStyle(_:)
Examples found in repository?
54fn body() -> View {
55 vstack_aligned_spacing(
56 &[
57 text("System").text_style(TextStyle::LargeTitle).bold(),
58 grid(&[grid_row(&[tile(0), tile(1), tile(2)])]),
59 divider(),
60 // A gauge over the busiest reading, which is a different control
61 // from the rings and reads the same state.
62 vstack_aligned(
63 &[
64 text("Busiest").font_size(12.0).fg_system(SystemColor::Gray),
65 gauge(reading(1), 0.0, 1.0, text("Memory"))
66 .gauge_style(views::GaugeStyle::AccessoryLinearCapacityGaugeStyle)
67 .tint_system(SystemColor::Orange),
68 ],
69 HorizontalAlignment::Leading,
70 ),
71 spacer(),
72 button("Refresh", refresh)
73 .button_style(views::ButtonStyle::BorderedProminent)
74 .keyboard_shortcut(KeyboardShortcut::DefaultAction),
75 ],
76 HorizontalAlignment::Leading,
77 Some(16.0),
78 )
79 .padding(20.0)
80 // Animate whatever changed, rather than snapping to the new reading.
81 .animation(LOAD[0].load(Ordering::Relaxed) as i64)
82}Sourcepub fn form_style(self, style: FormStyle) -> Self
pub fn form_style(self, style: FormStyle) -> Self
.formStyle(_:)
Examples found in repository?
43fn body() -> View {
44 let s = settings();
45
46 form![
47 section![header: text("Account");
48 hstack![
49 text("Name"),
50 spacer(),
51 textfield_bound("Your name", &s.name).text_field_style(
52 views::TextFieldStyle::RoundedBorderTextFieldStyle,
53 ),
54 ],
55 toggle_bound("Notifications", &s.notify),
56 ],
57 section![header: text("Playback");
58 vstack_aligned(&[
59 hstack![
60 text("Volume"),
61 spacer(),
62 text!("{:.0}%", s.volume.get() * 100.0).fg_system(SystemColor::Gray),
63 ],
64 slider_bound(&s.volume, 0.0, 1.0),
65 ], HorizontalAlignment::Leading),
66 stepper_bound("Refresh every", &s.refresh, 1.0, 60.0, 1.0),
67 ],
68 section![header: text("Appearance");
69 picker_bound!(
70 "Theme",
71 &s.theme,
72 text(THEMES[0]).tag_int(0),
73 text(THEMES[1]).tag_int(1),
74 text(THEMES[2]).tag_int(2),
75 )
76 .picker_style(PickerStyle::InlinePickerStyle),
77 ],
78 section![
79 button("About", show_about)
80 .a11y_hint("Opens a panel describing this app"),
81 ],
82 ]
83 .form_style(FormStyle::GroupedFormStyle)
84 .sheet_bound(&s.about, about_panel())
85}Sourcepub fn group_box_style(self, style: GroupBoxStyle) -> Self
pub fn group_box_style(self, style: GroupBoxStyle) -> Self
.groupBoxStyle(_:)
Sourcepub fn control_group_style(self, style: ControlGroupStyle) -> Self
pub fn control_group_style(self, style: ControlGroupStyle) -> Self
.controlGroupStyle(_:)
Sourcepub fn disclosure_group_style(self, style: DisclosureGroupStyle) -> Self
pub fn disclosure_group_style(self, style: DisclosureGroupStyle) -> Self
.disclosureGroupStyle(_:)
Sourcepub fn table_style(self, style: TableStyle) -> Self
pub fn table_style(self, style: TableStyle) -> Self
.tableStyle(_:)
Sourcepub fn text_editor_style(self, style: TextEditorStyle) -> Self
pub fn text_editor_style(self, style: TextEditorStyle) -> Self
.textEditorStyle(_:)
Sourcepub fn labeled_content_style(self, style: LabeledContentStyle) -> Self
pub fn labeled_content_style(self, style: LabeledContentStyle) -> Self
.labeledContentStyle(_:)
Sourcepub fn text_selection(self, style: TextSelectability) -> Self
pub fn text_selection(self, style: TextSelectability) -> Self
.textSelection(_:) — whether the user can select and copy the text.
.buttonRepeatBehavior(_:) — whether holding repeats the action.
.buttonSizing(_:)
.menuButtonStyle(_:)
.menuActionDismissBehavior(_:) — whether choosing an item closes the menu.
Sourcepub fn slider_thumb_visibility(self, value: Visibility) -> Self
pub fn slider_thumb_visibility(self, value: Visibility) -> Self
.sliderThumbVisibility(_:)
Sourcepub fn spring_loading_behavior(self, value: SpringLoadingBehavior) -> Self
pub fn spring_loading_behavior(self, value: SpringLoadingBehavior) -> Self
.springLoadingBehavior(_:) — whether hovering a drag over this opens it.
Sourcepub fn palette_selection_effect(self, value: PaletteSelectionEffect) -> Self
pub fn palette_selection_effect(self, value: PaletteSelectionEffect) -> Self
.paletteSelectionEffect(_:)
Sourcepub fn material_active_appearance(self, value: MaterialActiveAppearance) -> Self
pub fn material_active_appearance(self, value: MaterialActiveAppearance) -> Self
.materialActiveAppearance(_:)
Sourcepub fn progress_view_style_circular(self) -> Self
pub fn progress_view_style_circular(self) -> Self
.progressViewStyle(.circular)
.menuIndicator(_:) — the chevron that says a control opens a menu.
.menuOrder(_:)
Sourcepub fn labels_visibility(self, visibility: Visibility) -> Self
pub fn labels_visibility(self, visibility: Visibility) -> Self
.labelsVisibility(_:) — hiding a label keeps it for VoiceOver while
taking it off the screen, which .hidden() does not.
Sourcepub fn header_prominence(self, prominence: Prominence) -> Self
pub fn header_prominence(self, prominence: Prominence) -> Self
.headerProminence(_:)
Sourcepub fn badge_prominence(self, prominence: BadgeProminence) -> Self
pub fn badge_prominence(self, prominence: BadgeProminence) -> Self
.badgeProminence(_:)
Sourcepub fn list_style(self, style: ListStyle) -> Self
pub fn list_style(self, style: ListStyle) -> Self
.listStyle(_:)
Examples found in repository?
More examples
83fn body() -> View {
84 let todos = items().lock().unwrap().clone();
85 let remaining = todos.iter().filter(|i| !i.done).count();
86
87 vstack_aligned_spacing(
88 &[
89 hstack![
90 text("Todo").text_style(TextStyle::LargeTitle).bold(),
91 spacer(),
92 text!("{remaining} left").fg_system(SystemColor::Gray),
93 ],
94 hstack_spacing(
95 &[
96 textfield_bound("What needs doing?", draft())
97 .text_field_style(views::TextFieldStyle::RoundedBorderTextFieldStyle)
98 .on_submit(SubmitTrigger::Text, add)
99 .submit_label(SubmitLabel::Done),
100 button("Add", add).button_style(views::ButtonStyle::BorderedProminent),
101 ],
102 8.0,
103 ),
104 // The empty state is a branch, so it arrives and leaves rather than
105 // appearing from nothing.
106 view_if!(
107 todos.is_empty(),
108 vstack_spacing(
109 &[
110 system_image("checkmark.seal").view().font_size(40.0)
111 .fg_system(SystemColor::Green),
112 text("Nothing left to do").fg_system(SystemColor::Gray),
113 ],
114 8.0,
115 )
116 .frame_optional(None, Some(160.0), Alignment::Center)
117 .transition(Transition::ScaleWithOpacity { scale: 0.8, anchor: (0.5, 0.5) }),
118 list(for_each_items(
119 &todos.iter().cloned().enumerate().collect::<Vec<_>>(),
120 |(i, it)| row(*i, it),
121 ))
122 .list_style(views::ListStyle::PlainListStyle)
123 ),
124 ],
125 HorizontalAlignment::Leading,
126 Some(14.0),
127 )
128 .padding(20.0)
129}Sourcepub fn list_row_insets(self, insets: Option<[f64; 4]>) -> Self
pub fn list_row_insets(self, insets: Option<[f64; 4]>) -> Self
.listRowInsets(_:) as [top, leading, bottom, trailing]; None
restores the default inset.
Sourcepub fn list_row_separator(
self,
visibility: Visibility,
edges: VerticalEdgeSet,
) -> Self
pub fn list_row_separator( self, visibility: Visibility, edges: VerticalEdgeSet, ) -> Self
.listRowSeparator(_:edges:)
Sourcepub fn list_section_separator(
self,
visibility: Visibility,
edges: VerticalEdgeSet,
) -> Self
pub fn list_section_separator( self, visibility: Visibility, edges: VerticalEdgeSet, ) -> Self
.listSectionSeparator(_:edges:)
Sourcepub fn selection_disabled(self, disabled: bool) -> Self
pub fn selection_disabled(self, disabled: bool) -> Self
.selectionDisabled(_:) — a row that shows but cannot be picked.
Sourcepub fn swipe_actions(
self,
edge: HorizontalEdge,
allows_full_swipe: bool,
content: View,
) -> Self
pub fn swipe_actions( self, edge: HorizontalEdge, allows_full_swipe: bool, content: View, ) -> Self
.swipeActions(edge:allowsFullSwipe:content:)
Sourcepub fn refreshable(self, action: impl Fn() + Send + Sync + 'static) -> Self
pub fn refreshable(self, action: impl Fn() + Send + Sync + 'static) -> Self
.refreshable(action:) — pull to refresh.
Sourcepub fn scroll_dismisses_keyboard(
self,
mode: ScrollDismissesKeyboardMode,
) -> Self
pub fn scroll_dismisses_keyboard( self, mode: ScrollDismissesKeyboardMode, ) -> Self
.scrollDismissesKeyboard(_:) — what scrolling does to an open keyboard.
Sourcepub fn list_row_separator_tint(
self,
color: Option<Color>,
edges: &[VerticalEdgeSet],
) -> Self
pub fn list_row_separator_tint( self, color: Option<Color>, edges: &[VerticalEdgeSet], ) -> Self
.listRowSeparatorTint(_:edges:) — None restores the default.
Sourcepub fn list_section_separator_tint(
self,
color: Option<Color>,
edges: &[VerticalEdgeSet],
) -> Self
pub fn list_section_separator_tint( self, color: Option<Color>, edges: &[VerticalEdgeSet], ) -> Self
.listSectionSeparatorTint(_:edges:)
Sourcepub fn list_item_tint_monochrome(self, tinted: bool) -> Self
pub fn list_item_tint_monochrome(self, tinted: bool) -> Self
.listItemTint(.monochrome)
Sourcepub fn alternating_row_backgrounds(
self,
value: AlternatingRowBackgroundBehavior,
) -> Self
pub fn alternating_row_backgrounds( self, value: AlternatingRowBackgroundBehavior, ) -> Self
.alternatingRowBackgrounds(_:)
Sourcepub fn section_actions(self, content: View) -> Self
pub fn section_actions(self, content: View) -> Self
.sectionActions(content:) — controls in a section’s header area.
Sourcepub fn section_index_label(self, label: &str) -> Self
pub fn section_index_label(self, label: &str) -> Self
.sectionIndexLabel(_:) — the letter this section shows in a scrubber.
Sourcepub fn table_column_headers(self, visibility: Visibility) -> Self
pub fn table_column_headers(self, visibility: Visibility) -> Self
.tableColumnHeaders(_:)
Sourcepub fn tab_view_style_automatic(self) -> Self
pub fn tab_view_style_automatic(self) -> Self
.tabViewStyle(.automatic)
Sourcepub fn tab_view_customization_none(self) -> Self
pub fn tab_view_customization_none(self) -> Self
.tabViewCustomization(nil)
Sourcepub fn tab_view_search_activation_automatic(self) -> Self
pub fn tab_view_search_activation_automatic(self) -> Self
.tabViewSearchActivation(.automatic)
.tabViewSidebarHeader { … }
.tabViewSidebarFooter { … }
.tabViewSidebarBottomBar { … }
Sourcepub fn tab_bar_minimize_behavior(self, value: TabBarMinimizeBehavior) -> Self
pub fn tab_bar_minimize_behavior(self, value: TabBarMinimizeBehavior) -> Self
.tabBarMinimizeBehavior(_:)
Source§impl View
impl View
Sourcepub fn drag_configuration(
self,
within_app: DragOperations,
outside_app: DragOperations,
) -> Self
pub fn drag_configuration( self, within_app: DragOperations, outside_app: DragOperations, ) -> Self
.dragConfiguration(within:outside:) — which operations a drag permits
inside the app and outside it, which need not be the same.
Sourcepub fn drag_container(self, items: &[&str]) -> Self
pub fn drag_container(self, items: &[&str]) -> Self
.dragContainer(for:) — the items a multi-item drag carries.
Sourcepub fn drag_container_selection(self, selected: &[&str]) -> Self
pub fn drag_container_selection(self, selected: &[&str]) -> Self
.dragContainerSelection(_:) — which of them are selected, so dragging
one drags the selection rather than just the item under the finger.
Sourcepub fn draggable_container_item(self, id: HashableValue<'_>) -> Self
pub fn draggable_container_item(self, id: HashableValue<'_>) -> Self
.draggableContainerItem(id:) — mark this view as one of the container’s
items.
Sourcepub fn drag_previews_formation(self, value: DragDropPreviewsFormation) -> Self
pub fn drag_previews_formation(self, value: DragDropPreviewsFormation) -> Self
.dragPreviewsFormation(_:) — how several dragged previews stack up.
Sourcepub fn drop_previews_formation(self, value: DragDropPreviewsFormation) -> Self
pub fn drop_previews_formation(self, value: DragDropPreviewsFormation) -> Self
.dropPreviewsFormation(_:)
Sourcepub fn drop_configuration(
self,
decide: impl Fn() -> DropOperation + 'static,
) -> Self
pub fn drop_configuration( self, decide: impl Fn() -> DropOperation + 'static, ) -> Self
.dropConfiguration(_:) — decide what a drop over this view would do,
which is what sets the cursor before anything is released.
Sourcepub fn drop_destination(
self,
accept: impl Fn(&[String]) -> bool + 'static,
targeted: impl Fn(bool) + 'static,
) -> Self
pub fn drop_destination( self, accept: impl Fn(&[String]) -> bool + 'static, targeted: impl Fn(bool) + 'static, ) -> Self
.dropDestination(for:action:isTargeted:) — accept returns whether the
drop was taken; targeted fires as the drag enters and leaves.
Sourcepub fn on_drag_session_updated(self, action: impl Fn() + 'static) -> Self
pub fn on_drag_session_updated(self, action: impl Fn() + 'static) -> Self
.onDragSessionUpdated(_:)
Sourcepub fn on_drop_session_updated(self, action: impl Fn() + 'static) -> Self
pub fn on_drop_session_updated(self, action: impl Fn() + 'static) -> Self
.onDropSessionUpdated(_:)
Sourcepub fn on_copy_command(self, items: &[&str]) -> Self
pub fn on_copy_command(self, items: &[&str]) -> Self
.onCopyCommand(perform:) — what Copy takes from this view.
Sourcepub fn on_cut_command(self, items: &[&str]) -> Self
pub fn on_cut_command(self, items: &[&str]) -> Self
.onCutCommand(perform:)
Sourcepub fn on_paste_command(
self,
kinds: &[ContentType],
paste: impl Fn(&[ItemProvider]) + 'static,
) -> Self
pub fn on_paste_command( self, kinds: &[ContentType], paste: impl Fn(&[ItemProvider]) + 'static, ) -> Self
.onPasteCommand(of:perform:)
Sourcepub fn on_delete_command(self, action: impl Fn() + 'static) -> Self
pub fn on_delete_command(self, action: impl Fn() + 'static) -> Self
.onDeleteCommand(perform:)
Sourcepub fn on_move_command(self, action: impl Fn(i64) + 'static) -> Self
pub fn on_move_command(self, action: impl Fn(i64) + 'static) -> Self
.onMoveCommand(perform:) — arrow keys, with the direction as an Int.
Sourcepub fn on_exit_command(self, action: impl Fn() + 'static) -> Self
pub fn on_exit_command(self, action: impl Fn() + 'static) -> Self
.onExitCommand(perform:) — escape.
Sourcepub fn on_command(
self,
selector: &'static CStr,
action: impl Fn() + 'static,
) -> Self
pub fn on_command( self, selector: &'static CStr, action: impl Fn() + 'static, ) -> Self
.onCommand(_:perform:) — any other selector by name, which is the way
out when a command has no modifier of its own.
Sourcepub fn cuttable(self, items: &[&str]) -> Self
pub fn cuttable(self, items: &[&str]) -> Self
.cuttable(for:action:) — what Cut takes, as distinct from
View::copyable, which Copy takes.
Sourcepub fn paste_destination(self, paste: impl Fn(&[String]) + 'static) -> Self
pub fn paste_destination(self, paste: impl Fn(&[String]) + 'static) -> Self
.pasteDestination(for:action:)
Sourcepub fn rename_action(self, action: impl Fn() + 'static) -> Self
pub fn rename_action(self, action: impl Fn() + 'static) -> Self
.renameAction(_:) — what the Rename command does, which a list row
needs for in-place renaming to work at all.
Sourcepub fn pointer_style(self, style: Option<PointerStyle>) -> Self
pub fn pointer_style(self, style: Option<PointerStyle>) -> Self
.pointerStyle(_:) — None restores the default cursor.
Sourcepub fn pointer_visibility(self, value: Visibility) -> Self
pub fn pointer_visibility(self, value: Visibility) -> Self
.pointerVisibility(_:)
Sourcepub fn on_modifier_keys_changed(
self,
mask: EventModifier,
initial: bool,
action: impl Fn(u64, u64) + 'static,
) -> Self
pub fn on_modifier_keys_changed( self, mask: EventModifier, initial: bool, action: impl Fn(u64, u64) + 'static, ) -> Self
.onModifierKeysChanged(mask:initial:_:)
Sourcepub fn modifier_key_alternate(
self,
modifiers: EventModifier,
content: View,
) -> Self
pub fn modifier_key_alternate( self, modifiers: EventModifier, content: View, ) -> Self
.modifierKeyAlternate(_:_:) — a different view while a key is held.
Sourcepub fn on_interactive_resize_change(
self,
action: impl Fn(bool) + 'static,
) -> Self
pub fn on_interactive_resize_change( self, action: impl Fn(bool) + 'static, ) -> Self
.onInteractiveResizeChange(_:)
Sourcepub fn user_activity(
self,
kind: &str,
active: bool,
action: impl Fn() + 'static,
) -> Self
pub fn user_activity( self, kind: &str, active: bool, action: impl Fn() + 'static, ) -> Self
.userActivity(_:isActive:_:) — advertise what this view is doing, for
Handoff and Spotlight.
Sourcepub fn on_continue_user_activity(
self,
kind: &str,
action: impl Fn() + 'static,
) -> Self
pub fn on_continue_user_activity( self, kind: &str, action: impl Fn() + 'static, ) -> Self
.onContinueUserActivity(_:perform:) — the other end of Handoff.
Sourcepub fn handles_external_events(
self,
preferring: &[&str],
allowing: &[&str],
) -> Self
pub fn handles_external_events( self, preferring: &[&str], allowing: &[&str], ) -> Self
.handlesExternalEvents(preferring:allowing:)
Sourcepub fn allowed_dynamic_range_high(self) -> Self
pub fn allowed_dynamic_range_high(self) -> Self
.allowedDynamicRange(.high)
Sourcepub fn tab_item(self, label: View) -> Self
pub fn tab_item(self, label: View) -> Self
.tabItem { … } — the label a TabView shows for this page.
Sourcepub fn high_priority_gesture(
self,
minimum_distance: f64,
action: impl Fn() + 'static,
) -> Self
pub fn high_priority_gesture( self, minimum_distance: f64, action: impl Fn() + 'static, ) -> Self
.highPriorityGesture(_:) — take the gesture ahead of the children,
where .gesture would lose to them.
Sourcepub fn simultaneous_gesture(
self,
minimum_distance: f64,
action: impl Fn() + 'static,
) -> Self
pub fn simultaneous_gesture( self, minimum_distance: f64, action: impl Fn() + 'static, ) -> Self
.simultaneousGesture(_:) — recognise alongside the children rather than
instead of them.
Sourcepub fn on_open_url(self, action: impl Fn(&str) + 'static) -> Self
pub fn on_open_url(self, action: impl Fn(&str) + 'static) -> Self
.onOpenURL(perform:) — deep links.
Sourcepub fn copyable(self, items: &[&str]) -> Self
pub fn copyable(self, items: &[&str]) -> Self
.copyable(_:) — what a copy command takes from this view.
Sourcepub fn scroll_position_id(
self,
state: &BoundState<String>,
anchor: Option<(f64, f64)>,
) -> Self
pub fn scroll_position_id( self, state: &BoundState<String>, anchor: Option<(f64, f64)>, ) -> Self
.scrollPosition(id:anchor:) bound to Rust state — the id of the item
at the anchor lands in state, and writing it scrolls there.
Sourcepub fn default_scroll_anchor(
self,
anchor: Option<(f64, f64)>,
role: ScrollAnchorRole,
) -> Self
pub fn default_scroll_anchor( self, anchor: Option<(f64, f64)>, role: ScrollAnchorRole, ) -> Self
.defaultScrollAnchor(_:for:) — None restores the default.
Sourcepub fn scroll_target_layout(self, enabled: bool) -> Self
pub fn scroll_target_layout(self, enabled: bool) -> Self
.scrollTargetLayout() — mark the stack whose children are the targets
a paging scroll snaps to.
Sourcepub fn scroll_bounce_behavior(
self,
behavior: ScrollBounceBehavior,
axes: AxisSet,
) -> Self
pub fn scroll_bounce_behavior( self, behavior: ScrollBounceBehavior, axes: AxisSet, ) -> Self
.scrollBounceBehavior(_:axes:)
Sourcepub fn scroll_indicators_flash(self, on_appear: bool) -> Self
pub fn scroll_indicators_flash(self, on_appear: bool) -> Self
.scrollIndicatorsFlash(onAppear:)
.scrollEdgeEffectHidden(_:for:)
Sourcepub fn scroll_edge_effect_style(
self,
style: Option<ScrollEdgeEffectStyle>,
edges: &[EdgeSetMember],
) -> Self
pub fn scroll_edge_effect_style( self, style: Option<ScrollEdgeEffectStyle>, edges: &[EdgeSetMember], ) -> Self
.scrollEdgeEffectStyle(_:for:) — None restores the default.
Sourcepub fn scroll_transition(
self,
config: ScrollTransitionConfiguration,
axis: Option<Axis>,
) -> Self
pub fn scroll_transition( self, config: ScrollTransitionConfiguration, axis: Option<Axis>, ) -> Self
.scrollTransition(_:axis:) — how a child changes as it crosses the
viewport.
Sourcepub fn scroll_transition_ends(
self,
top_leading: ScrollTransitionConfiguration,
bottom_trailing: ScrollTransitionConfiguration,
axis: Option<Axis>,
) -> Self
pub fn scroll_transition_ends( self, top_leading: ScrollTransitionConfiguration, bottom_trailing: ScrollTransitionConfiguration, axis: Option<Axis>, ) -> Self
.scrollTransition(topLeading:bottomTrailing:axis:) — the two ends of
the scroll configured separately.
The single-configuration scroll_transition
applies the same one at both ends; this is what lets a view animate on
the way in and do nothing on the way out.
Sourcepub fn on_scroll_phase_change(self, action: impl Fn(i64, i64) + 'static) -> Self
pub fn on_scroll_phase_change(self, action: impl Fn(i64, i64) + 'static) -> Self
.onScrollPhaseChange(_:) — the handler sees the old and new phase.
Sourcepub fn on_scroll_visibility_change(
self,
threshold: f64,
action: impl Fn(bool) + 'static,
) -> Self
pub fn on_scroll_visibility_change( self, threshold: f64, action: impl Fn(bool) + 'static, ) -> Self
.onScrollVisibilityChange(threshold:_:)
Sourcepub fn default_focus(self, value: bool, priority: DefaultFocusPriority) -> Self
pub fn default_focus(self, value: bool, priority: DefaultFocusPriority) -> Self
.defaultFocus(_:_:) — which control starts focused.
Sourcepub fn prefers_default_focus(self, prefers: bool) -> Self
pub fn prefers_default_focus(self, prefers: bool) -> Self
.prefersDefaultFocus(_:in:)
Sourcepub fn focus_scope(self) -> Self
pub fn focus_scope(self) -> Self
.focusScope(_:) — a boundary focus moves within.
Sourcepub fn a11y_focused(self) -> Self
pub fn a11y_focused(self) -> Self
.accessibilityFocused(_:)
Sourcepub fn a11y_default_focus(self, value: bool) -> Self
pub fn a11y_default_focus(self, value: bool) -> Self
.accessibilityDefaultFocus(_:_:)
Sourcepub fn matched_geometry_effect(
self,
id: HashableValue<'_>,
properties: &[GeometryProperties],
anchor: (f64, f64),
is_source: bool,
) -> Self
pub fn matched_geometry_effect( self, id: HashableValue<'_>, properties: &[GeometryProperties], anchor: (f64, f64), is_source: bool, ) -> Self
.matchedGeometryEffect(id:in:properties:anchor:isSource:) — the pair of
views that share an id are interpolated between rather than crossfaded.
Sourcepub fn matched_geometry_effect_in(
self,
id: HashableValue<'_>,
namespace: Namespace,
properties: &[GeometryProperties],
anchor: (f64, f64),
is_source: bool,
) -> Self
pub fn matched_geometry_effect_in( self, id: HashableValue<'_>, namespace: Namespace, properties: &[GeometryProperties], anchor: (f64, f64), is_source: bool, ) -> Self
.matchedGeometryEffect(id:in:properties:anchor:isSource:) in a
shared namespace.
The pairing spelling. matched_geometry_effect
mints a namespace per call, so the views it makes cannot pair with
anything.
Sourcepub fn on_drag_item(self, item: &str, preview: View) -> Self
pub fn on_drag_item(self, item: &str, preview: View) -> Self
.onDrag { NSItemProvider(object: item) } with a custom preview.
Named apart from View::on_drag, which is the drag gesture — a
finger moving on screen — where this is drag and drop, which hands an
item to another view or another app.
Sourcepub fn on_drop(
self,
kinds: &[ContentType],
accept: impl Fn(&[ItemProvider]) -> bool + 'static,
) -> Self
pub fn on_drop( self, kinds: &[ContentType], accept: impl Fn(&[ItemProvider]) -> bool + 'static, ) -> Self
.onDrop(of:isTargeted:perform:) — the handler returns whether it took
the drop.
Sourcepub fn on_key_press(
self,
characters: CharacterSetKind,
phases: KeyPressPhases,
action: impl Fn(KeyPress) -> KeyPressResult + 'static,
) -> Self
pub fn on_key_press( self, characters: CharacterSetKind, phases: KeyPressPhases, action: impl Fn(KeyPress) -> KeyPressResult + 'static, ) -> Self
.onKeyPress(_:phases:action:)
The action is handed the views::KeyPress — what was typed, which
modifiers were held, and which phase of the press it is — and answers
whether it handled it. It used to receive nothing at all, which left a
key handler unable to branch on the key.
let v = text("editor").on_key_press(
CharacterSetKind::Alphanumerics,
KeyPressPhases::Down,
|press| {
if press.characters == "s" && press.holding(EventModifier::Command) {
KeyPressResult::Handled
} else {
KeyPressResult::Ignored
}
},
);Sourcepub fn on_key(
self,
key: Key,
action: impl Fn() -> KeyPressResult + 'static,
) -> Self
pub fn on_key( self, key: Key, action: impl Fn() -> KeyPressResult + 'static, ) -> Self
.onKeyPress(_:action:) — one named key.
on_key_press watches a whole character set and
hands the action the press; this watches one key, which is how a
shortcut is usually written — “Escape closes this”. Only the
character-set form was bound, so a view that cared about Escape had to
accept every key and filter.
let sheet = text("editor").on_key(Key::Escape, || KeyPressResult::Handled);Sourcepub fn sensory_feedback(
self,
feedback: SensoryFeedback,
trigger: i64,
condition: impl Fn(i64, i64) -> bool + 'static,
) -> Self
pub fn sensory_feedback( self, feedback: SensoryFeedback, trigger: i64, condition: impl Fn(i64, i64) -> bool + 'static, ) -> Self
.sensoryFeedback(_:trigger:condition:) — haptics, fired when the
condition says the trigger’s change deserves one.
Source§impl View
impl View
Sourcepub fn padding(self, amount: f64) -> Self
pub fn padding(self, amount: f64) -> Self
Apply .padding(_:).
Examples found in repository?
60fn detail(i: usize) -> View {
61 let m = &MESSAGES[i];
62 vstack_aligned_spacing(
63 &[
64 text(m.subject).text_style(TextStyle::Title).bold(),
65 text!("From {}", m.from).fg_system(SystemColor::Gray),
66 divider(),
67 text("Body text would go here.").fg_system(SystemColor::Gray),
68 spacer(),
69 ],
70 HorizontalAlignment::Leading,
71 Some(12.0),
72 )
73 .padding(20.0)
74 .navigation_title(m.subject)
75}More examples
9fn main() {
10 run(|| {
11 vstack(&[
12 text("Hello from Rust! 🦀")
13 .padding(12.0)
14 .bg(Color::BLUE)
15 .rounded(8.0)
16 .opacity(0.95),
17 spacer(),
18 hstack(&[
19 image("star.fill"),
20 text("No Swift compiler needed"),
21 ]),
22 divider(),
23 text("Pure dlsym + arm64 asm → SwiftUI")
24 .padding(8.0),
25 ])
26 .padding(40.0)
27 .into_handle()
28 });
29}632fn decorate(mut v: View, node: &Node) -> Result<View, String> {
633 if let Some(p) = node.f64_attr("pad") {
634 v = v.padding(p);
635 }
636 if let Some(size) = node.attr("frame") {
637 let (w, h) = parse_size(size, node.line)?;
638 v = v.frame(w, h);
639 }
640 if let Some(o) = node.f64_attr("opacity") {
641 v = v.opacity(o);
642 }
643 if let Some(c) = node.attr("bg") {
644 let c = parse_color(c, node.line)?;
645 v = v.bg(c);
646 }
647 if let Some(r) = node.f64_attr("corner") {
648 v = v.corner_radius(r);
649 }
650 Ok(v)
651}64pub fn body() -> View {
65 let text_src = current().lock().expect("spec").clone();
66 match spec::parse(&text_src).and_then(|nodes| spec::build(&nodes)) {
67 Ok(v) => v,
68 Err(e) => vstack_aligned_spacing(
69 &[
70 text("Could not build that screen")
71 .text_style(TextStyle::Headline)
72 .fg_system(SystemColor::Red),
73 text(&e).font_size(12.0).fg_system(SystemColor::Secondary),
74 ],
75 HorizontalAlignment::Leading,
76 Some(8.0),
77 )
78 .padding(20.0),
79 }
80}96fn body() -> View {
97 let (src, error, generation, micros) = {
98 let g = state_cell().lock().expect("state");
99 (g.last_good.clone(), g.error.clone(), g.generation, g.micros)
100 };
101
102 // The last version that parsed. It cannot fail — it parsed before — but a
103 // spec that builds views from slots could in principle, so the fallback is
104 // still handled rather than unwrapped.
105 let screen = spec::parse(&src)
106 .and_then(|nodes| spec::build(&nodes))
107 .unwrap_or_else(|e| text(&e).fg_system(SystemColor::Red).padding(20.0));
108
109 vstack_spacing(&[screen, status(error.as_deref(), generation, micros)], 0.0)
110}
111
112/// A strip along the bottom: which generation is on screen, how long the last
113/// reload took, what the slots hold, and the error if there is one.
114///
115/// In the window rather than the terminal because that is where you are
116/// looking. Watching a reloader work from a log means watching two things.
117fn status(error: Option<&str>, generation: u64, micros: u64) -> View {
118 let slots = spec::slot_summary();
119 let slot_line = if slots.is_empty() {
120 String::new()
121 } else {
122 slots
123 .iter()
124 .map(|(k, v)| format!("{k}={v}"))
125 .collect::<Vec<_>>()
126 .join(" ")
127 };
128
129 // The error row is *always* present, empty when there is nothing wrong.
130 // An error that appears and disappears would otherwise reflow the screen
131 // above it on every save — which looks exactly like the reloader having
132 // replaced the view, and makes "did the screen survive this?" impossible
133 // to answer by looking.
134 let rows = vec![
135 divider(),
136 hstack_spacing(
137 &[
138 circle_shape()
139 .fill_system(if error.is_some() {
140 SystemColor::Orange
141 } else {
142 SystemColor::Clear
143 })
144 .frame(8.0, 8.0),
145 text(error.unwrap_or(""))
146 .font_size(11.0)
147 .fg_system(SystemColor::Orange),
148 spacer(),
149 ],
150 6.0,
151 )
152 .padding(6.0)
153 .frame(348.0, 24.0),
154 hstack_spacing(
155 &[
156 circle_shape()
157 .fill_system(if error.is_some() {
158 SystemColor::Orange
159 } else {
160 SystemColor::Green
161 })
162 .frame(8.0, 8.0),
163 text(&format!("gen {generation}"))
164 .font_size(11.0)
165 .fg_system(SystemColor::Secondary),
166 // Microseconds below a millisecond: a reload of a short spec
167 // really is that fast, and "0.0 ms" reads as "not measured".
168 text(&if micros < 1000 {
169 format!("{micros} \u{b5}s")
170 } else {
171 format!("{:.1} ms", micros as f64 / 1000.0)
172 })
173 .font_size(11.0)
174 .fg_system(SystemColor::Secondary),
175 spacer(),
176 text(&slot_line).font_size(11.0).fg_system(SystemColor::Secondary),
177 ],
178 8.0,
179 )
180 .padding(6.0)
181 .frame(348.0, 24.0),
182 ];
183 vstack_spacing(&rows, 0.0)
184}48fn main_window() -> ViewHandle {
49 vstack(&[
50 text("A SwiftUI app, no Swift source")
51 .font_size(20.0)
52 .padding(8.0),
53 divider(),
54 text(&format!("count: {}", counter().get()))
55 .font_size(34.0)
56 .padding(12.0),
57 hstack(&[
58 button("−", || counter().set(counter().get() - 1)),
59 button("+", || counter().set(counter().get() + 1)),
60 ]),
61 spacer(),
62 text("⌘, for Settings · the ★ in the menu bar has a menu")
63 .font_size(11.0)
64 .opacity(0.6),
65 ])
66 .padding(24.0)
67 .frame(420.0, 300.0)
68 .focused_scene_value(counter_focus_key(), counter().get())
69 .into_handle()
70}
71
72/// The focused-value key the window publishes its count under.
73///
74/// `.focusedSceneValue(\.key, value)` is how a window tells the commands above
75/// it what is selected. Both halves are synthesised at run time: the
76/// `FocusedValueKey` conformance *and* the `WritableKeyPath<FocusedValues, Int?>`
77/// — `FocusedValues` exports no properties, so unlike `EnvironmentValues` there
78/// is no SwiftUI modifier holding a key path to borrow.
79///
80/// The menu cannot *read* it yet: that needs `@FocusedValue`, a `DynamicProperty`
81/// SwiftUI instantiates itself, which is a different mechanism from anything
82/// here. What this demonstrates is the publishing half, in a real app.
83fn counter_focus_key() -> &'static views::FocusKey {
84 static K: std::sync::OnceLock<views::FocusKey> = std::sync::OnceLock::new();
85 K.get_or_init(|| views::focus_key("sceneCounter"))
86}
87
88fn settings_pane() -> ViewHandle {
89 vstack(&[
90 text("Preferences").font_size(18.0),
91 divider(),
92 text("This pane is a `Settings` scene — the one ⌘, opens."),
93 text(&format!("It sees the same state: {}", counter().get()))
94 .opacity(0.7),
95 ])
96 .padding(24.0)
97 .frame(360.0, 200.0)
98 .into_handle()
99}
100
101fn utility_window() -> ViewHandle {
102 vstack(&[
103 text("Utility").font_size(16.0),
104 text("A `Window`, not a `WindowGroup`: one of it, addressed by id.")
105 .opacity(0.7),
106 ])
107 .padding(20.0)
108 .frame(320.0, 140.0)
109 .into_handle()
110}
111
112fn menu_bar_item() -> ViewHandle {
113 vstack(&[
114 text(&format!("count: {}", counter().get())),
115 button("Reset", || counter().set(0)),
116 ])
117 .padding(10.0)
118 .into_handle()
119}Sourcepub fn padding_edges(self, edges: EdgeSet, length: Option<f64>) -> Self
pub fn padding_edges(self, edges: EdgeSet, length: Option<f64>) -> Self
.padding(_:_:) on chosen edges — .padding(.horizontal, 8).
None asks for SwiftUI’s own default inset rather than a number.
Examples found in repository?
77fn row(i: usize) -> View {
78 let m = &MESSAGES[i];
79 hstack_spacing(
80 &[
81 // An unread dot, or the space where one would be.
82 view_if!(
83 m.unread,
84 circle_shape().fill_system(SystemColor::Blue).frame(8.0, 8.0),
85 empty().frame(8.0, 8.0)
86 ),
87 vstack_aligned(
88 &[
89 text(m.from).bold(),
90 text(m.subject).font_size(12.0).fg_system(SystemColor::Gray),
91 ],
92 HorizontalAlignment::Leading,
93 ),
94 spacer(),
95 ],
96 8.0,
97 )
98 .padding_edges(EdgeSet::Vertical, Some(4.0))
99 .a11y_label(&format!("{}, {}", m.from, m.subject))
100 .a11y_hint(if m.unread { "Unread" } else { "Read" })
101}More examples
59fn row(i: usize, it: &Item) -> View {
60 hstack_spacing(
61 &[
62 // The checkmark is the button, so the whole symbol is the target.
63 button_labelled(
64 system_image(if it.done { "checkmark.circle.fill" } else { "circle" })
65 .symbol_rendering_mode(Some(views::SymbolRenderingMode::Hierarchical))
66 .view()
67 .fg_system(if it.done { SystemColor::Green } else { SystemColor::Gray }),
68 move || toggle(i),
69 )
70 .button_style(views::ButtonStyle::Bordered),
71 text(&it.title)
72 .strikethrough_styled(it.done, LinePattern::Solid, None)
73 .fg_system(if it.done { SystemColor::Gray } else { SystemColor::Primary }),
74 spacer(),
75 ],
76 10.0,
77 )
78 .padding_edges(EdgeSet::Vertical, Some(6.0))
79 .a11y_label(&it.title)
80 .a11y_value(if it.done { "Done" } else { "Not done" })
81}Sourcepub fn padding_default(self) -> Self
pub fn padding_default(self) -> Self
.padding() — the system’s default inset on every edge.
Sourcepub fn frame_optional(
self,
width: Option<f64>,
height: Option<f64>,
alignment: Alignment,
) -> Self
pub fn frame_optional( self, width: Option<f64>, height: Option<f64>, alignment: Alignment, ) -> Self
.frame(width:height:alignment:) with either dimension left out.
An omitted dimension is not zero: it means “take what the parent offers”, which is a different layout from asking for nothing.
Examples found in repository?
83fn body() -> View {
84 let todos = items().lock().unwrap().clone();
85 let remaining = todos.iter().filter(|i| !i.done).count();
86
87 vstack_aligned_spacing(
88 &[
89 hstack![
90 text("Todo").text_style(TextStyle::LargeTitle).bold(),
91 spacer(),
92 text!("{remaining} left").fg_system(SystemColor::Gray),
93 ],
94 hstack_spacing(
95 &[
96 textfield_bound("What needs doing?", draft())
97 .text_field_style(views::TextFieldStyle::RoundedBorderTextFieldStyle)
98 .on_submit(SubmitTrigger::Text, add)
99 .submit_label(SubmitLabel::Done),
100 button("Add", add).button_style(views::ButtonStyle::BorderedProminent),
101 ],
102 8.0,
103 ),
104 // The empty state is a branch, so it arrives and leaves rather than
105 // appearing from nothing.
106 view_if!(
107 todos.is_empty(),
108 vstack_spacing(
109 &[
110 system_image("checkmark.seal").view().font_size(40.0)
111 .fg_system(SystemColor::Green),
112 text("Nothing left to do").fg_system(SystemColor::Gray),
113 ],
114 8.0,
115 )
116 .frame_optional(None, Some(160.0), Alignment::Center)
117 .transition(Transition::ScaleWithOpacity { scale: 0.8, anchor: (0.5, 0.5) }),
118 list(for_each_items(
119 &todos.iter().cloned().enumerate().collect::<Vec<_>>(),
120 |(i, it)| row(*i, it),
121 ))
122 .list_style(views::ListStyle::PlainListStyle)
123 ),
124 ],
125 HorizontalAlignment::Leading,
126 Some(14.0),
127 )
128 .padding(20.0)
129}Sourcepub fn expand(self, alignment: Alignment) -> Self
pub fn expand(self, alignment: Alignment) -> Self
.frame(maxWidth: .infinity, maxHeight: .infinity) — fill the parent.
Sourcepub fn expand_width(self, alignment: Alignment) -> Self
pub fn expand_width(self, alignment: Alignment) -> Self
.frame(maxWidth: .infinity) — fill across, keep the natural height.
Sourcepub fn frame_aligned(self, w: f64, h: f64, alignment: Alignment) -> Self
pub fn frame_aligned(self, w: f64, h: f64, alignment: Alignment) -> Self
.frame(width:height:alignment:).
Sourcepub fn frame(self, w: f64, h: f64) -> Self
pub fn frame(self, w: f64, h: f64) -> Self
Apply .frame(width:height:).
Examples found in repository?
632fn decorate(mut v: View, node: &Node) -> Result<View, String> {
633 if let Some(p) = node.f64_attr("pad") {
634 v = v.padding(p);
635 }
636 if let Some(size) = node.attr("frame") {
637 let (w, h) = parse_size(size, node.line)?;
638 v = v.frame(w, h);
639 }
640 if let Some(o) = node.f64_attr("opacity") {
641 v = v.opacity(o);
642 }
643 if let Some(c) = node.attr("bg") {
644 let c = parse_color(c, node.line)?;
645 v = v.bg(c);
646 }
647 if let Some(r) = node.f64_attr("corner") {
648 v = v.corner_radius(r);
649 }
650 Ok(v)
651}More examples
48fn main_window() -> ViewHandle {
49 vstack(&[
50 text("A SwiftUI app, no Swift source")
51 .font_size(20.0)
52 .padding(8.0),
53 divider(),
54 text(&format!("count: {}", counter().get()))
55 .font_size(34.0)
56 .padding(12.0),
57 hstack(&[
58 button("−", || counter().set(counter().get() - 1)),
59 button("+", || counter().set(counter().get() + 1)),
60 ]),
61 spacer(),
62 text("⌘, for Settings · the ★ in the menu bar has a menu")
63 .font_size(11.0)
64 .opacity(0.6),
65 ])
66 .padding(24.0)
67 .frame(420.0, 300.0)
68 .focused_scene_value(counter_focus_key(), counter().get())
69 .into_handle()
70}
71
72/// The focused-value key the window publishes its count under.
73///
74/// `.focusedSceneValue(\.key, value)` is how a window tells the commands above
75/// it what is selected. Both halves are synthesised at run time: the
76/// `FocusedValueKey` conformance *and* the `WritableKeyPath<FocusedValues, Int?>`
77/// — `FocusedValues` exports no properties, so unlike `EnvironmentValues` there
78/// is no SwiftUI modifier holding a key path to borrow.
79///
80/// The menu cannot *read* it yet: that needs `@FocusedValue`, a `DynamicProperty`
81/// SwiftUI instantiates itself, which is a different mechanism from anything
82/// here. What this demonstrates is the publishing half, in a real app.
83fn counter_focus_key() -> &'static views::FocusKey {
84 static K: std::sync::OnceLock<views::FocusKey> = std::sync::OnceLock::new();
85 K.get_or_init(|| views::focus_key("sceneCounter"))
86}
87
88fn settings_pane() -> ViewHandle {
89 vstack(&[
90 text("Preferences").font_size(18.0),
91 divider(),
92 text("This pane is a `Settings` scene — the one ⌘, opens."),
93 text(&format!("It sees the same state: {}", counter().get()))
94 .opacity(0.7),
95 ])
96 .padding(24.0)
97 .frame(360.0, 200.0)
98 .into_handle()
99}
100
101fn utility_window() -> ViewHandle {
102 vstack(&[
103 text("Utility").font_size(16.0),
104 text("A `Window`, not a `WindowGroup`: one of it, addressed by id.")
105 .opacity(0.7),
106 ])
107 .padding(20.0)
108 .frame(320.0, 140.0)
109 .into_handle()
110}77fn row(i: usize) -> View {
78 let m = &MESSAGES[i];
79 hstack_spacing(
80 &[
81 // An unread dot, or the space where one would be.
82 view_if!(
83 m.unread,
84 circle_shape().fill_system(SystemColor::Blue).frame(8.0, 8.0),
85 empty().frame(8.0, 8.0)
86 ),
87 vstack_aligned(
88 &[
89 text(m.from).bold(),
90 text(m.subject).font_size(12.0).fg_system(SystemColor::Gray),
91 ],
92 HorizontalAlignment::Leading,
93 ),
94 spacer(),
95 ],
96 8.0,
97 )
98 .padding_edges(EdgeSet::Vertical, Some(4.0))
99 .a11y_label(&format!("{}, {}", m.from, m.subject))
100 .a11y_hint(if m.unread { "Unread" } else { "Read" })
101}28fn tile(i: usize) -> View {
29 let value = reading(i);
30 vstack_spacing(
31 &[
32 zstack![
33 circle_shape().stroke_system(SystemColor::Gray, 6.0).opacity(0.25),
34 // The filled part: the same circle trimmed to the fraction, and
35 // turned so the arc starts at the top rather than at three
36 // o'clock.
37 circle_shape()
38 .trim(0.0, value)
39 .stroke_system(TINTS[i], 6.0)
40 .rotate(-90.0),
41 text!("{:.0}", value * 100.0).text_style(TextStyle::Title2).bold(),
42 ]
43 .frame(72.0, 72.0),
44 text(LABELS[i]).font_size(12.0).fg_system(SystemColor::Gray),
45 ],
46 8.0,
47 )
48 .padding(12.0)
49 .a11y_element(AccessibilityChildBehavior::Combine)
50 .a11y_label(LABELS[i])
51 .a11y_value(&format!("{:.0} percent", value * 100.0))
52}117fn status(error: Option<&str>, generation: u64, micros: u64) -> View {
118 let slots = spec::slot_summary();
119 let slot_line = if slots.is_empty() {
120 String::new()
121 } else {
122 slots
123 .iter()
124 .map(|(k, v)| format!("{k}={v}"))
125 .collect::<Vec<_>>()
126 .join(" ")
127 };
128
129 // The error row is *always* present, empty when there is nothing wrong.
130 // An error that appears and disappears would otherwise reflow the screen
131 // above it on every save — which looks exactly like the reloader having
132 // replaced the view, and makes "did the screen survive this?" impossible
133 // to answer by looking.
134 let rows = vec![
135 divider(),
136 hstack_spacing(
137 &[
138 circle_shape()
139 .fill_system(if error.is_some() {
140 SystemColor::Orange
141 } else {
142 SystemColor::Clear
143 })
144 .frame(8.0, 8.0),
145 text(error.unwrap_or(""))
146 .font_size(11.0)
147 .fg_system(SystemColor::Orange),
148 spacer(),
149 ],
150 6.0,
151 )
152 .padding(6.0)
153 .frame(348.0, 24.0),
154 hstack_spacing(
155 &[
156 circle_shape()
157 .fill_system(if error.is_some() {
158 SystemColor::Orange
159 } else {
160 SystemColor::Green
161 })
162 .frame(8.0, 8.0),
163 text(&format!("gen {generation}"))
164 .font_size(11.0)
165 .fg_system(SystemColor::Secondary),
166 // Microseconds below a millisecond: a reload of a short spec
167 // really is that fast, and "0.0 ms" reads as "not measured".
168 text(&if micros < 1000 {
169 format!("{micros} \u{b5}s")
170 } else {
171 format!("{:.1} ms", micros as f64 / 1000.0)
172 })
173 .font_size(11.0)
174 .fg_system(SystemColor::Secondary),
175 spacer(),
176 text(&slot_line).font_size(11.0).fg_system(SystemColor::Secondary),
177 ],
178 8.0,
179 )
180 .padding(6.0)
181 .frame(348.0, 24.0),
182 ];
183 vstack_spacing(&rows, 0.0)
184}Sourcepub fn clip_circle(self) -> Self
pub fn clip_circle(self) -> Self
.clipShape(Circle())
Sourcepub fn clip_capsule(self) -> Self
pub fn clip_capsule(self) -> Self
.clipShape(Capsule())
Sourcepub fn clip_capsule_styled(self, continuous: bool) -> Self
pub fn clip_capsule_styled(self, continuous: bool) -> Self
.clipShape(Capsule(style:)) — false gives the circular arc.
Sourcepub fn clip_rounded_styled(self, radius: f64, continuous: bool) -> Self
pub fn clip_rounded_styled(self, radius: f64, continuous: bool) -> Self
.clipShape(RoundedRectangle(cornerRadius:style:)) — .continuous is
the squircle Apple’s own UI uses, and it is visibly not a circular arc.
Sourcepub fn clip_rounded(self, radius: f64) -> Self
pub fn clip_rounded(self, radius: f64) -> Self
.clipShape(RoundedRectangle(cornerRadius:))
Sourcepub fn overlay(self, content: View) -> Self
pub fn overlay(self, content: View) -> Self
.overlay(alignment: .center) { … }
Examples found in repository?
129fn body() -> View {
130 let colour = COLORS[COLOR.load(Ordering::Relaxed) % COLORS.len()];
131
132 vstack![
133 // Text("Why not try…").font(.largeTitle.bold())
134 text("Why not try…").text_style(TextStyle::LargeTitle).bold(),
135 vstack![
136 // Circle().fill(colors.randomElement() ?? .blue).padding().overlay(…)
137 circle_shape().fill_system(colour).padding(16.0).overlay(
138 // Image(systemName: "figure.\(selected.lowercased())")
139 // .font(.system(size: 144)).foregroundColor(.white)
140 image!("figure.{}", selected().to_lowercase())
141 .font_size(144.0)
142 .fg(Color::WHITE),
143 ),
144 // Text("\(selected)!").font(.title)
145 text!("{}!", selected()).text_style(TextStyle::Title),
146 ]
147 .transition(Transition::Slide)
148 .id(ID.load(Ordering::Relaxed)),
149 spacer(),
150 // Button("Try again") { … }.buttonStyle(.borderedProminent)
151 button("Try again", try_again).button_style(ButtonStyle::BorderedProminent),
152 ]
153}Sourcepub fn overlay_aligned(self, content: View, alignment: Alignment) -> Self
pub fn overlay_aligned(self, content: View, alignment: Alignment) -> Self
.overlay(alignment:content:) — the same modifier as View::overlay,
which pins to the centre.
Sourcepub fn mask(self, content: View) -> Self
pub fn mask(self, content: View) -> Self
.mask(alignment: .center) { … } — a _MaskAlignmentEffect.
Sourcepub fn mask_aligned(self, content: View, alignment: Alignment) -> Self
pub fn mask_aligned(self, content: View, alignment: Alignment) -> Self
.mask(alignment:_:) with an alignment other than the centre.
Sourcepub fn mask_plain(self, content: View) -> Self
pub fn mask_plain(self, content: View) -> Self
.mask(_:) — the older, alignment-free overload, which is a
_MaskEffect. A different type from View::mask, not a shorthand
for it.
Sourcepub fn aspect_ratio(self, ratio: f64, fill: bool) -> Self
pub fn aspect_ratio(self, ratio: f64, fill: bool) -> Self
.aspectRatio(_:contentMode:)
Sourcepub fn fixed_size(self, horizontal: bool, vertical: bool) -> Self
pub fn fixed_size(self, horizontal: bool, vertical: bool) -> Self
.fixedSize(horizontal:vertical:)
.hidden()
Sourcepub fn blend_mode(self, mode: u8) -> Self
pub fn blend_mode(self, mode: u8) -> Self
.blendMode(_:)
.navigationTitle(_:)
Examples found in repository?
60fn detail(i: usize) -> View {
61 let m = &MESSAGES[i];
62 vstack_aligned_spacing(
63 &[
64 text(m.subject).text_style(TextStyle::Title).bold(),
65 text!("From {}", m.from).fg_system(SystemColor::Gray),
66 divider(),
67 text("Body text would go here.").fg_system(SystemColor::Gray),
68 spacer(),
69 ],
70 HorizontalAlignment::Leading,
71 Some(12.0),
72 )
73 .padding(20.0)
74 .navigation_title(m.subject)
75}
76
77fn row(i: usize) -> View {
78 let m = &MESSAGES[i];
79 hstack_spacing(
80 &[
81 // An unread dot, or the space where one would be.
82 view_if!(
83 m.unread,
84 circle_shape().fill_system(SystemColor::Blue).frame(8.0, 8.0),
85 empty().frame(8.0, 8.0)
86 ),
87 vstack_aligned(
88 &[
89 text(m.from).bold(),
90 text(m.subject).font_size(12.0).fg_system(SystemColor::Gray),
91 ],
92 HorizontalAlignment::Leading,
93 ),
94 spacer(),
95 ],
96 8.0,
97 )
98 .padding_edges(EdgeSet::Vertical, Some(4.0))
99 .a11y_label(&format!("{}, {}", m.from, m.subject))
100 .a11y_hint(if m.unread { "Unread" } else { "Read" })
101}
102
103/// The row as it appears in the list: a link to the detail, with the swipe
104/// action attached to the link rather than to its label.
105fn linked_row(i: usize) -> View {
106 navigation_link_labelled(row(i), detail(i))
107 .swipe_actions(HorizontalEdge::Trailing, true, button("Delete", || {}))
108}
109
110fn body() -> View {
111 let i = inbox();
112 let rows = matching();
113 navigation_stack(
114 list(for_each_items(&rows, |&i| linked_row(i)))
115 .list_style(views::ListStyle::InsetListStyle)
116 .searchable(&i.query, &i.searching, SearchFieldPlacement::Automatic, "Search"),
117 )
118 .navigation_title("Inbox")
119 .toolbar(button("Compose", || {}).keyboard_shortcut(KeyboardShortcut::DefaultAction))
120}.navigationTitle(_:) with a binding — an editable title.
The title bar becomes a rename field: the user edits it in place and the new name is written back into Rust. Only the fixed-string overload was bound, so a document could be shown under a name but never renamed from where the name appears.
let name = BoundState::new(String::from("Untitled"));
let doc = text("body").navigation_title_bound(&name);.navigationDestination(for: Int.self) { value in … } — value-based
routing.
This is how a NavigationStack is driven in modern SwiftUI: rows push a
value, and the stack asks this modifier what view that value means.
Only the isPresented: overload was bound, which is the older
one-destination-per-flag shape — fine for a single detail sheet, and no
use for a stack that pushes rows.
let stack = navigation_stack(
list_identified(&[1, 2, 3], |id| text(&format!("row {id}")))
.navigation_destination_for(|id| text(&format!("detail {id}"))),
);Sourcepub fn alert(self, title: &str, presented: bool, actions: View) -> Self
pub fn alert(self, title: &str, presented: bool, actions: View) -> Self
.alert(_:isPresented:actions:) with a fixed flag.
The flag becomes a Binding.constant, which SwiftUI treats as
read-only, so this alert cannot be dismissed — there is nowhere to write
false back to. View::alert_bound is the one a user can close.
Sourcepub fn alert_bound(
self,
title: &str,
state: &BoundState<bool>,
actions: View,
) -> Self
pub fn alert_bound( self, title: &str, state: &BoundState<bool>, actions: View, ) -> Self
.alert(_:isPresented:actions:) bound to Rust state.
Dismissing writes false into state, so Rust learns the alert closed
without being told.
Sourcepub fn alert_message_bound(
self,
title: &str,
state: &BoundState<bool>,
actions: View,
message: View,
) -> Self
pub fn alert_message_bound( self, title: &str, state: &BoundState<bool>, actions: View, message: View, ) -> Self
.alert(_:isPresented:actions:message:) — an alert that explains itself.
The message is the line under the title: what the buttons are about, and the difference between “Delete” and “Delete — this cannot be undone”. Only the title-and-buttons overload was bound, so an alert could ask but not say why.
let asking = BoundState::new(false);
let page = text("Notes").alert_message_bound(
"Delete this?",
&asking,
button("Delete", || {}),
text("This cannot be undone."),
);Sourcepub fn alert_message(
self,
title: &str,
presented: bool,
actions: View,
message: View,
) -> Self
pub fn alert_message( self, title: &str, presented: bool, actions: View, message: View, ) -> Self
.alert(_:isPresented:actions:message:) with a fixed flag, which cannot
be dismissed — see alert.
Sourcepub fn confirmation_message_bound(
self,
title: &str,
state: &BoundState<bool>,
actions: View,
message: View,
) -> Self
pub fn confirmation_message_bound( self, title: &str, state: &BoundState<bool>, actions: View, message: View, ) -> Self
.confirmationDialog(_:isPresented:titleVisibility:actions:message:)
The message is the explanatory line under the title, and on a dialog it is often the only place the consequence is stated — “This deletes 12 items” under a bare “Delete”.
Sourcepub fn sheet(self, presented: bool, content: View) -> Self
pub fn sheet(self, presented: bool, content: View) -> Self
.sheet(isPresented:content:) with a fixed flag — undismissable, as
View::alert is. See View::sheet_bound.
Sourcepub fn sheet_bound(self, state: &BoundState<bool>, content: View) -> Self
pub fn sheet_bound(self, state: &BoundState<bool>, content: View) -> Self
.sheet(isPresented:content:) bound to Rust state, so a swipe down
writes false back.
Examples found in repository?
43fn body() -> View {
44 let s = settings();
45
46 form![
47 section![header: text("Account");
48 hstack![
49 text("Name"),
50 spacer(),
51 textfield_bound("Your name", &s.name).text_field_style(
52 views::TextFieldStyle::RoundedBorderTextFieldStyle,
53 ),
54 ],
55 toggle_bound("Notifications", &s.notify),
56 ],
57 section![header: text("Playback");
58 vstack_aligned(&[
59 hstack![
60 text("Volume"),
61 spacer(),
62 text!("{:.0}%", s.volume.get() * 100.0).fg_system(SystemColor::Gray),
63 ],
64 slider_bound(&s.volume, 0.0, 1.0),
65 ], HorizontalAlignment::Leading),
66 stepper_bound("Refresh every", &s.refresh, 1.0, 60.0, 1.0),
67 ],
68 section![header: text("Appearance");
69 picker_bound!(
70 "Theme",
71 &s.theme,
72 text(THEMES[0]).tag_int(0),
73 text(THEMES[1]).tag_int(1),
74 text(THEMES[2]).tag_int(2),
75 )
76 .picker_style(PickerStyle::InlinePickerStyle),
77 ],
78 section![
79 button("About", show_about)
80 .a11y_hint("Opens a panel describing this app"),
81 ],
82 ]
83 .form_style(FormStyle::GroupedFormStyle)
84 .sheet_bound(&s.about, about_panel())
85}Sourcepub fn sheet_bound_dismiss(
self,
state: &BoundState<bool>,
content: View,
on_dismiss: impl Fn() + 'static,
) -> Self
pub fn sheet_bound_dismiss( self, state: &BoundState<bool>, content: View, on_dismiss: impl Fn() + 'static, ) -> Self
.sheet(isPresented:onDismiss:content:) — with a callback for the
closing.
A sheet that saves what was edited has to know when it was dismissed,
and onDismiss was hardwired to nil, so the sheet could be opened and
closed and nothing on the Rust side would hear about it.
let editing = BoundState::new(false);
let page = text("Notes").sheet_bound_dismiss(
&editing,
text("editor"),
|| println!("saved"),
);Sourcepub fn confirmation_dialog(
self,
title: &str,
presented: bool,
actions: View,
) -> Self
pub fn confirmation_dialog( self, title: &str, presented: bool, actions: View, ) -> Self
.confirmationDialog(_:isPresented:actions:) with a fixed flag —
undismissable. See View::confirmation_dialog_bound.
Sourcepub fn confirmation_dialog_bound(
self,
title: &str,
state: &BoundState<bool>,
actions: View,
) -> Self
pub fn confirmation_dialog_bound( self, title: &str, state: &BoundState<bool>, actions: View, ) -> Self
.confirmationDialog(_:isPresented:actions:) bound to Rust state.
Sourcepub fn a11y_label(self, label: &str) -> Self
pub fn a11y_label(self, label: &str) -> Self
.accessibilityLabel(_:)
Examples found in repository?
77fn row(i: usize) -> View {
78 let m = &MESSAGES[i];
79 hstack_spacing(
80 &[
81 // An unread dot, or the space where one would be.
82 view_if!(
83 m.unread,
84 circle_shape().fill_system(SystemColor::Blue).frame(8.0, 8.0),
85 empty().frame(8.0, 8.0)
86 ),
87 vstack_aligned(
88 &[
89 text(m.from).bold(),
90 text(m.subject).font_size(12.0).fg_system(SystemColor::Gray),
91 ],
92 HorizontalAlignment::Leading,
93 ),
94 spacer(),
95 ],
96 8.0,
97 )
98 .padding_edges(EdgeSet::Vertical, Some(4.0))
99 .a11y_label(&format!("{}, {}", m.from, m.subject))
100 .a11y_hint(if m.unread { "Unread" } else { "Read" })
101}More examples
28fn tile(i: usize) -> View {
29 let value = reading(i);
30 vstack_spacing(
31 &[
32 zstack![
33 circle_shape().stroke_system(SystemColor::Gray, 6.0).opacity(0.25),
34 // The filled part: the same circle trimmed to the fraction, and
35 // turned so the arc starts at the top rather than at three
36 // o'clock.
37 circle_shape()
38 .trim(0.0, value)
39 .stroke_system(TINTS[i], 6.0)
40 .rotate(-90.0),
41 text!("{:.0}", value * 100.0).text_style(TextStyle::Title2).bold(),
42 ]
43 .frame(72.0, 72.0),
44 text(LABELS[i]).font_size(12.0).fg_system(SystemColor::Gray),
45 ],
46 8.0,
47 )
48 .padding(12.0)
49 .a11y_element(AccessibilityChildBehavior::Combine)
50 .a11y_label(LABELS[i])
51 .a11y_value(&format!("{:.0} percent", value * 100.0))
52}59fn row(i: usize, it: &Item) -> View {
60 hstack_spacing(
61 &[
62 // The checkmark is the button, so the whole symbol is the target.
63 button_labelled(
64 system_image(if it.done { "checkmark.circle.fill" } else { "circle" })
65 .symbol_rendering_mode(Some(views::SymbolRenderingMode::Hierarchical))
66 .view()
67 .fg_system(if it.done { SystemColor::Green } else { SystemColor::Gray }),
68 move || toggle(i),
69 )
70 .button_style(views::ButtonStyle::Bordered),
71 text(&it.title)
72 .strikethrough_styled(it.done, LinePattern::Solid, None)
73 .fg_system(if it.done { SystemColor::Gray } else { SystemColor::Primary }),
74 spacer(),
75 ],
76 10.0,
77 )
78 .padding_edges(EdgeSet::Vertical, Some(6.0))
79 .a11y_label(&it.title)
80 .a11y_value(if it.done { "Done" } else { "Not done" })
81}.accessibilityHidden(_:)
Sourcepub fn on_disappear(self, action: impl Fn() + 'static) -> Self
pub fn on_disappear(self, action: impl Fn() + 'static) -> Self
.onDisappear(perform:)
Sourcepub fn on_long_press(self, duration: f64, max_distance: f64) -> Self
pub fn on_long_press(self, duration: f64, max_distance: f64) -> Self
.gesture(LongPressGesture(...))
Sourcepub fn on_long_press_perform(
self,
duration: f64,
max_distance: f64,
action: impl Fn() + 'static,
) -> Self
pub fn on_long_press_perform( self, duration: f64, max_distance: f64, action: impl Fn() + 'static, ) -> Self
.onLongPressGesture(minimumDuration:maximumDistance:pressing:perform:)
Prefer this over on_long_press, which attaches
the gesture with nothing listening.
Sourcepub fn compositing_group(self) -> Self
pub fn compositing_group(self) -> Self
.compositingGroup()
Sourcepub fn drawing_group(self) -> Self
pub fn drawing_group(self) -> Self
.drawingGroup() — flatten the subtree through Metal.
Sourcepub fn on_drag_ended(
self,
minimum_distance: f64,
action: impl Fn() + 'static,
) -> Self
pub fn on_drag_ended( self, minimum_distance: f64, action: impl Fn() + 'static, ) -> Self
.gesture(DragGesture(...).onEnded(_:))
Prefer this over on_drag, which attaches the gesture
with nothing listening.
Sourcepub fn on_drag_value(
self,
minimum_distance: f64,
action: impl Fn(DragValue) + 'static,
) -> Self
pub fn on_drag_value( self, minimum_distance: f64, action: impl Fn(DragValue) + 'static, ) -> Self
.gesture(DragGesture(...).onEnded { value in … }), with the value.
on_drag_ended tells the handler only that a
drag ended. This one hands over where it started, where it finished and
how fast it was moving — see views::DragValue.
let card = text("drag me").on_drag_value(1.0, |v| {
let (dx, dy) = v.translation();
println!("moved {dx} x {dy}");
});Sourcepub fn on_magnify(self, minimum_scale_delta: f64) -> Self
pub fn on_magnify(self, minimum_scale_delta: f64) -> Self
.gesture(MagnifyGesture(...))
Sourcepub fn on_magnify_value(
self,
minimum_scale_delta: f64,
action: impl Fn(MagnifyValue) + 'static,
) -> Self
pub fn on_magnify_value( self, minimum_scale_delta: f64, action: impl Fn(MagnifyValue) + 'static, ) -> Self
.gesture(MagnifyGesture(...).onEnded { value in … })
on_magnify attaches the gesture with nothing
listening — it builds the value Swift would and can never be seen to
fire. This one hands over the magnification, the velocity and where the
pinch was centred; see views::MagnifyValue.
Sourcepub fn on_rotate_value(
self,
minimum_degrees: f64,
action: impl Fn(RotateValue) + 'static,
) -> Self
pub fn on_rotate_value( self, minimum_degrees: f64, action: impl Fn(RotateValue) + 'static, ) -> Self
.gesture(RotateGesture(...).onEnded { value in … })
As on_rotate, but the handler is told how far.
Angle stores radians, so views::RotateValue::degrees converts
rather than reading a second field.
Sourcepub fn popover(self, presented: bool, content: View) -> Self
pub fn popover(self, presented: bool, content: View) -> Self
.popover(isPresented:content:) with a fixed flag — undismissable.
See View::popover_bound.
Sourcepub fn popover_bound(self, state: &BoundState<bool>, content: View) -> Self
pub fn popover_bound(self, state: &BoundState<bool>, content: View) -> Self
.popover(isPresented:content:) bound to Rust state, so tapping outside
writes false back.
Sourcepub fn on_change(self, value: i64, handler: impl Fn(i64, i64) + 'static) -> Self
pub fn on_change(self, value: i64, handler: impl Fn(i64, i64) + 'static) -> Self
.onChange(of:_:), watching an Int.
Sourcepub fn on_change_str(
self,
value: &str,
handler: impl Fn(String, String) + 'static,
) -> Self
pub fn on_change_str( self, value: &str, handler: impl Fn(String, String) + 'static, ) -> Self
.onChange(of:initial:_:) over a String.
onChange is one of the modifiers an application reaches for most, and
it could only watch an Int — a search term, a selected identifier, a
mode name all had to be turned into a number first. Swift constrains the
watched value to Equatable and nothing else.
let v = text("results").on_change_str("query", |was, now| {
println!("search went from {was:?} to {now:?}");
});Sourcepub fn on_change_bool(
self,
value: bool,
handler: impl Fn(bool, bool) + 'static,
) -> Self
pub fn on_change_bool( self, value: bool, handler: impl Fn(bool, bool) + 'static, ) -> Self
.onChange(of:initial:_:) over a Bool.
Sourcepub fn on_change_f64(
self,
value: f64,
handler: impl Fn(f64, f64) + 'static,
) -> Self
pub fn on_change_f64( self, value: f64, handler: impl Fn(f64, f64) + 'static, ) -> Self
.onChange(of:initial:_:) over a Double.
Sourcepub fn toolbar_customizable(
self,
toolbar_id: &str,
item_id: &str,
shows_by_default: bool,
content: View,
) -> Self
pub fn toolbar_customizable( self, toolbar_id: &str, item_id: &str, shows_by_default: bool, content: View, ) -> Self
.toolbar(id:) { ToolbarItem(id:showsByDefault:) { content } } — a
toolbar the user can rearrange, remembered under toolbar_id.
shows_by_default is whether the item is there before any
customization; false leaves it in the palette until it is dragged in.
Sourcepub fn transition(self, kind: Transition) -> Self
pub fn transition(self, kind: Transition) -> Self
.transition(.opacity)
Examples found in repository?
129fn body() -> View {
130 let colour = COLORS[COLOR.load(Ordering::Relaxed) % COLORS.len()];
131
132 vstack![
133 // Text("Why not try…").font(.largeTitle.bold())
134 text("Why not try…").text_style(TextStyle::LargeTitle).bold(),
135 vstack![
136 // Circle().fill(colors.randomElement() ?? .blue).padding().overlay(…)
137 circle_shape().fill_system(colour).padding(16.0).overlay(
138 // Image(systemName: "figure.\(selected.lowercased())")
139 // .font(.system(size: 144)).foregroundColor(.white)
140 image!("figure.{}", selected().to_lowercase())
141 .font_size(144.0)
142 .fg(Color::WHITE),
143 ),
144 // Text("\(selected)!").font(.title)
145 text!("{}!", selected()).text_style(TextStyle::Title),
146 ]
147 .transition(Transition::Slide)
148 .id(ID.load(Ordering::Relaxed)),
149 spacer(),
150 // Button("Try again") { … }.buttonStyle(.borderedProminent)
151 button("Try again", try_again).button_style(ButtonStyle::BorderedProminent),
152 ]
153}More examples
83fn body() -> View {
84 let todos = items().lock().unwrap().clone();
85 let remaining = todos.iter().filter(|i| !i.done).count();
86
87 vstack_aligned_spacing(
88 &[
89 hstack![
90 text("Todo").text_style(TextStyle::LargeTitle).bold(),
91 spacer(),
92 text!("{remaining} left").fg_system(SystemColor::Gray),
93 ],
94 hstack_spacing(
95 &[
96 textfield_bound("What needs doing?", draft())
97 .text_field_style(views::TextFieldStyle::RoundedBorderTextFieldStyle)
98 .on_submit(SubmitTrigger::Text, add)
99 .submit_label(SubmitLabel::Done),
100 button("Add", add).button_style(views::ButtonStyle::BorderedProminent),
101 ],
102 8.0,
103 ),
104 // The empty state is a branch, so it arrives and leaves rather than
105 // appearing from nothing.
106 view_if!(
107 todos.is_empty(),
108 vstack_spacing(
109 &[
110 system_image("checkmark.seal").view().font_size(40.0)
111 .fg_system(SystemColor::Green),
112 text("Nothing left to do").fg_system(SystemColor::Gray),
113 ],
114 8.0,
115 )
116 .frame_optional(None, Some(160.0), Alignment::Center)
117 .transition(Transition::ScaleWithOpacity { scale: 0.8, anchor: (0.5, 0.5) }),
118 list(for_each_items(
119 &todos.iter().cloned().enumerate().collect::<Vec<_>>(),
120 |(i, it)| row(*i, it),
121 ))
122 .list_style(views::ListStyle::PlainListStyle)
123 ),
124 ],
125 HorizontalAlignment::Leading,
126 Some(14.0),
127 )
128 .padding(20.0)
129}Sourcepub fn id(self, value: i64) -> Self
pub fn id(self, value: i64) -> Self
.id(_) — the identity SwiftUI diffs against.
Changing it replaces the view rather than updating it, which is what makes a transition play: the old identity leaves, the new one arrives.
Examples found in repository?
129fn body() -> View {
130 let colour = COLORS[COLOR.load(Ordering::Relaxed) % COLORS.len()];
131
132 vstack![
133 // Text("Why not try…").font(.largeTitle.bold())
134 text("Why not try…").text_style(TextStyle::LargeTitle).bold(),
135 vstack![
136 // Circle().fill(colors.randomElement() ?? .blue).padding().overlay(…)
137 circle_shape().fill_system(colour).padding(16.0).overlay(
138 // Image(systemName: "figure.\(selected.lowercased())")
139 // .font(.system(size: 144)).foregroundColor(.white)
140 image!("figure.{}", selected().to_lowercase())
141 .font_size(144.0)
142 .fg(Color::WHITE),
143 ),
144 // Text("\(selected)!").font(.title)
145 text!("{}!", selected()).text_style(TextStyle::Title),
146 ]
147 .transition(Transition::Slide)
148 .id(ID.load(Ordering::Relaxed)),
149 spacer(),
150 // Button("Try again") { … }.buttonStyle(.borderedProminent)
151 button("Try again", try_again).button_style(ButtonStyle::BorderedProminent),
152 ]
153}Sourcepub fn animation(self, value: i64) -> Self
pub fn animation(self, value: i64) -> Self
.animation(.default, value:)
Examples found in repository?
54fn body() -> View {
55 vstack_aligned_spacing(
56 &[
57 text("System").text_style(TextStyle::LargeTitle).bold(),
58 grid(&[grid_row(&[tile(0), tile(1), tile(2)])]),
59 divider(),
60 // A gauge over the busiest reading, which is a different control
61 // from the rings and reads the same state.
62 vstack_aligned(
63 &[
64 text("Busiest").font_size(12.0).fg_system(SystemColor::Gray),
65 gauge(reading(1), 0.0, 1.0, text("Memory"))
66 .gauge_style(views::GaugeStyle::AccessoryLinearCapacityGaugeStyle)
67 .tint_system(SystemColor::Orange),
68 ],
69 HorizontalAlignment::Leading,
70 ),
71 spacer(),
72 button("Refresh", refresh)
73 .button_style(views::ButtonStyle::BorderedProminent)
74 .keyboard_shortcut(KeyboardShortcut::DefaultAction),
75 ],
76 HorizontalAlignment::Leading,
77 Some(16.0),
78 )
79 .padding(20.0)
80 // Animate whatever changed, rather than snapping to the new reading.
81 .animation(LOAD[0].load(Ordering::Relaxed) as i64)
82}.contextMenu(menuItems:)
.contextMenu(menuItems:preview:) — a menu with something to look at.
The preview is what a long press enlarges before the menu appears: the
row blown up, a photo, a card. context_menu has
no such slot, so the menu came up over the view as it already was.
let row = text("Photo").context_menu_preview(
button("Delete", || {}),
image("photo").frame(200.0, 200.0),
);Sourcepub fn scroll(self) -> Self
pub fn scroll(self) -> Self
Wrap in a vertical ScrollView.
Examples found in repository?
487fn node_view(node: &Node) -> Result<View, String> {
488 let spacing = node.f64_attr("spacing").unwrap_or(8.0);
489 let base = match node.name.as_str() {
490 "vstack" => {
491 let kids = children(node)?;
492 match node.attr("align") {
493 Some(a) => vstack_aligned_spacing(&kids, h_align(a, node.line)?, Some(spacing)),
494 None => vstack_spacing(&kids, spacing),
495 }
496 }
497 "hstack" => {
498 let kids = children(node)?;
499 match node.attr("align") {
500 Some(a) => hstack_aligned_spacing(&kids, v_align(a, node.line)?, Some(spacing)),
501 None => hstack_spacing(&kids, spacing),
502 }
503 }
504 "zstack" => zstack_aligned(&children(node)?, align(node.attr("align").unwrap_or("center"), node.line)?),
505 "text" => {
506 let s = node.value.as_deref().unwrap_or("");
507 let mut v = text(s);
508 if let Some(style) = node.attr("style") {
509 v = v.text_style(text_style(style, node.line)?);
510 }
511 if let Some(size) = node.f64_attr("size") {
512 v = v.font_size(size);
513 }
514 if node.flag("bold") {
515 v = v.bold();
516 }
517 if node.flag("italic") {
518 v = v.italic();
519 }
520 if let Some(c) = node.attr("color") {
521 v = match tint(c, node.line)? {
522 Tint::System(sc) => v.fg_system(sc),
523 Tint::Literal(lc) => v.fg(lc),
524 };
525 }
526 v
527 }
528 "spacer" => spacer(),
529 "divider" => divider(),
530 // The action is a no-op on purpose: a spec read from a file has nowhere
531 // to put behaviour, and pretending otherwise would be worse than a
532 // button that visibly does nothing. `hot_reload.rs` is where a spec
533 // gains behaviour, by being reloaded.
534 "button" => button(node.value.as_deref().unwrap_or("Button"), || {}),
535 "color" => color(parse_color(node.value.as_deref().unwrap_or("#808080"), node.line)?),
536 "image" => system_image(node.value.as_deref().unwrap_or("star")).into_view(),
537 "rect" => match node.attr("color") {
538 Some(c) => match tint(c, node.line)? {
539 Tint::System(sc) => rectangle_shape().fill_system(sc),
540 Tint::Literal(lc) => rectangle_shape().fill(lc),
541 },
542 None => rectangle_shape().into_view(),
543 },
544 "circle" => match node.attr("color") {
545 Some(c) => match tint(c, node.line)? {
546 Tint::System(sc) => circle_shape().fill_system(sc),
547 Tint::Literal(lc) => circle_shape().fill(lc),
548 },
549 None => circle_shape().into_view(),
550 },
551 "capsule" => match node.attr("color") {
552 Some(c) => match tint(c, node.line)? {
553 Tint::System(sc) => capsule_shape().fill_system(sc),
554 Tint::Literal(lc) => capsule_shape().fill(lc),
555 },
556 None => capsule_shape().into_view(),
557 },
558 "progress" => progress(
559 node.value.as_deref().and_then(|v| v.parse().ok()).unwrap_or(0.5),
560 node.f64_attr("total").unwrap_or(1.0),
561 ),
562 "gauge" => gauge(
563 node.value.as_deref().and_then(|v| v.parse().ok()).unwrap_or(0.5),
564 node.f64_attr("min").unwrap_or(0.0),
565 node.f64_attr("max").unwrap_or(1.0),
566 text(node.attr("label").unwrap_or("")),
567 ),
568 "group_box" => group_box(stack_children(node)?),
569 "list" => list(stack_children(node)?),
570 "scroll" => stack_children(node)?.scroll(),
571 "form" => form(stack_children(node)?),
572 // Every bound control needs an explicit `@name`.
573 //
574 // Inventing one — from the line, or from position in the tree — looks
575 // friendlier and is a trap: adding a line above a `toggle` would
576 // change its derived name, and the control would silently reset on the
577 // next reload. A name the file states is a name that survives the file
578 // being edited, which is the entire point of the slots.
579 "toggle" => toggle_bound(
580 node.value.as_deref().unwrap_or("Toggle"),
581 &flag_slot(&require_slot(node)?, node.flag("on")),
582 ),
583 "slider" => {
584 let lo = node.f64_attr("min").unwrap_or(0.0);
585 let hi = node.f64_attr("max").unwrap_or(1.0);
586 slider_bound(
587 &number_slot(&require_slot(node)?, node.f64_attr("value").unwrap_or(lo)),
588 lo,
589 hi,
590 )
591 }
592 "stepper" => stepper_bound(
593 node.value.as_deref().unwrap_or("Stepper"),
594 &number_slot(&require_slot(node)?, node.f64_attr("value").unwrap_or(0.0)),
595 node.f64_attr("min").unwrap_or(0.0),
596 node.f64_attr("max").unwrap_or(100.0),
597 node.f64_attr("step").unwrap_or(1.0),
598 ),
599 "field" => textfield_bound(
600 node.value.as_deref().unwrap_or(""),
601 &string_slot(&require_slot(node)?, node.attr("text").unwrap_or("")),
602 ),
603 "label" => label(
604 node.value.as_deref().unwrap_or(""),
605 node.attr("icon").unwrap_or("star"),
606 ),
607 other => {
608 return Err(format!(
609 "line {}: no view called `{other}`; try one of {}",
610 node.line,
611 NAMES.join(", ")
612 ))
613 }
614 };
615 decorate(base, node)
616}Sourcepub fn position(self, x: f64, y: f64) -> Self
pub fn position(self, x: f64, y: f64) -> Self
.position(x:y:) — place the view’s centre at a point in its parent,
which is not the same as .offset(x:y:) moving it from where it was.
Sourcepub fn hue_rotation(self, radians: f64) -> Self
pub fn hue_rotation(self, radians: f64) -> Self
.hueRotation(.radians(_))
Sourcepub fn color_multiply(self, color: Color) -> Self
pub fn color_multiply(self, color: Color) -> Self
.colorMultiply(_:) — multiply every pixel by a colour, which tints
without covering.
Sourcepub fn content_transition(self, transition: ContentTransition) -> Self
pub fn content_transition(self, transition: ContentTransition) -> Self
.contentTransition(_:) — how a change to the content animates, as
distinct from the view arriving or leaving.
Sourcepub fn projection_effect(self, m: [f64; 9]) -> Self
pub fn projection_effect(self, m: [f64; 9]) -> Self
.projectionEffect(_:) — a 3x3 projection, row-major.
Sourcepub fn aspect_ratio_mode(self, fill: bool) -> Self
pub fn aspect_ratio_mode(self, fill: bool) -> Self
.aspectRatio(contentMode:) without pinning a ratio — true fills,
false fits.
Sourcepub fn safe_area_padding(self, length: f64) -> Self
pub fn safe_area_padding(self, length: f64) -> Self
.safeAreaPadding(_:) — padding measured from the safe area rather than
from the view.
Sourcepub fn content_margins(
self,
length: f64,
placement: ContentMarginPlacement,
) -> Self
pub fn content_margins( self, length: f64, placement: ContentMarginPlacement, ) -> Self
.contentMargins(_:for:)
Sourcepub fn container_shape(self, shape: InsettableShape) -> Self
pub fn container_shape(self, shape: InsettableShape) -> Self
.containerShape(_:) — the shape descendants inherit for clipping.
Sourcepub fn coordinate_space(self, name: HashableValue<'_>) -> Self
pub fn coordinate_space(self, name: HashableValue<'_>) -> Self
.coordinateSpace(_:) — name this view’s space so a GeometryProxy can
report positions relative to it.
Sourcepub fn grid_cell_unsized_axes(self, axes: AxisSet) -> Self
pub fn grid_cell_unsized_axes(self, axes: AxisSet) -> Self
.gridCellUnsizedAxes(_:) — axes this cell should not stretch along.
Sourcepub fn grid_column_alignment(self, alignment: HorizontalAlignment) -> Self
pub fn grid_column_alignment(self, alignment: HorizontalAlignment) -> Self
.gridColumnAlignment(_:)
Sourcepub fn alignment_guide(
self,
alignment: HorizontalAlignment,
compute: impl Fn(ViewDimensions) -> f64 + 'static,
) -> Self
pub fn alignment_guide( self, alignment: HorizontalAlignment, compute: impl Fn(ViewDimensions) -> f64 + 'static, ) -> Self
.alignmentGuide(_:computeValue:) — move where this view lines up with
its siblings without moving the view.
compute is handed the view’s views::ViewDimensions and answers in
terms of them, which is what an alignment guide is for: returning
d.width / 2.0 lines the view up by its centre, d.width by its far
edge. It used to take no arguments, so the only guide it could express
was a constant — the one kind that does not need the modifier.
let v = text("centred").alignment_guide(HorizontalAlignment::Leading, |d| d.width / 2.0);Sourcepub fn container_relative_frame(
self,
axes: &[AxisSet],
alignment: Alignment,
) -> Self
pub fn container_relative_frame( self, axes: &[AxisSet], alignment: Alignment, ) -> Self
.containerRelativeFrame(_:alignment:) — size against the container
rather than the content, which is what makes a carousel page.
Sourcepub fn container_relative_frame_thirds(
self,
axes: &[AxisSet],
alignment: Alignment,
) -> Self
pub fn container_relative_frame_thirds( self, axes: &[AxisSet], alignment: Alignment, ) -> Self
.containerRelativeFrame(_:count:span:spacing:alignment:) at thirds.
Sourcepub fn on_geometry_change(
self,
measure: impl Fn(f64, f64) -> i64 + 'static,
action: impl Fn(i64, i64) + 'static,
) -> Self
pub fn on_geometry_change( self, measure: impl Fn(f64, f64) -> i64 + 'static, action: impl Fn(i64, i64) + 'static, ) -> Self
.onGeometryChange(for:of:action:) — observe the measured geometry.
measure is handed the view’s width and height and returns the value to
watch; action is called with the old and the new one whenever that
value changes. Both used to be blind — measure took no arguments, so
it could not read the geometry the modifier exists to report, and
action was told only that something had changed.
let v = text("wide?").on_geometry_change(
|w, _h| (w > 400.0) as i64,
|was, now| println!("wide: {was} -> {now}"),
);Sourcepub fn on_geometry_change_f64(
self,
measure: impl Fn(f64, f64) -> f64 + 'static,
action: impl Fn(f64, f64) + 'static,
) -> Self
pub fn on_geometry_change_f64( self, measure: impl Fn(f64, f64) -> f64 + 'static, action: impl Fn(f64, f64) + 'static, ) -> Self
.onGeometryChange(for: Double.self, of:action:) — the same, watching a
Double.
Which is usually what is wanted: the value being watched is nearly
always a width or a height, and for: Int.self meant rounding it before
it could be watched at all.
let v = text("wide?").on_geometry_change_f64(|w, _h| w, |was, now| {
println!("width {was} -> {now}");
});Sourcepub fn clip_ellipse(self) -> Self
pub fn clip_ellipse(self) -> Self
.clipShape(Ellipse())
Sourcepub fn layout_direction_behavior(self, value: LayoutDirectionBehavior) -> Self
pub fn layout_direction_behavior(self, value: LayoutDirectionBehavior) -> Self
.layoutDirectionBehavior(_:) — whether this mirrors in a
right-to-left language.
Sourcepub fn layout_value(self, value: i64) -> Self
pub fn layout_value(self, value: i64) -> Self
.layoutValue(key:value:)
Sourcepub fn container_corner_offset(self, edges: EdgeSet, value: bool) -> Self
pub fn container_corner_offset(self, edges: EdgeSet, value: bool) -> Self
.containerCornerOffset(_:)
Sourcepub fn safe_area_bar(
self,
edge: VerticalEdge,
alignment: HorizontalAlignment,
spacing: Option<f64>,
content: View,
) -> Self
pub fn safe_area_bar( self, edge: VerticalEdge, alignment: HorizontalAlignment, spacing: Option<f64>, content: View, ) -> Self
.safeAreaBar(edge:alignment:spacing:content:) — a bar that shrinks the
safe area, as View::safe_area_inset does, but styled as a bar.
Sourcepub fn ignores_safe_area(self) -> Self
pub fn ignores_safe_area(self) -> Self
.ignoresSafeArea() — let the view run under the notch, the home
indicator and the keyboard, which is what a full-bleed background wants.
Sourcepub fn ignores_safe_area_edges(
self,
regions: SafeAreaRegions,
edges: EdgeSet,
) -> Self
pub fn ignores_safe_area_edges( self, regions: SafeAreaRegions, edges: EdgeSet, ) -> Self
.ignoresSafeArea(_:edges:) — the same, but only the regions and edges
named. .ignoresSafeArea(.keyboard) alone is the common case.
Sourcepub fn safe_area_inset(
self,
edge: VerticalEdge,
alignment: HorizontalAlignment,
spacing: Option<f64>,
content: View,
) -> Self
pub fn safe_area_inset( self, edge: VerticalEdge, alignment: HorizontalAlignment, spacing: Option<f64>, content: View, ) -> Self
.safeAreaInset(edge:alignment:spacing:) { … } — put a view against one
edge and shrink this view’s safe area by however tall it turns out to
be. A bottom bar that scrolling content stops above, without measuring.
Sourcepub fn scroll_indicators(
self,
visibility: ScrollIndicatorVisibility,
axes: AxisSet,
) -> Self
pub fn scroll_indicators( self, visibility: ScrollIndicatorVisibility, axes: AxisSet, ) -> Self
.scrollIndicators(_:axes:)
The axis is not optional here as it is in Swift: SwiftUI’s default is
[.horizontal, .vertical], and Axis.Set has no .all static to name
that pair with, so a no-axis convenience would have to quietly pick one.
Sourcepub fn content_shape(self, shape: InsettableShape) -> Self
pub fn content_shape(self, shape: InsettableShape) -> Self
.contentShape(_:) — the region that takes hits, which is otherwise the
view’s frame. A circular button in a square frame needs this or its
corners stay tappable.
Sourcepub fn tag(self, value: HashableValue<'_>) -> Self
pub fn tag(self, value: HashableValue<'_>) -> Self
.tag(_:) — the value a Picker or TabView selects when this is the
chosen row.
Sourcepub fn tag_int(self, value: i64) -> Self
pub fn tag_int(self, value: i64) -> Self
.tag(_:) with an Int, which is what a Picker bound to
views::BoundState<i64> selects by.
Examples found in repository?
43fn body() -> View {
44 let s = settings();
45
46 form![
47 section![header: text("Account");
48 hstack![
49 text("Name"),
50 spacer(),
51 textfield_bound("Your name", &s.name).text_field_style(
52 views::TextFieldStyle::RoundedBorderTextFieldStyle,
53 ),
54 ],
55 toggle_bound("Notifications", &s.notify),
56 ],
57 section![header: text("Playback");
58 vstack_aligned(&[
59 hstack![
60 text("Volume"),
61 spacer(),
62 text!("{:.0}%", s.volume.get() * 100.0).fg_system(SystemColor::Gray),
63 ],
64 slider_bound(&s.volume, 0.0, 1.0),
65 ], HorizontalAlignment::Leading),
66 stepper_bound("Refresh every", &s.refresh, 1.0, 60.0, 1.0),
67 ],
68 section![header: text("Appearance");
69 picker_bound!(
70 "Theme",
71 &s.theme,
72 text(THEMES[0]).tag_int(0),
73 text(THEMES[1]).tag_int(1),
74 text(THEMES[2]).tag_int(2),
75 )
76 .picker_style(PickerStyle::InlinePickerStyle),
77 ],
78 section![
79 button("About", show_about)
80 .a11y_hint("Opens a panel describing this app"),
81 ],
82 ]
83 .form_style(FormStyle::GroupedFormStyle)
84 .sheet_bound(&s.about, about_panel())
85}Sourcepub fn task(self, action: impl Fn() + Send + Sync + 'static) -> Self
pub fn task(self, action: impl Fn() + Send + Sync + 'static) -> Self
.task { … } — run the action once when the view appears, cancelled if
it goes away first.
#[track_caller] so the task carries the call site’s file and line,
which is what SwiftUI names it by in Instruments — taking file!() here
would name every task after this file.
Sourcepub fn task_id(self, id: i64, action: impl Fn() + Send + Sync + 'static) -> Self
pub fn task_id(self, id: i64, action: impl Fn() + Send + Sync + 'static) -> Self
.task(id:) { … } — as task, but restarted whenever the
identity changes.
SwiftUI cancels the running task and starts a new one when id differs
from the last body evaluation, which is how a detail view re-fetches
when the selection moves. views::task has always built this; it had
no chainable method, so the DSL could only ever start a task once.
Sourcepub fn image_scale(self, scale: ImageScale) -> Self
pub fn image_scale(self, scale: ImageScale) -> Self
.imageScale(_:) — how large an SF Symbol draws relative to its font.
Source§impl View
impl View
.navigationDestination(isPresented:destination:) bound to Rust state —
pushing sets it, and the back button writes false back.
Sourcepub fn inspector(self, state: &BoundState<bool>, content: View) -> Self
pub fn inspector(self, state: &BoundState<bool>, content: View) -> Self
.inspector(isPresented:content:) bound to Rust state.
Sourcepub fn inspector_column_width(self, width: f64) -> Self
pub fn inspector_column_width(self, width: f64) -> Self
.inspectorColumnWidth(_:) — one fixed width for the inspector column.
Sourcepub fn inspector_column_width_range(
self,
min: Option<f64>,
ideal: f64,
max: Option<f64>,
) -> Self
pub fn inspector_column_width_range( self, min: Option<f64>, ideal: f64, max: Option<f64>, ) -> Self
.inspectorColumnWidth(min:ideal:max:) — a width the user can drag
within.
None for a bound leaves the column unconstrained in that direction,
which is not the same as pinning it to zero. .inspector_column_width
above is the fixed spelling.
Sourcepub fn toolbar_background(
self,
visibility: Visibility,
placements: &[ToolbarPlacement],
) -> Self
pub fn toolbar_background( self, visibility: Visibility, placements: &[ToolbarPlacement], ) -> Self
.toolbarBackground(_:for:)
Sourcepub fn toolbar_visibility(
self,
visibility: Visibility,
placements: &[ToolbarPlacement],
) -> Self
pub fn toolbar_visibility( self, visibility: Visibility, placements: &[ToolbarPlacement], ) -> Self
.toolbarVisibility(_:for:) — whether the bar shows at all.
SwiftUI also spells this .toolbar(_:for:); this reaches the named one.
Sourcepub fn toolbar_title_display_mode(self, mode: ToolbarTitleDisplayMode) -> Self
pub fn toolbar_title_display_mode(self, mode: ToolbarTitleDisplayMode) -> Self
.toolbarTitleDisplayMode(_:) — large title or inline.
Sourcepub fn toolbar_role(self, role: ToolbarRole) -> Self
pub fn toolbar_role(self, role: ToolbarRole) -> Self
.toolbarRole(_:)
Sourcepub fn searchable(
self,
text: &BoundState<String>,
presented: &BoundState<bool>,
placement: SearchFieldPlacement,
prompt: &str,
) -> Self
pub fn searchable( self, text: &BoundState<String>, presented: &BoundState<bool>, placement: SearchFieldPlacement, prompt: &str, ) -> Self
.searchable(text:isPresented:placement:prompt:), both bindings owned by
Rust — the query text lands in text as it is typed.
.navigationSplitViewStyle(.automatic)
.navigationViewStyle(.automatic)
.navigationDocument(_:)
.navigationDocument(_:) with a URL.
Sourcepub fn toolbar_background_visibility(
self,
visibility: Visibility,
placements: &[ToolbarPlacement],
) -> Self
pub fn toolbar_background_visibility( self, visibility: Visibility, placements: &[ToolbarPlacement], ) -> Self
.toolbarBackgroundVisibility(_:for:) — distinct from
View::toolbar_background, which sets what the background is.
Sourcepub fn toolbar_color_scheme(
self,
scheme: Option<ColorScheme>,
placements: &[ToolbarPlacement],
) -> Self
pub fn toolbar_color_scheme( self, scheme: Option<ColorScheme>, placements: &[ToolbarPlacement], ) -> Self
.toolbarColorScheme(_:in:) — None restores the inherited scheme.
.toolbarTitleMenu(content:) — the menu behind a tappable title.
Sourcepub fn presentation_sizing(self) -> Self
pub fn presentation_sizing(self) -> Self
.presentationSizing(_:)
Sourcepub fn presentation_background_interaction(
self,
value: PresentationBackgroundInteraction,
) -> Self
pub fn presentation_background_interaction( self, value: PresentationBackgroundInteraction, ) -> Self
.presentationBackgroundInteraction(_:) — whether what is behind a
sheet still takes touches, which is what makes a half-sheet usable.
Sourcepub fn presentation_compact_adaptation(
self,
value: PresentationAdaptation,
) -> Self
pub fn presentation_compact_adaptation( self, value: PresentationAdaptation, ) -> Self
.presentationCompactAdaptation(_:) — what a popover becomes when the
size class is compact, which on a phone is always.
Sourcepub fn presentation_content_interaction(
self,
value: PresentationContentInteraction,
) -> Self
pub fn presentation_content_interaction( self, value: PresentationContentInteraction, ) -> Self
.presentationContentInteraction(_:) — whether a drag resizes the sheet
or scrolls its content.
.navigationTransition(_:)
.navigationSplitViewColumnWidth(_:)
Sourcepub fn matched_transition_source(self, id: HashableValue<'_>) -> Self
pub fn matched_transition_source(self, id: HashableValue<'_>) -> Self
.matchedTransitionSource(id:in:) — the view a zoom transition grows
from, paired with View::matched_geometry_effect’s destination.
Sourcepub fn presentation_detents(self, detents: &[PresentationDetent]) -> Self
pub fn presentation_detents(self, detents: &[PresentationDetent]) -> Self
.presentationDetents(_:) — the heights a sheet can rest at, which is
what makes it a half-sheet rather than a full one.
Examples found in repository?
89fn about_panel() -> View {
90 let s = settings();
91 vstack_spacing(
92 &[
93 system_image("gearshape.fill")
94 .symbol_rendering_mode(Some(views::SymbolRenderingMode::Hierarchical))
95 .view()
96 .font_size(48.0)
97 .fg_system(SystemColor::Blue),
98 text("Settings").text_style(TextStyle::Title).bold(),
99 text!("Signed in as {}", s.name.get()).fg_system(SystemColor::Gray),
100 spacer(),
101 button("Done", hide_about).button_style(views::ButtonStyle::BorderedProminent),
102 ],
103 16.0,
104 )
105 .padding(24.0)
106 .presentation_detents(&[views::PresentationDetent::Medium])
107 .presentation_drag_indicator(Visibility::Visible)
108}Sourcepub fn presentation_drag_indicator(self, visibility: Visibility) -> Self
pub fn presentation_drag_indicator(self, visibility: Visibility) -> Self
.presentationDragIndicator(_:)
Examples found in repository?
89fn about_panel() -> View {
90 let s = settings();
91 vstack_spacing(
92 &[
93 system_image("gearshape.fill")
94 .symbol_rendering_mode(Some(views::SymbolRenderingMode::Hierarchical))
95 .view()
96 .font_size(48.0)
97 .fg_system(SystemColor::Blue),
98 text("Settings").text_style(TextStyle::Title).bold(),
99 text!("Signed in as {}", s.name.get()).fg_system(SystemColor::Gray),
100 spacer(),
101 button("Done", hide_about).button_style(views::ButtonStyle::BorderedProminent),
102 ],
103 16.0,
104 )
105 .padding(24.0)
106 .presentation_detents(&[views::PresentationDetent::Medium])
107 .presentation_drag_indicator(Visibility::Visible)
108}Sourcepub fn presentation_corner_radius(self, radius: Option<f64>) -> Self
pub fn presentation_corner_radius(self, radius: Option<f64>) -> Self
.presentationCornerRadius(_:) — None restores the system radius.
Sourcepub fn presentation_background(
self,
alignment: Alignment,
content: View,
) -> Self
pub fn presentation_background( self, alignment: Alignment, content: View, ) -> Self
.presentationBackground(alignment:content:)
Sourcepub fn tint_system(self, c: SystemColor) -> Self
pub fn tint_system(self, c: SystemColor) -> Self
.tint(_:) with one of SwiftUI’s own colours.
View::tint takes a literal Color; a named colour is not a fixed
triple, so for an accent — which is what the system draws controls with —
naming it is usually what is meant.
Examples found in repository?
54fn body() -> View {
55 vstack_aligned_spacing(
56 &[
57 text("System").text_style(TextStyle::LargeTitle).bold(),
58 grid(&[grid_row(&[tile(0), tile(1), tile(2)])]),
59 divider(),
60 // A gauge over the busiest reading, which is a different control
61 // from the rings and reads the same state.
62 vstack_aligned(
63 &[
64 text("Busiest").font_size(12.0).fg_system(SystemColor::Gray),
65 gauge(reading(1), 0.0, 1.0, text("Memory"))
66 .gauge_style(views::GaugeStyle::AccessoryLinearCapacityGaugeStyle)
67 .tint_system(SystemColor::Orange),
68 ],
69 HorizontalAlignment::Leading,
70 ),
71 spacer(),
72 button("Refresh", refresh)
73 .button_style(views::ButtonStyle::BorderedProminent)
74 .keyboard_shortcut(KeyboardShortcut::DefaultAction),
75 ],
76 HorizontalAlignment::Leading,
77 Some(16.0),
78 )
79 .padding(20.0)
80 // Animate whatever changed, rather than snapping to the new reading.
81 .animation(LOAD[0].load(Ordering::Relaxed) as i64)
82}Sourcepub fn search_toolbar_behavior(self, value: SearchToolbarBehavior) -> Self
pub fn search_toolbar_behavior(self, value: SearchToolbarBehavior) -> Self
.searchToolbarBehavior(_:)
Sourcepub fn search_presentation_toolbar_behavior(
self,
value: SearchPresentationToolbarBehavior,
) -> Self
pub fn search_presentation_toolbar_behavior( self, value: SearchPresentationToolbarBehavior, ) -> Self
.searchPresentationToolbarBehavior(_:)
Sourcepub fn text_selection_affinity(self, value: TextSelectionAffinity) -> Self
pub fn text_selection_affinity(self, value: TextSelectionAffinity) -> Self
.textSelectionAffinity(_:)
Sourcepub fn type_select_equivalent(self, text: Option<&str>) -> Self
pub fn type_select_equivalent(self, text: Option<&str>) -> Self
.typeSelectEquivalent(_:) — what typing in a list jumps to.
Sourcepub fn search_scopes(self, scope: &BoundState<i64>, scopes: View) -> Self
pub fn search_scopes(self, scope: &BoundState<i64>, scopes: View) -> Self
.searchScopes(_:scopes:) bound to Rust state — the chosen scope lands
in scope.
Sourcepub fn search_suggestions(
self,
visibility: Visibility,
placements: SearchSuggestionsPlacementSet,
) -> Self
pub fn search_suggestions( self, visibility: Visibility, placements: SearchSuggestionsPlacementSet, ) -> Self
.searchSuggestions(_:for:) — where suggestions may appear.
Sourcepub fn search_selection(self, changed: impl Fn() + 'static) -> Self
pub fn search_selection(self, changed: impl Fn() + 'static) -> Self
.searchSelection(_:)
Sourcepub fn search_focused(self) -> Self
pub fn search_focused(self) -> Self
.searchFocused(_:)
Sourcepub fn text_input_suggestions(self, count: usize, content: View) -> Self
pub fn text_input_suggestions(self, count: usize, content: View) -> Self
.textInputSuggestions { … } — completions offered under a field.
.findNavigator(isPresented:) bound to Rust state — the find bar.
Source§impl View
impl View
Sourcepub fn file_exporter(
self,
state: &BoundState<bool>,
item: Option<&str>,
kinds: &[ContentType],
default_filename: Option<&str>,
completion: impl Fn(FileOutcome) + 'static,
cancellation: impl Fn() + 'static,
) -> Self
pub fn file_exporter( self, state: &BoundState<bool>, item: Option<&str>, kinds: &[ContentType], default_filename: Option<&str>, completion: impl Fn(FileOutcome) + 'static, cancellation: impl Fn() + 'static, ) -> Self
.fileExporter(isPresented:item:contentTypes:defaultFilename:onCompletion:onCancellation:)
Sourcepub fn file_importer(
self,
state: &BoundState<bool>,
kinds: &[ContentType],
completion: impl Fn(FileOutcome) + 'static,
) -> Self
pub fn file_importer( self, state: &BoundState<bool>, kinds: &[ContentType], completion: impl Fn(FileOutcome) + 'static, ) -> Self
.fileImporter(isPresented:allowedContentTypes:onCompletion:)
Sourcepub fn file_mover(
self,
state: &BoundState<bool>,
file: Option<&str>,
completion: impl Fn(FileOutcome) + 'static,
) -> Self
pub fn file_mover( self, state: &BoundState<bool>, file: Option<&str>, completion: impl Fn(FileOutcome) + 'static, ) -> Self
.fileMover(isPresented:file:onCompletion:)
Sourcepub fn item_provider(self, item: Option<&str>) -> Self
pub fn item_provider(self, item: Option<&str>) -> Self
.itemProvider(_:) — what this view offers to a drag or a service.
Sourcepub fn exports_item_providers(
self,
kinds: &[ContentType],
items: &[&str],
edit: impl Fn(&[ItemProvider]) -> bool + 'static,
) -> Self
pub fn exports_item_providers( self, kinds: &[ContentType], items: &[&str], edit: impl Fn(&[ItemProvider]) -> bool + 'static, ) -> Self
.exportsItemProviders(_:items:onEdit:)
Sourcepub fn imports_item_providers(
self,
kinds: &[ContentType],
accept: impl Fn(&[ItemProvider]) -> bool + 'static,
) -> Self
pub fn imports_item_providers( self, kinds: &[ContentType], accept: impl Fn(&[ItemProvider]) -> bool + 'static, ) -> Self
.importsItemProviders(_:onImport:)
Sourcepub fn exportable_to_services(self, items: &[&str]) -> Self
pub fn exportable_to_services(self, items: &[&str]) -> Self
.exportableToServices(_:) — what the Services menu may take.
Sourcepub fn importable_from_services(
self,
accept: impl Fn(&[String]) -> bool + 'static,
) -> Self
pub fn importable_from_services( self, accept: impl Fn(&[String]) -> bool + 'static, ) -> Self
.importableFromServices(for:action:)
Sourcepub fn on_receive(
self,
complete_immediately: bool,
perform: impl Fn(i64) + 'static,
) -> Self
pub fn on_receive( self, complete_immediately: bool, perform: impl Fn(i64) + 'static, ) -> Self
.onReceive(_:perform:) — a publisher’s values, as Ints.
Sourcepub fn on_scroll_geometry_change(
self,
measure: impl Fn(ScrollGeometry) -> i64 + 'static,
action: impl Fn(i64, i64) + 'static,
) -> Self
pub fn on_scroll_geometry_change( self, measure: impl Fn(ScrollGeometry) -> i64 + 'static, action: impl Fn(i64, i64) + 'static, ) -> Self
.onScrollGeometryChange(for:of:action:)
measure is handed the scroll view’s views::ScrollGeometry and
returns the value to watch; action is called with the old and the new
one. Both used to be blind, which left the modifier able to notice that
something had scrolled and nothing more.
Sourcepub fn on_scroll_geometry_change_f64(
self,
measure: impl Fn(ScrollGeometry) -> f64 + 'static,
action: impl Fn(f64, f64) + 'static,
) -> Self
pub fn on_scroll_geometry_change_f64( self, measure: impl Fn(ScrollGeometry) -> f64 + 'static, action: impl Fn(f64, f64) + 'static, ) -> Self
.onScrollGeometryChange(for: Double.self, …) — the same, watching a
Double, which a scroll offset is.
Sourcepub fn on_scroll_target_visibility_change(
self,
threshold: f64,
visible: impl Fn(&[i64]) + 'static,
) -> Self
pub fn on_scroll_target_visibility_change( self, threshold: f64, visible: impl Fn(&[i64]) + 'static, ) -> Self
.onScrollTargetVisibilityChange(for:threshold:_:) — which targets are
on screen, which is how a carousel knows what page it is on.
Sourcepub fn dismissal_confirmation_dialog(
self,
title: &str,
should_present: bool,
actions: View,
message: View,
) -> Self
pub fn dismissal_confirmation_dialog( self, title: &str, should_present: bool, actions: View, message: View, ) -> Self
.dismissalConfirmationDialog(_:shouldPresent:actions:message:) — ask
before a sheet closes on unsaved work.
Sourcepub fn presentation_prevents_app_termination(
self,
prevents: Option<bool>,
) -> Self
pub fn presentation_prevents_app_termination( self, prevents: Option<bool>, ) -> Self
.presentationPreventsAppTermination(_:) — None restores the default.
Sourcepub fn text_input_formatting_control_visibility(
self,
visibility: Visibility,
placements: TextInputFormattingControlPlacementSet,
) -> Self
pub fn text_input_formatting_control_visibility( self, visibility: Visibility, placements: TextInputFormattingControlPlacementSet, ) -> Self
.textInputFormattingControlVisibility(_:for:)
Sourcepub fn hand_gesture_shortcut(
self,
shortcut: HandGestureShortcut,
enabled: bool,
) -> Self
pub fn hand_gesture_shortcut( self, shortcut: HandGestureShortcut, enabled: bool, ) -> Self
.handGestureShortcut(_:isEnabled:) — the pinch that stands in for a
tap on a watch.
.assistiveAccessNavigationIcon(_:)
Sourcepub fn a11y_rotor(self, label: &str, text: &str) -> Self
pub fn a11y_rotor(self, label: &str, text: &str) -> Self
.accessibilityRotor(_:textRanges:) — a custom rotor VoiceOver can spin
through.
Sourcepub fn a11y_rotor_entry(self, id: HashableValue<'_>) -> Self
pub fn a11y_rotor_entry(self, id: HashableValue<'_>) -> Self
.accessibilityRotorEntry(id:in:)
Sourcepub fn a11y_chart_descriptor(self) -> Self
pub fn a11y_chart_descriptor(self) -> Self
.accessibilityChartDescriptor(_:)
Sourcepub fn environment_object(self) -> Self
pub fn environment_object(self) -> Self
.environmentObject(_:)
Sourcepub fn focused_object(self) -> Self
pub fn focused_object(self) -> Self
.focusedObject(_:)
Sourcepub fn default_app_storage_standard(self) -> Self
pub fn default_app_storage_standard(self) -> Self
.defaultAppStorage(_:)
Sourcepub fn text_renderer(self) -> Self
pub fn text_renderer(self) -> Self
.textRenderer(_:)
Sourcepub fn attributed_text_formatting_definition(self) -> Self
pub fn attributed_text_formatting_definition(self) -> Self
.attributedTextFormattingDefinition(_:)
Sourcepub fn environment_image_scale(self, scale: ImageScale) -> Self
pub fn environment_image_scale(self, scale: ImageScale) -> Self
.environment(\.imageScale, _)
Sourcepub fn environment_symbol_variants(self, value: SymbolVariants) -> Self
pub fn environment_symbol_variants(self, value: SymbolVariants) -> Self
.environment(\.symbolVariants, _)
Sourcepub fn transform_environment_image_scale(
self,
action: impl Fn(ImageScale) -> ImageScale + 'static,
) -> Self
pub fn transform_environment_image_scale( self, action: impl Fn(ImageScale) -> ImageScale + 'static, ) -> Self
.transformEnvironment(\.imageScale, _)
Sourcepub fn focused_value(self, present: bool) -> Self
pub fn focused_value(self, present: bool) -> Self
.focusedValue(_:)
Sourcepub fn preference(self, value: i64) -> Self
pub fn preference(self, value: i64) -> Self
.preference(key:value:) — write a value for an ancestor to collect.
Sourcepub fn on_preference_change(self) -> Self
pub fn on_preference_change(self) -> Self
.onPreferenceChange(_:perform:) — observe what descendants wrote.
The value is read back with views::observed_preference rather than
through a closure, because SwiftUI calls the handler on its own schedule
and the last value is what a caller wants.
Sourcepub fn transform_preference(self) -> Self
pub fn transform_preference(self) -> Self
.transformPreference(_:_:) — rewrite what passes through.
Sourcepub fn anchor_preference(self, transform: impl Fn() -> i64 + 'static) -> Self
pub fn anchor_preference(self, transform: impl Fn() -> i64 + 'static) -> Self
.anchorPreference(key:value:transform:) — write a preference derived
from this view’s geometry.
Sourcepub fn transform_anchor_preference(
self,
transform: impl Fn(i64) -> i64 + 'static,
) -> Self
pub fn transform_anchor_preference( self, transform: impl Fn(i64) -> i64 + 'static, ) -> Self
.transformAnchorPreference(key:value:transform:)
Sourcepub fn overlay_preference_value(
self,
alignment: Alignment,
content: View,
) -> Self
pub fn overlay_preference_value( self, alignment: Alignment, content: View, ) -> Self
.overlayPreferenceValue(_:alignment:_:) — place content over this view
using what a descendant reported, which is how a badge follows the thing
it belongs to.
Sourcepub fn background_preference_value(
self,
alignment: Alignment,
content: View,
) -> Self
pub fn background_preference_value( self, alignment: Alignment, content: View, ) -> Self
.backgroundPreferenceValue(_:alignment:_:)
Sourcepub fn grid_cell_anchor(self, x: f64, y: f64) -> Self
pub fn grid_cell_anchor(self, x: f64, y: f64) -> Self
.gridCellAnchor(_:) — where this cell sits in the space the grid gives
it, as a unit point.
Sourcepub fn popover_anchored(
self,
state: &BoundState<bool>,
anchor: (f64, f64),
arrow_edge: Edge,
content: View,
) -> Self
pub fn popover_anchored( self, state: &BoundState<bool>, anchor: (f64, f64), arrow_edge: Edge, content: View, ) -> Self
.popover(isPresented:attachmentAnchor:arrowEdge:content:) bound to Rust
state — the anchored form, where the arrow points at a chosen point
rather than the view’s middle.
Sourcepub fn window_resize_anchor(self, anchor: Option<(f64, f64)>) -> Self
pub fn window_resize_anchor(self, anchor: Option<(f64, f64)>) -> Self
.windowResizeAnchor(_:) — None restores the default.
Source§impl View
impl View
Sourcepub fn font_size(self, size: f64) -> Self
pub fn font_size(self, size: f64) -> Self
.font(.system(size:))
On a Text this is Text.font(_:), which returns Text, so a chain of
text modifiers stays one type the way Swift’s does.
Examples found in repository?
64pub fn body() -> View {
65 let text_src = current().lock().expect("spec").clone();
66 match spec::parse(&text_src).and_then(|nodes| spec::build(&nodes)) {
67 Ok(v) => v,
68 Err(e) => vstack_aligned_spacing(
69 &[
70 text("Could not build that screen")
71 .text_style(TextStyle::Headline)
72 .fg_system(SystemColor::Red),
73 text(&e).font_size(12.0).fg_system(SystemColor::Secondary),
74 ],
75 HorizontalAlignment::Leading,
76 Some(8.0),
77 )
78 .padding(20.0),
79 }
80}More examples
48fn main_window() -> ViewHandle {
49 vstack(&[
50 text("A SwiftUI app, no Swift source")
51 .font_size(20.0)
52 .padding(8.0),
53 divider(),
54 text(&format!("count: {}", counter().get()))
55 .font_size(34.0)
56 .padding(12.0),
57 hstack(&[
58 button("−", || counter().set(counter().get() - 1)),
59 button("+", || counter().set(counter().get() + 1)),
60 ]),
61 spacer(),
62 text("⌘, for Settings · the ★ in the menu bar has a menu")
63 .font_size(11.0)
64 .opacity(0.6),
65 ])
66 .padding(24.0)
67 .frame(420.0, 300.0)
68 .focused_scene_value(counter_focus_key(), counter().get())
69 .into_handle()
70}
71
72/// The focused-value key the window publishes its count under.
73///
74/// `.focusedSceneValue(\.key, value)` is how a window tells the commands above
75/// it what is selected. Both halves are synthesised at run time: the
76/// `FocusedValueKey` conformance *and* the `WritableKeyPath<FocusedValues, Int?>`
77/// — `FocusedValues` exports no properties, so unlike `EnvironmentValues` there
78/// is no SwiftUI modifier holding a key path to borrow.
79///
80/// The menu cannot *read* it yet: that needs `@FocusedValue`, a `DynamicProperty`
81/// SwiftUI instantiates itself, which is a different mechanism from anything
82/// here. What this demonstrates is the publishing half, in a real app.
83fn counter_focus_key() -> &'static views::FocusKey {
84 static K: std::sync::OnceLock<views::FocusKey> = std::sync::OnceLock::new();
85 K.get_or_init(|| views::focus_key("sceneCounter"))
86}
87
88fn settings_pane() -> ViewHandle {
89 vstack(&[
90 text("Preferences").font_size(18.0),
91 divider(),
92 text("This pane is a `Settings` scene — the one ⌘, opens."),
93 text(&format!("It sees the same state: {}", counter().get()))
94 .opacity(0.7),
95 ])
96 .padding(24.0)
97 .frame(360.0, 200.0)
98 .into_handle()
99}
100
101fn utility_window() -> ViewHandle {
102 vstack(&[
103 text("Utility").font_size(16.0),
104 text("A `Window`, not a `WindowGroup`: one of it, addressed by id.")
105 .opacity(0.7),
106 ])
107 .padding(20.0)
108 .frame(320.0, 140.0)
109 .into_handle()
110}89fn about_panel() -> View {
90 let s = settings();
91 vstack_spacing(
92 &[
93 system_image("gearshape.fill")
94 .symbol_rendering_mode(Some(views::SymbolRenderingMode::Hierarchical))
95 .view()
96 .font_size(48.0)
97 .fg_system(SystemColor::Blue),
98 text("Settings").text_style(TextStyle::Title).bold(),
99 text!("Signed in as {}", s.name.get()).fg_system(SystemColor::Gray),
100 spacer(),
101 button("Done", hide_about).button_style(views::ButtonStyle::BorderedProminent),
102 ],
103 16.0,
104 )
105 .padding(24.0)
106 .presentation_detents(&[views::PresentationDetent::Medium])
107 .presentation_drag_indicator(Visibility::Visible)
108}77fn row(i: usize) -> View {
78 let m = &MESSAGES[i];
79 hstack_spacing(
80 &[
81 // An unread dot, or the space where one would be.
82 view_if!(
83 m.unread,
84 circle_shape().fill_system(SystemColor::Blue).frame(8.0, 8.0),
85 empty().frame(8.0, 8.0)
86 ),
87 vstack_aligned(
88 &[
89 text(m.from).bold(),
90 text(m.subject).font_size(12.0).fg_system(SystemColor::Gray),
91 ],
92 HorizontalAlignment::Leading,
93 ),
94 spacer(),
95 ],
96 8.0,
97 )
98 .padding_edges(EdgeSet::Vertical, Some(4.0))
99 .a11y_label(&format!("{}, {}", m.from, m.subject))
100 .a11y_hint(if m.unread { "Unread" } else { "Read" })
101}28fn tile(i: usize) -> View {
29 let value = reading(i);
30 vstack_spacing(
31 &[
32 zstack![
33 circle_shape().stroke_system(SystemColor::Gray, 6.0).opacity(0.25),
34 // The filled part: the same circle trimmed to the fraction, and
35 // turned so the arc starts at the top rather than at three
36 // o'clock.
37 circle_shape()
38 .trim(0.0, value)
39 .stroke_system(TINTS[i], 6.0)
40 .rotate(-90.0),
41 text!("{:.0}", value * 100.0).text_style(TextStyle::Title2).bold(),
42 ]
43 .frame(72.0, 72.0),
44 text(LABELS[i]).font_size(12.0).fg_system(SystemColor::Gray),
45 ],
46 8.0,
47 )
48 .padding(12.0)
49 .a11y_element(AccessibilityChildBehavior::Combine)
50 .a11y_label(LABELS[i])
51 .a11y_value(&format!("{:.0} percent", value * 100.0))
52}
53
54fn body() -> View {
55 vstack_aligned_spacing(
56 &[
57 text("System").text_style(TextStyle::LargeTitle).bold(),
58 grid(&[grid_row(&[tile(0), tile(1), tile(2)])]),
59 divider(),
60 // A gauge over the busiest reading, which is a different control
61 // from the rings and reads the same state.
62 vstack_aligned(
63 &[
64 text("Busiest").font_size(12.0).fg_system(SystemColor::Gray),
65 gauge(reading(1), 0.0, 1.0, text("Memory"))
66 .gauge_style(views::GaugeStyle::AccessoryLinearCapacityGaugeStyle)
67 .tint_system(SystemColor::Orange),
68 ],
69 HorizontalAlignment::Leading,
70 ),
71 spacer(),
72 button("Refresh", refresh)
73 .button_style(views::ButtonStyle::BorderedProminent)
74 .keyboard_shortcut(KeyboardShortcut::DefaultAction),
75 ],
76 HorizontalAlignment::Leading,
77 Some(16.0),
78 )
79 .padding(20.0)
80 // Animate whatever changed, rather than snapping to the new reading.
81 .animation(LOAD[0].load(Ordering::Relaxed) as i64)
82}129fn body() -> View {
130 let colour = COLORS[COLOR.load(Ordering::Relaxed) % COLORS.len()];
131
132 vstack![
133 // Text("Why not try…").font(.largeTitle.bold())
134 text("Why not try…").text_style(TextStyle::LargeTitle).bold(),
135 vstack![
136 // Circle().fill(colors.randomElement() ?? .blue).padding().overlay(…)
137 circle_shape().fill_system(colour).padding(16.0).overlay(
138 // Image(systemName: "figure.\(selected.lowercased())")
139 // .font(.system(size: 144)).foregroundColor(.white)
140 image!("figure.{}", selected().to_lowercase())
141 .font_size(144.0)
142 .fg(Color::WHITE),
143 ),
144 // Text("\(selected)!").font(.title)
145 text!("{}!", selected()).text_style(TextStyle::Title),
146 ]
147 .transition(Transition::Slide)
148 .id(ID.load(Ordering::Relaxed)),
149 spacer(),
150 // Button("Try again") { … }.buttonStyle(.borderedProminent)
151 button("Try again", try_again).button_style(ButtonStyle::BorderedProminent),
152 ]
153}Sourcepub fn font(
self,
size: f64,
weight: Option<Weight>,
design: Option<Design>,
) -> Self
pub fn font( self, size: f64, weight: Option<Weight>, design: Option<Design>, ) -> Self
.font(.system(size:weight:design:)) — Text.font(_:) on a Text.
Sourcepub fn text_style(self, style: TextStyle) -> Self
pub fn text_style(self, style: TextStyle) -> Self
.font(_:) with a built-in text style.
On a Text this is Text.font(_:), which returns Text — so a chain
like .text_style(.body).bold() stays a Text the way Swift’s does,
instead of each step wrapping the last in an environment modifier.
Examples found in repository?
60fn detail(i: usize) -> View {
61 let m = &MESSAGES[i];
62 vstack_aligned_spacing(
63 &[
64 text(m.subject).text_style(TextStyle::Title).bold(),
65 text!("From {}", m.from).fg_system(SystemColor::Gray),
66 divider(),
67 text("Body text would go here.").fg_system(SystemColor::Gray),
68 spacer(),
69 ],
70 HorizontalAlignment::Leading,
71 Some(12.0),
72 )
73 .padding(20.0)
74 .navigation_title(m.subject)
75}More examples
64pub fn body() -> View {
65 let text_src = current().lock().expect("spec").clone();
66 match spec::parse(&text_src).and_then(|nodes| spec::build(&nodes)) {
67 Ok(v) => v,
68 Err(e) => vstack_aligned_spacing(
69 &[
70 text("Could not build that screen")
71 .text_style(TextStyle::Headline)
72 .fg_system(SystemColor::Red),
73 text(&e).font_size(12.0).fg_system(SystemColor::Secondary),
74 ],
75 HorizontalAlignment::Leading,
76 Some(8.0),
77 )
78 .padding(20.0),
79 }
80}89fn about_panel() -> View {
90 let s = settings();
91 vstack_spacing(
92 &[
93 system_image("gearshape.fill")
94 .symbol_rendering_mode(Some(views::SymbolRenderingMode::Hierarchical))
95 .view()
96 .font_size(48.0)
97 .fg_system(SystemColor::Blue),
98 text("Settings").text_style(TextStyle::Title).bold(),
99 text!("Signed in as {}", s.name.get()).fg_system(SystemColor::Gray),
100 spacer(),
101 button("Done", hide_about).button_style(views::ButtonStyle::BorderedProminent),
102 ],
103 16.0,
104 )
105 .padding(24.0)
106 .presentation_detents(&[views::PresentationDetent::Medium])
107 .presentation_drag_indicator(Visibility::Visible)
108}28fn tile(i: usize) -> View {
29 let value = reading(i);
30 vstack_spacing(
31 &[
32 zstack![
33 circle_shape().stroke_system(SystemColor::Gray, 6.0).opacity(0.25),
34 // The filled part: the same circle trimmed to the fraction, and
35 // turned so the arc starts at the top rather than at three
36 // o'clock.
37 circle_shape()
38 .trim(0.0, value)
39 .stroke_system(TINTS[i], 6.0)
40 .rotate(-90.0),
41 text!("{:.0}", value * 100.0).text_style(TextStyle::Title2).bold(),
42 ]
43 .frame(72.0, 72.0),
44 text(LABELS[i]).font_size(12.0).fg_system(SystemColor::Gray),
45 ],
46 8.0,
47 )
48 .padding(12.0)
49 .a11y_element(AccessibilityChildBehavior::Combine)
50 .a11y_label(LABELS[i])
51 .a11y_value(&format!("{:.0} percent", value * 100.0))
52}
53
54fn body() -> View {
55 vstack_aligned_spacing(
56 &[
57 text("System").text_style(TextStyle::LargeTitle).bold(),
58 grid(&[grid_row(&[tile(0), tile(1), tile(2)])]),
59 divider(),
60 // A gauge over the busiest reading, which is a different control
61 // from the rings and reads the same state.
62 vstack_aligned(
63 &[
64 text("Busiest").font_size(12.0).fg_system(SystemColor::Gray),
65 gauge(reading(1), 0.0, 1.0, text("Memory"))
66 .gauge_style(views::GaugeStyle::AccessoryLinearCapacityGaugeStyle)
67 .tint_system(SystemColor::Orange),
68 ],
69 HorizontalAlignment::Leading,
70 ),
71 spacer(),
72 button("Refresh", refresh)
73 .button_style(views::ButtonStyle::BorderedProminent)
74 .keyboard_shortcut(KeyboardShortcut::DefaultAction),
75 ],
76 HorizontalAlignment::Leading,
77 Some(16.0),
78 )
79 .padding(20.0)
80 // Animate whatever changed, rather than snapping to the new reading.
81 .animation(LOAD[0].load(Ordering::Relaxed) as i64)
82}4fn main() {
5 let show_detail = true;
6 let items = vec![String::from("alpha"), String::from("beta")];
7
8 let sugared = swiftui! {
9 VStack(spacing: 8.0) {
10 Text("Title").text_style(.large_title)
11 if show_detail {
12 Text("the details")
13 }
14 ForEach(items) { item in
15 Text(item)
16 }
17 }
18 };
19
20 let by_hand = vstack_spacing(
21 &[
22 text("Title").text_style(views::TextStyle::LargeTitle),
23 conditional(show_detail, text("the details"), empty()),
24 for_each_items(&items, |item| text(item)),
25 ],
26 8.0,
27 );
28
29 let a = views::dump_value_to_depth(&sugared.into_handle(), 6);
30 let b = views::dump_value_to_depth(&by_hand.into_handle(), 6);
31 eprintln!("macro == hand-written? {}", a == b);
32 if a != b {
33 for (x, y) in a.lines().zip(b.lines()) {
34 if x != y {
35 eprintln!(" macro: {}\n hand : {}", x.trim(), y.trim());
36 break;
37 }
38 }
39 }
40}129fn body() -> View {
130 let colour = COLORS[COLOR.load(Ordering::Relaxed) % COLORS.len()];
131
132 vstack![
133 // Text("Why not try…").font(.largeTitle.bold())
134 text("Why not try…").text_style(TextStyle::LargeTitle).bold(),
135 vstack![
136 // Circle().fill(colors.randomElement() ?? .blue).padding().overlay(…)
137 circle_shape().fill_system(colour).padding(16.0).overlay(
138 // Image(systemName: "figure.\(selected.lowercased())")
139 // .font(.system(size: 144)).foregroundColor(.white)
140 image!("figure.{}", selected().to_lowercase())
141 .font_size(144.0)
142 .fg(Color::WHITE),
143 ),
144 // Text("\(selected)!").font(.title)
145 text!("{}!", selected()).text_style(TextStyle::Title),
146 ]
147 .transition(Transition::Slide)
148 .id(ID.load(Ordering::Relaxed)),
149 spacer(),
150 // Button("Try again") { … }.buttonStyle(.borderedProminent)
151 button("Try again", try_again).button_style(ButtonStyle::BorderedProminent),
152 ]
153}Sourcepub fn font_named(self, name: &str, size: f64) -> Self
pub fn font_named(self, name: &str, size: f64) -> Self
.font(.custom(_:size:))
Sourcepub fn font_ref(self, font: &Font) -> Self
pub fn font_ref(self, font: &Font) -> Self
.font(_:) with a prebuilt views::Font, which is far cheaper than
rebuilding the font for every view.
Sourcepub fn bold(self) -> Self
pub fn bold(self) -> Self
.bold()
On a Text this is Text.bold(), which returns Text — the same type
Swift produces, and the reason the documentation corpus compares equal.
On anything else it is the View extension, which writes the environment
so the text below inherits it.
Examples found in repository?
60fn detail(i: usize) -> View {
61 let m = &MESSAGES[i];
62 vstack_aligned_spacing(
63 &[
64 text(m.subject).text_style(TextStyle::Title).bold(),
65 text!("From {}", m.from).fg_system(SystemColor::Gray),
66 divider(),
67 text("Body text would go here.").fg_system(SystemColor::Gray),
68 spacer(),
69 ],
70 HorizontalAlignment::Leading,
71 Some(12.0),
72 )
73 .padding(20.0)
74 .navigation_title(m.subject)
75}
76
77fn row(i: usize) -> View {
78 let m = &MESSAGES[i];
79 hstack_spacing(
80 &[
81 // An unread dot, or the space where one would be.
82 view_if!(
83 m.unread,
84 circle_shape().fill_system(SystemColor::Blue).frame(8.0, 8.0),
85 empty().frame(8.0, 8.0)
86 ),
87 vstack_aligned(
88 &[
89 text(m.from).bold(),
90 text(m.subject).font_size(12.0).fg_system(SystemColor::Gray),
91 ],
92 HorizontalAlignment::Leading,
93 ),
94 spacer(),
95 ],
96 8.0,
97 )
98 .padding_edges(EdgeSet::Vertical, Some(4.0))
99 .a11y_label(&format!("{}, {}", m.from, m.subject))
100 .a11y_hint(if m.unread { "Unread" } else { "Read" })
101}More examples
89fn about_panel() -> View {
90 let s = settings();
91 vstack_spacing(
92 &[
93 system_image("gearshape.fill")
94 .symbol_rendering_mode(Some(views::SymbolRenderingMode::Hierarchical))
95 .view()
96 .font_size(48.0)
97 .fg_system(SystemColor::Blue),
98 text("Settings").text_style(TextStyle::Title).bold(),
99 text!("Signed in as {}", s.name.get()).fg_system(SystemColor::Gray),
100 spacer(),
101 button("Done", hide_about).button_style(views::ButtonStyle::BorderedProminent),
102 ],
103 16.0,
104 )
105 .padding(24.0)
106 .presentation_detents(&[views::PresentationDetent::Medium])
107 .presentation_drag_indicator(Visibility::Visible)
108}28fn tile(i: usize) -> View {
29 let value = reading(i);
30 vstack_spacing(
31 &[
32 zstack![
33 circle_shape().stroke_system(SystemColor::Gray, 6.0).opacity(0.25),
34 // The filled part: the same circle trimmed to the fraction, and
35 // turned so the arc starts at the top rather than at three
36 // o'clock.
37 circle_shape()
38 .trim(0.0, value)
39 .stroke_system(TINTS[i], 6.0)
40 .rotate(-90.0),
41 text!("{:.0}", value * 100.0).text_style(TextStyle::Title2).bold(),
42 ]
43 .frame(72.0, 72.0),
44 text(LABELS[i]).font_size(12.0).fg_system(SystemColor::Gray),
45 ],
46 8.0,
47 )
48 .padding(12.0)
49 .a11y_element(AccessibilityChildBehavior::Combine)
50 .a11y_label(LABELS[i])
51 .a11y_value(&format!("{:.0} percent", value * 100.0))
52}
53
54fn body() -> View {
55 vstack_aligned_spacing(
56 &[
57 text("System").text_style(TextStyle::LargeTitle).bold(),
58 grid(&[grid_row(&[tile(0), tile(1), tile(2)])]),
59 divider(),
60 // A gauge over the busiest reading, which is a different control
61 // from the rings and reads the same state.
62 vstack_aligned(
63 &[
64 text("Busiest").font_size(12.0).fg_system(SystemColor::Gray),
65 gauge(reading(1), 0.0, 1.0, text("Memory"))
66 .gauge_style(views::GaugeStyle::AccessoryLinearCapacityGaugeStyle)
67 .tint_system(SystemColor::Orange),
68 ],
69 HorizontalAlignment::Leading,
70 ),
71 spacer(),
72 button("Refresh", refresh)
73 .button_style(views::ButtonStyle::BorderedProminent)
74 .keyboard_shortcut(KeyboardShortcut::DefaultAction),
75 ],
76 HorizontalAlignment::Leading,
77 Some(16.0),
78 )
79 .padding(20.0)
80 // Animate whatever changed, rather than snapping to the new reading.
81 .animation(LOAD[0].load(Ordering::Relaxed) as i64)
82}129fn body() -> View {
130 let colour = COLORS[COLOR.load(Ordering::Relaxed) % COLORS.len()];
131
132 vstack![
133 // Text("Why not try…").font(.largeTitle.bold())
134 text("Why not try…").text_style(TextStyle::LargeTitle).bold(),
135 vstack![
136 // Circle().fill(colors.randomElement() ?? .blue).padding().overlay(…)
137 circle_shape().fill_system(colour).padding(16.0).overlay(
138 // Image(systemName: "figure.\(selected.lowercased())")
139 // .font(.system(size: 144)).foregroundColor(.white)
140 image!("figure.{}", selected().to_lowercase())
141 .font_size(144.0)
142 .fg(Color::WHITE),
143 ),
144 // Text("\(selected)!").font(.title)
145 text!("{}!", selected()).text_style(TextStyle::Title),
146 ]
147 .transition(Transition::Slide)
148 .id(ID.load(Ordering::Relaxed)),
149 spacer(),
150 // Button("Try again") { … }.buttonStyle(.borderedProminent)
151 button("Try again", try_again).button_style(ButtonStyle::BorderedProminent),
152 ]
153}83fn body() -> View {
84 let todos = items().lock().unwrap().clone();
85 let remaining = todos.iter().filter(|i| !i.done).count();
86
87 vstack_aligned_spacing(
88 &[
89 hstack![
90 text("Todo").text_style(TextStyle::LargeTitle).bold(),
91 spacer(),
92 text!("{remaining} left").fg_system(SystemColor::Gray),
93 ],
94 hstack_spacing(
95 &[
96 textfield_bound("What needs doing?", draft())
97 .text_field_style(views::TextFieldStyle::RoundedBorderTextFieldStyle)
98 .on_submit(SubmitTrigger::Text, add)
99 .submit_label(SubmitLabel::Done),
100 button("Add", add).button_style(views::ButtonStyle::BorderedProminent),
101 ],
102 8.0,
103 ),
104 // The empty state is a branch, so it arrives and leaves rather than
105 // appearing from nothing.
106 view_if!(
107 todos.is_empty(),
108 vstack_spacing(
109 &[
110 system_image("checkmark.seal").view().font_size(40.0)
111 .fg_system(SystemColor::Green),
112 text("Nothing left to do").fg_system(SystemColor::Gray),
113 ],
114 8.0,
115 )
116 .frame_optional(None, Some(160.0), Alignment::Center)
117 .transition(Transition::ScaleWithOpacity { scale: 0.8, anchor: (0.5, 0.5) }),
118 list(for_each_items(
119 &todos.iter().cloned().enumerate().collect::<Vec<_>>(),
120 |(i, it)| row(*i, it),
121 ))
122 .list_style(views::ListStyle::PlainListStyle)
123 ),
124 ],
125 HorizontalAlignment::Leading,
126 Some(14.0),
127 )
128 .padding(20.0)
129}487fn node_view(node: &Node) -> Result<View, String> {
488 let spacing = node.f64_attr("spacing").unwrap_or(8.0);
489 let base = match node.name.as_str() {
490 "vstack" => {
491 let kids = children(node)?;
492 match node.attr("align") {
493 Some(a) => vstack_aligned_spacing(&kids, h_align(a, node.line)?, Some(spacing)),
494 None => vstack_spacing(&kids, spacing),
495 }
496 }
497 "hstack" => {
498 let kids = children(node)?;
499 match node.attr("align") {
500 Some(a) => hstack_aligned_spacing(&kids, v_align(a, node.line)?, Some(spacing)),
501 None => hstack_spacing(&kids, spacing),
502 }
503 }
504 "zstack" => zstack_aligned(&children(node)?, align(node.attr("align").unwrap_or("center"), node.line)?),
505 "text" => {
506 let s = node.value.as_deref().unwrap_or("");
507 let mut v = text(s);
508 if let Some(style) = node.attr("style") {
509 v = v.text_style(text_style(style, node.line)?);
510 }
511 if let Some(size) = node.f64_attr("size") {
512 v = v.font_size(size);
513 }
514 if node.flag("bold") {
515 v = v.bold();
516 }
517 if node.flag("italic") {
518 v = v.italic();
519 }
520 if let Some(c) = node.attr("color") {
521 v = match tint(c, node.line)? {
522 Tint::System(sc) => v.fg_system(sc),
523 Tint::Literal(lc) => v.fg(lc),
524 };
525 }
526 v
527 }
528 "spacer" => spacer(),
529 "divider" => divider(),
530 // The action is a no-op on purpose: a spec read from a file has nowhere
531 // to put behaviour, and pretending otherwise would be worse than a
532 // button that visibly does nothing. `hot_reload.rs` is where a spec
533 // gains behaviour, by being reloaded.
534 "button" => button(node.value.as_deref().unwrap_or("Button"), || {}),
535 "color" => color(parse_color(node.value.as_deref().unwrap_or("#808080"), node.line)?),
536 "image" => system_image(node.value.as_deref().unwrap_or("star")).into_view(),
537 "rect" => match node.attr("color") {
538 Some(c) => match tint(c, node.line)? {
539 Tint::System(sc) => rectangle_shape().fill_system(sc),
540 Tint::Literal(lc) => rectangle_shape().fill(lc),
541 },
542 None => rectangle_shape().into_view(),
543 },
544 "circle" => match node.attr("color") {
545 Some(c) => match tint(c, node.line)? {
546 Tint::System(sc) => circle_shape().fill_system(sc),
547 Tint::Literal(lc) => circle_shape().fill(lc),
548 },
549 None => circle_shape().into_view(),
550 },
551 "capsule" => match node.attr("color") {
552 Some(c) => match tint(c, node.line)? {
553 Tint::System(sc) => capsule_shape().fill_system(sc),
554 Tint::Literal(lc) => capsule_shape().fill(lc),
555 },
556 None => capsule_shape().into_view(),
557 },
558 "progress" => progress(
559 node.value.as_deref().and_then(|v| v.parse().ok()).unwrap_or(0.5),
560 node.f64_attr("total").unwrap_or(1.0),
561 ),
562 "gauge" => gauge(
563 node.value.as_deref().and_then(|v| v.parse().ok()).unwrap_or(0.5),
564 node.f64_attr("min").unwrap_or(0.0),
565 node.f64_attr("max").unwrap_or(1.0),
566 text(node.attr("label").unwrap_or("")),
567 ),
568 "group_box" => group_box(stack_children(node)?),
569 "list" => list(stack_children(node)?),
570 "scroll" => stack_children(node)?.scroll(),
571 "form" => form(stack_children(node)?),
572 // Every bound control needs an explicit `@name`.
573 //
574 // Inventing one — from the line, or from position in the tree — looks
575 // friendlier and is a trap: adding a line above a `toggle` would
576 // change its derived name, and the control would silently reset on the
577 // next reload. A name the file states is a name that survives the file
578 // being edited, which is the entire point of the slots.
579 "toggle" => toggle_bound(
580 node.value.as_deref().unwrap_or("Toggle"),
581 &flag_slot(&require_slot(node)?, node.flag("on")),
582 ),
583 "slider" => {
584 let lo = node.f64_attr("min").unwrap_or(0.0);
585 let hi = node.f64_attr("max").unwrap_or(1.0);
586 slider_bound(
587 &number_slot(&require_slot(node)?, node.f64_attr("value").unwrap_or(lo)),
588 lo,
589 hi,
590 )
591 }
592 "stepper" => stepper_bound(
593 node.value.as_deref().unwrap_or("Stepper"),
594 &number_slot(&require_slot(node)?, node.f64_attr("value").unwrap_or(0.0)),
595 node.f64_attr("min").unwrap_or(0.0),
596 node.f64_attr("max").unwrap_or(100.0),
597 node.f64_attr("step").unwrap_or(1.0),
598 ),
599 "field" => textfield_bound(
600 node.value.as_deref().unwrap_or(""),
601 &string_slot(&require_slot(node)?, node.attr("text").unwrap_or("")),
602 ),
603 "label" => label(
604 node.value.as_deref().unwrap_or(""),
605 node.attr("icon").unwrap_or("star"),
606 ),
607 other => {
608 return Err(format!(
609 "line {}: no view called `{other}`; try one of {}",
610 node.line,
611 NAMES.join(", ")
612 ))
613 }
614 };
615 decorate(base, node)
616}Sourcepub fn italic(self) -> Self
pub fn italic(self) -> Self
.italic() — Text.italic() on a Text, the View extension otherwise.
Examples found in repository?
487fn node_view(node: &Node) -> Result<View, String> {
488 let spacing = node.f64_attr("spacing").unwrap_or(8.0);
489 let base = match node.name.as_str() {
490 "vstack" => {
491 let kids = children(node)?;
492 match node.attr("align") {
493 Some(a) => vstack_aligned_spacing(&kids, h_align(a, node.line)?, Some(spacing)),
494 None => vstack_spacing(&kids, spacing),
495 }
496 }
497 "hstack" => {
498 let kids = children(node)?;
499 match node.attr("align") {
500 Some(a) => hstack_aligned_spacing(&kids, v_align(a, node.line)?, Some(spacing)),
501 None => hstack_spacing(&kids, spacing),
502 }
503 }
504 "zstack" => zstack_aligned(&children(node)?, align(node.attr("align").unwrap_or("center"), node.line)?),
505 "text" => {
506 let s = node.value.as_deref().unwrap_or("");
507 let mut v = text(s);
508 if let Some(style) = node.attr("style") {
509 v = v.text_style(text_style(style, node.line)?);
510 }
511 if let Some(size) = node.f64_attr("size") {
512 v = v.font_size(size);
513 }
514 if node.flag("bold") {
515 v = v.bold();
516 }
517 if node.flag("italic") {
518 v = v.italic();
519 }
520 if let Some(c) = node.attr("color") {
521 v = match tint(c, node.line)? {
522 Tint::System(sc) => v.fg_system(sc),
523 Tint::Literal(lc) => v.fg(lc),
524 };
525 }
526 v
527 }
528 "spacer" => spacer(),
529 "divider" => divider(),
530 // The action is a no-op on purpose: a spec read from a file has nowhere
531 // to put behaviour, and pretending otherwise would be worse than a
532 // button that visibly does nothing. `hot_reload.rs` is where a spec
533 // gains behaviour, by being reloaded.
534 "button" => button(node.value.as_deref().unwrap_or("Button"), || {}),
535 "color" => color(parse_color(node.value.as_deref().unwrap_or("#808080"), node.line)?),
536 "image" => system_image(node.value.as_deref().unwrap_or("star")).into_view(),
537 "rect" => match node.attr("color") {
538 Some(c) => match tint(c, node.line)? {
539 Tint::System(sc) => rectangle_shape().fill_system(sc),
540 Tint::Literal(lc) => rectangle_shape().fill(lc),
541 },
542 None => rectangle_shape().into_view(),
543 },
544 "circle" => match node.attr("color") {
545 Some(c) => match tint(c, node.line)? {
546 Tint::System(sc) => circle_shape().fill_system(sc),
547 Tint::Literal(lc) => circle_shape().fill(lc),
548 },
549 None => circle_shape().into_view(),
550 },
551 "capsule" => match node.attr("color") {
552 Some(c) => match tint(c, node.line)? {
553 Tint::System(sc) => capsule_shape().fill_system(sc),
554 Tint::Literal(lc) => capsule_shape().fill(lc),
555 },
556 None => capsule_shape().into_view(),
557 },
558 "progress" => progress(
559 node.value.as_deref().and_then(|v| v.parse().ok()).unwrap_or(0.5),
560 node.f64_attr("total").unwrap_or(1.0),
561 ),
562 "gauge" => gauge(
563 node.value.as_deref().and_then(|v| v.parse().ok()).unwrap_or(0.5),
564 node.f64_attr("min").unwrap_or(0.0),
565 node.f64_attr("max").unwrap_or(1.0),
566 text(node.attr("label").unwrap_or("")),
567 ),
568 "group_box" => group_box(stack_children(node)?),
569 "list" => list(stack_children(node)?),
570 "scroll" => stack_children(node)?.scroll(),
571 "form" => form(stack_children(node)?),
572 // Every bound control needs an explicit `@name`.
573 //
574 // Inventing one — from the line, or from position in the tree — looks
575 // friendlier and is a trap: adding a line above a `toggle` would
576 // change its derived name, and the control would silently reset on the
577 // next reload. A name the file states is a name that survives the file
578 // being edited, which is the entire point of the slots.
579 "toggle" => toggle_bound(
580 node.value.as_deref().unwrap_or("Toggle"),
581 &flag_slot(&require_slot(node)?, node.flag("on")),
582 ),
583 "slider" => {
584 let lo = node.f64_attr("min").unwrap_or(0.0);
585 let hi = node.f64_attr("max").unwrap_or(1.0);
586 slider_bound(
587 &number_slot(&require_slot(node)?, node.f64_attr("value").unwrap_or(lo)),
588 lo,
589 hi,
590 )
591 }
592 "stepper" => stepper_bound(
593 node.value.as_deref().unwrap_or("Stepper"),
594 &number_slot(&require_slot(node)?, node.f64_attr("value").unwrap_or(0.0)),
595 node.f64_attr("min").unwrap_or(0.0),
596 node.f64_attr("max").unwrap_or(100.0),
597 node.f64_attr("step").unwrap_or(1.0),
598 ),
599 "field" => textfield_bound(
600 node.value.as_deref().unwrap_or(""),
601 &string_slot(&require_slot(node)?, node.attr("text").unwrap_or("")),
602 ),
603 "label" => label(
604 node.value.as_deref().unwrap_or(""),
605 node.attr("icon").unwrap_or("star"),
606 ),
607 other => {
608 return Err(format!(
609 "line {}: no view called `{other}`; try one of {}",
610 node.line,
611 NAMES.join(", ")
612 ))
613 }
614 };
615 decorate(base, node)
616}Sourcepub fn monospaced(self) -> Self
pub fn monospaced(self) -> Self
.monospaced() — Text.monospaced() on a Text.
Sourcepub fn weight(self, weight: Weight) -> Self
pub fn weight(self, weight: Weight) -> Self
.fontWeight(_:) — Text.fontWeight(_:) on a Text, which returns
Text, and the View extension otherwise.
Sourcepub fn fg(self, c: Color) -> Self
pub fn fg(self, c: Color) -> Self
.foregroundStyle(_:)
On a Text this is Text.foregroundColor(_:), which returns Text.
Examples found in repository?
129fn body() -> View {
130 let colour = COLORS[COLOR.load(Ordering::Relaxed) % COLORS.len()];
131
132 vstack![
133 // Text("Why not try…").font(.largeTitle.bold())
134 text("Why not try…").text_style(TextStyle::LargeTitle).bold(),
135 vstack![
136 // Circle().fill(colors.randomElement() ?? .blue).padding().overlay(…)
137 circle_shape().fill_system(colour).padding(16.0).overlay(
138 // Image(systemName: "figure.\(selected.lowercased())")
139 // .font(.system(size: 144)).foregroundColor(.white)
140 image!("figure.{}", selected().to_lowercase())
141 .font_size(144.0)
142 .fg(Color::WHITE),
143 ),
144 // Text("\(selected)!").font(.title)
145 text!("{}!", selected()).text_style(TextStyle::Title),
146 ]
147 .transition(Transition::Slide)
148 .id(ID.load(Ordering::Relaxed)),
149 spacer(),
150 // Button("Try again") { … }.buttonStyle(.borderedProminent)
151 button("Try again", try_again).button_style(ButtonStyle::BorderedProminent),
152 ]
153}More examples
487fn node_view(node: &Node) -> Result<View, String> {
488 let spacing = node.f64_attr("spacing").unwrap_or(8.0);
489 let base = match node.name.as_str() {
490 "vstack" => {
491 let kids = children(node)?;
492 match node.attr("align") {
493 Some(a) => vstack_aligned_spacing(&kids, h_align(a, node.line)?, Some(spacing)),
494 None => vstack_spacing(&kids, spacing),
495 }
496 }
497 "hstack" => {
498 let kids = children(node)?;
499 match node.attr("align") {
500 Some(a) => hstack_aligned_spacing(&kids, v_align(a, node.line)?, Some(spacing)),
501 None => hstack_spacing(&kids, spacing),
502 }
503 }
504 "zstack" => zstack_aligned(&children(node)?, align(node.attr("align").unwrap_or("center"), node.line)?),
505 "text" => {
506 let s = node.value.as_deref().unwrap_or("");
507 let mut v = text(s);
508 if let Some(style) = node.attr("style") {
509 v = v.text_style(text_style(style, node.line)?);
510 }
511 if let Some(size) = node.f64_attr("size") {
512 v = v.font_size(size);
513 }
514 if node.flag("bold") {
515 v = v.bold();
516 }
517 if node.flag("italic") {
518 v = v.italic();
519 }
520 if let Some(c) = node.attr("color") {
521 v = match tint(c, node.line)? {
522 Tint::System(sc) => v.fg_system(sc),
523 Tint::Literal(lc) => v.fg(lc),
524 };
525 }
526 v
527 }
528 "spacer" => spacer(),
529 "divider" => divider(),
530 // The action is a no-op on purpose: a spec read from a file has nowhere
531 // to put behaviour, and pretending otherwise would be worse than a
532 // button that visibly does nothing. `hot_reload.rs` is where a spec
533 // gains behaviour, by being reloaded.
534 "button" => button(node.value.as_deref().unwrap_or("Button"), || {}),
535 "color" => color(parse_color(node.value.as_deref().unwrap_or("#808080"), node.line)?),
536 "image" => system_image(node.value.as_deref().unwrap_or("star")).into_view(),
537 "rect" => match node.attr("color") {
538 Some(c) => match tint(c, node.line)? {
539 Tint::System(sc) => rectangle_shape().fill_system(sc),
540 Tint::Literal(lc) => rectangle_shape().fill(lc),
541 },
542 None => rectangle_shape().into_view(),
543 },
544 "circle" => match node.attr("color") {
545 Some(c) => match tint(c, node.line)? {
546 Tint::System(sc) => circle_shape().fill_system(sc),
547 Tint::Literal(lc) => circle_shape().fill(lc),
548 },
549 None => circle_shape().into_view(),
550 },
551 "capsule" => match node.attr("color") {
552 Some(c) => match tint(c, node.line)? {
553 Tint::System(sc) => capsule_shape().fill_system(sc),
554 Tint::Literal(lc) => capsule_shape().fill(lc),
555 },
556 None => capsule_shape().into_view(),
557 },
558 "progress" => progress(
559 node.value.as_deref().and_then(|v| v.parse().ok()).unwrap_or(0.5),
560 node.f64_attr("total").unwrap_or(1.0),
561 ),
562 "gauge" => gauge(
563 node.value.as_deref().and_then(|v| v.parse().ok()).unwrap_or(0.5),
564 node.f64_attr("min").unwrap_or(0.0),
565 node.f64_attr("max").unwrap_or(1.0),
566 text(node.attr("label").unwrap_or("")),
567 ),
568 "group_box" => group_box(stack_children(node)?),
569 "list" => list(stack_children(node)?),
570 "scroll" => stack_children(node)?.scroll(),
571 "form" => form(stack_children(node)?),
572 // Every bound control needs an explicit `@name`.
573 //
574 // Inventing one — from the line, or from position in the tree — looks
575 // friendlier and is a trap: adding a line above a `toggle` would
576 // change its derived name, and the control would silently reset on the
577 // next reload. A name the file states is a name that survives the file
578 // being edited, which is the entire point of the slots.
579 "toggle" => toggle_bound(
580 node.value.as_deref().unwrap_or("Toggle"),
581 &flag_slot(&require_slot(node)?, node.flag("on")),
582 ),
583 "slider" => {
584 let lo = node.f64_attr("min").unwrap_or(0.0);
585 let hi = node.f64_attr("max").unwrap_or(1.0);
586 slider_bound(
587 &number_slot(&require_slot(node)?, node.f64_attr("value").unwrap_or(lo)),
588 lo,
589 hi,
590 )
591 }
592 "stepper" => stepper_bound(
593 node.value.as_deref().unwrap_or("Stepper"),
594 &number_slot(&require_slot(node)?, node.f64_attr("value").unwrap_or(0.0)),
595 node.f64_attr("min").unwrap_or(0.0),
596 node.f64_attr("max").unwrap_or(100.0),
597 node.f64_attr("step").unwrap_or(1.0),
598 ),
599 "field" => textfield_bound(
600 node.value.as_deref().unwrap_or(""),
601 &string_slot(&require_slot(node)?, node.attr("text").unwrap_or("")),
602 ),
603 "label" => label(
604 node.value.as_deref().unwrap_or(""),
605 node.attr("icon").unwrap_or("star"),
606 ),
607 other => {
608 return Err(format!(
609 "line {}: no view called `{other}`; try one of {}",
610 node.line,
611 NAMES.join(", ")
612 ))
613 }
614 };
615 decorate(base, node)
616}Sourcepub fn baseline_offset(self, amount: f64) -> Self
pub fn baseline_offset(self, amount: f64) -> Self
Text.baselineOffset(_:)
Sourcepub fn fg_system(self, c: SystemColor) -> Self
pub fn fg_system(self, c: SystemColor) -> Self
.foregroundColor(_:) with one of SwiftUI’s named colours.
Not the same modifier as View::fg, and not a colour that components
can spell: see views::system_color.
Examples found in repository?
60fn detail(i: usize) -> View {
61 let m = &MESSAGES[i];
62 vstack_aligned_spacing(
63 &[
64 text(m.subject).text_style(TextStyle::Title).bold(),
65 text!("From {}", m.from).fg_system(SystemColor::Gray),
66 divider(),
67 text("Body text would go here.").fg_system(SystemColor::Gray),
68 spacer(),
69 ],
70 HorizontalAlignment::Leading,
71 Some(12.0),
72 )
73 .padding(20.0)
74 .navigation_title(m.subject)
75}
76
77fn row(i: usize) -> View {
78 let m = &MESSAGES[i];
79 hstack_spacing(
80 &[
81 // An unread dot, or the space where one would be.
82 view_if!(
83 m.unread,
84 circle_shape().fill_system(SystemColor::Blue).frame(8.0, 8.0),
85 empty().frame(8.0, 8.0)
86 ),
87 vstack_aligned(
88 &[
89 text(m.from).bold(),
90 text(m.subject).font_size(12.0).fg_system(SystemColor::Gray),
91 ],
92 HorizontalAlignment::Leading,
93 ),
94 spacer(),
95 ],
96 8.0,
97 )
98 .padding_edges(EdgeSet::Vertical, Some(4.0))
99 .a11y_label(&format!("{}, {}", m.from, m.subject))
100 .a11y_hint(if m.unread { "Unread" } else { "Read" })
101}More examples
64pub fn body() -> View {
65 let text_src = current().lock().expect("spec").clone();
66 match spec::parse(&text_src).and_then(|nodes| spec::build(&nodes)) {
67 Ok(v) => v,
68 Err(e) => vstack_aligned_spacing(
69 &[
70 text("Could not build that screen")
71 .text_style(TextStyle::Headline)
72 .fg_system(SystemColor::Red),
73 text(&e).font_size(12.0).fg_system(SystemColor::Secondary),
74 ],
75 HorizontalAlignment::Leading,
76 Some(8.0),
77 )
78 .padding(20.0),
79 }
80}96fn body() -> View {
97 let (src, error, generation, micros) = {
98 let g = state_cell().lock().expect("state");
99 (g.last_good.clone(), g.error.clone(), g.generation, g.micros)
100 };
101
102 // The last version that parsed. It cannot fail — it parsed before — but a
103 // spec that builds views from slots could in principle, so the fallback is
104 // still handled rather than unwrapped.
105 let screen = spec::parse(&src)
106 .and_then(|nodes| spec::build(&nodes))
107 .unwrap_or_else(|e| text(&e).fg_system(SystemColor::Red).padding(20.0));
108
109 vstack_spacing(&[screen, status(error.as_deref(), generation, micros)], 0.0)
110}
111
112/// A strip along the bottom: which generation is on screen, how long the last
113/// reload took, what the slots hold, and the error if there is one.
114///
115/// In the window rather than the terminal because that is where you are
116/// looking. Watching a reloader work from a log means watching two things.
117fn status(error: Option<&str>, generation: u64, micros: u64) -> View {
118 let slots = spec::slot_summary();
119 let slot_line = if slots.is_empty() {
120 String::new()
121 } else {
122 slots
123 .iter()
124 .map(|(k, v)| format!("{k}={v}"))
125 .collect::<Vec<_>>()
126 .join(" ")
127 };
128
129 // The error row is *always* present, empty when there is nothing wrong.
130 // An error that appears and disappears would otherwise reflow the screen
131 // above it on every save — which looks exactly like the reloader having
132 // replaced the view, and makes "did the screen survive this?" impossible
133 // to answer by looking.
134 let rows = vec![
135 divider(),
136 hstack_spacing(
137 &[
138 circle_shape()
139 .fill_system(if error.is_some() {
140 SystemColor::Orange
141 } else {
142 SystemColor::Clear
143 })
144 .frame(8.0, 8.0),
145 text(error.unwrap_or(""))
146 .font_size(11.0)
147 .fg_system(SystemColor::Orange),
148 spacer(),
149 ],
150 6.0,
151 )
152 .padding(6.0)
153 .frame(348.0, 24.0),
154 hstack_spacing(
155 &[
156 circle_shape()
157 .fill_system(if error.is_some() {
158 SystemColor::Orange
159 } else {
160 SystemColor::Green
161 })
162 .frame(8.0, 8.0),
163 text(&format!("gen {generation}"))
164 .font_size(11.0)
165 .fg_system(SystemColor::Secondary),
166 // Microseconds below a millisecond: a reload of a short spec
167 // really is that fast, and "0.0 ms" reads as "not measured".
168 text(&if micros < 1000 {
169 format!("{micros} \u{b5}s")
170 } else {
171 format!("{:.1} ms", micros as f64 / 1000.0)
172 })
173 .font_size(11.0)
174 .fg_system(SystemColor::Secondary),
175 spacer(),
176 text(&slot_line).font_size(11.0).fg_system(SystemColor::Secondary),
177 ],
178 8.0,
179 )
180 .padding(6.0)
181 .frame(348.0, 24.0),
182 ];
183 vstack_spacing(&rows, 0.0)
184}28fn tile(i: usize) -> View {
29 let value = reading(i);
30 vstack_spacing(
31 &[
32 zstack![
33 circle_shape().stroke_system(SystemColor::Gray, 6.0).opacity(0.25),
34 // The filled part: the same circle trimmed to the fraction, and
35 // turned so the arc starts at the top rather than at three
36 // o'clock.
37 circle_shape()
38 .trim(0.0, value)
39 .stroke_system(TINTS[i], 6.0)
40 .rotate(-90.0),
41 text!("{:.0}", value * 100.0).text_style(TextStyle::Title2).bold(),
42 ]
43 .frame(72.0, 72.0),
44 text(LABELS[i]).font_size(12.0).fg_system(SystemColor::Gray),
45 ],
46 8.0,
47 )
48 .padding(12.0)
49 .a11y_element(AccessibilityChildBehavior::Combine)
50 .a11y_label(LABELS[i])
51 .a11y_value(&format!("{:.0} percent", value * 100.0))
52}
53
54fn body() -> View {
55 vstack_aligned_spacing(
56 &[
57 text("System").text_style(TextStyle::LargeTitle).bold(),
58 grid(&[grid_row(&[tile(0), tile(1), tile(2)])]),
59 divider(),
60 // A gauge over the busiest reading, which is a different control
61 // from the rings and reads the same state.
62 vstack_aligned(
63 &[
64 text("Busiest").font_size(12.0).fg_system(SystemColor::Gray),
65 gauge(reading(1), 0.0, 1.0, text("Memory"))
66 .gauge_style(views::GaugeStyle::AccessoryLinearCapacityGaugeStyle)
67 .tint_system(SystemColor::Orange),
68 ],
69 HorizontalAlignment::Leading,
70 ),
71 spacer(),
72 button("Refresh", refresh)
73 .button_style(views::ButtonStyle::BorderedProminent)
74 .keyboard_shortcut(KeyboardShortcut::DefaultAction),
75 ],
76 HorizontalAlignment::Leading,
77 Some(16.0),
78 )
79 .padding(20.0)
80 // Animate whatever changed, rather than snapping to the new reading.
81 .animation(LOAD[0].load(Ordering::Relaxed) as i64)
82}59fn row(i: usize, it: &Item) -> View {
60 hstack_spacing(
61 &[
62 // The checkmark is the button, so the whole symbol is the target.
63 button_labelled(
64 system_image(if it.done { "checkmark.circle.fill" } else { "circle" })
65 .symbol_rendering_mode(Some(views::SymbolRenderingMode::Hierarchical))
66 .view()
67 .fg_system(if it.done { SystemColor::Green } else { SystemColor::Gray }),
68 move || toggle(i),
69 )
70 .button_style(views::ButtonStyle::Bordered),
71 text(&it.title)
72 .strikethrough_styled(it.done, LinePattern::Solid, None)
73 .fg_system(if it.done { SystemColor::Gray } else { SystemColor::Primary }),
74 spacer(),
75 ],
76 10.0,
77 )
78 .padding_edges(EdgeSet::Vertical, Some(6.0))
79 .a11y_label(&it.title)
80 .a11y_value(if it.done { "Done" } else { "Not done" })
81}
82
83fn body() -> View {
84 let todos = items().lock().unwrap().clone();
85 let remaining = todos.iter().filter(|i| !i.done).count();
86
87 vstack_aligned_spacing(
88 &[
89 hstack![
90 text("Todo").text_style(TextStyle::LargeTitle).bold(),
91 spacer(),
92 text!("{remaining} left").fg_system(SystemColor::Gray),
93 ],
94 hstack_spacing(
95 &[
96 textfield_bound("What needs doing?", draft())
97 .text_field_style(views::TextFieldStyle::RoundedBorderTextFieldStyle)
98 .on_submit(SubmitTrigger::Text, add)
99 .submit_label(SubmitLabel::Done),
100 button("Add", add).button_style(views::ButtonStyle::BorderedProminent),
101 ],
102 8.0,
103 ),
104 // The empty state is a branch, so it arrives and leaves rather than
105 // appearing from nothing.
106 view_if!(
107 todos.is_empty(),
108 vstack_spacing(
109 &[
110 system_image("checkmark.seal").view().font_size(40.0)
111 .fg_system(SystemColor::Green),
112 text("Nothing left to do").fg_system(SystemColor::Gray),
113 ],
114 8.0,
115 )
116 .frame_optional(None, Some(160.0), Alignment::Center)
117 .transition(Transition::ScaleWithOpacity { scale: 0.8, anchor: (0.5, 0.5) }),
118 list(for_each_items(
119 &todos.iter().cloned().enumerate().collect::<Vec<_>>(),
120 |(i, it)| row(*i, it),
121 ))
122 .list_style(views::ListStyle::PlainListStyle)
123 ),
124 ],
125 HorizontalAlignment::Leading,
126 Some(14.0),
127 )
128 .padding(20.0)
129}43fn body() -> View {
44 let s = settings();
45
46 form![
47 section![header: text("Account");
48 hstack![
49 text("Name"),
50 spacer(),
51 textfield_bound("Your name", &s.name).text_field_style(
52 views::TextFieldStyle::RoundedBorderTextFieldStyle,
53 ),
54 ],
55 toggle_bound("Notifications", &s.notify),
56 ],
57 section![header: text("Playback");
58 vstack_aligned(&[
59 hstack![
60 text("Volume"),
61 spacer(),
62 text!("{:.0}%", s.volume.get() * 100.0).fg_system(SystemColor::Gray),
63 ],
64 slider_bound(&s.volume, 0.0, 1.0),
65 ], HorizontalAlignment::Leading),
66 stepper_bound("Refresh every", &s.refresh, 1.0, 60.0, 1.0),
67 ],
68 section![header: text("Appearance");
69 picker_bound!(
70 "Theme",
71 &s.theme,
72 text(THEMES[0]).tag_int(0),
73 text(THEMES[1]).tag_int(1),
74 text(THEMES[2]).tag_int(2),
75 )
76 .picker_style(PickerStyle::InlinePickerStyle),
77 ],
78 section![
79 button("About", show_about)
80 .a11y_hint("Opens a panel describing this app"),
81 ],
82 ]
83 .form_style(FormStyle::GroupedFormStyle)
84 .sheet_bound(&s.about, about_panel())
85}
86
87/// The sheet, which the user can dismiss — the flag is Rust's, so closing it
88/// writes `false` back rather than leaving the two sides disagreeing.
89fn about_panel() -> View {
90 let s = settings();
91 vstack_spacing(
92 &[
93 system_image("gearshape.fill")
94 .symbol_rendering_mode(Some(views::SymbolRenderingMode::Hierarchical))
95 .view()
96 .font_size(48.0)
97 .fg_system(SystemColor::Blue),
98 text("Settings").text_style(TextStyle::Title).bold(),
99 text!("Signed in as {}", s.name.get()).fg_system(SystemColor::Gray),
100 spacer(),
101 button("Done", hide_about).button_style(views::ButtonStyle::BorderedProminent),
102 ],
103 16.0,
104 )
105 .padding(24.0)
106 .presentation_detents(&[views::PresentationDetent::Medium])
107 .presentation_drag_indicator(Visibility::Visible)
108}Sourcepub fn fg_linear_gradient(
self,
colors: &[Color],
start: (f64, f64),
end: (f64, f64),
) -> Self
pub fn fg_linear_gradient( self, colors: &[Color], start: (f64, f64), end: (f64, f64), ) -> Self
.foregroundStyle(LinearGradient(colors:startPoint:endPoint:)) — text
and symbols painted with a gradient instead of a flat colour.
Unit points, as in View::bg_linear_gradient.
On a Text this is Text.foregroundStyle(_:), which returns Text.
Sourcepub fn kerning(self, amount: f64) -> Self
pub fn kerning(self, amount: f64) -> Self
.kerning(_:) — Text.kerning(_:) on a Text, which returns Text.
Sourcepub fn tracking(self, amount: f64) -> Self
pub fn tracking(self, amount: f64) -> Self
.tracking(_:) — like kerning, but not suppressed between the pairs the
font has a ligature for.
Sourcepub fn line_spacing(self, amount: f64) -> Self
pub fn line_spacing(self, amount: f64) -> Self
.lineSpacing(_:)
Sourcepub fn line_limit(self, limit: i64) -> Self
pub fn line_limit(self, limit: i64) -> Self
.lineLimit(_:)
Sourcepub fn text_align(self, align: TextAlign) -> Self
pub fn text_align(self, align: TextAlign) -> Self
.multilineTextAlignment(_:)
Sourcepub fn autocorrection_disabled(self, disable: Option<bool>) -> Self
pub fn autocorrection_disabled(self, disable: Option<bool>) -> Self
.disableAutocorrection(_:) — None restores the system default.
Named for the modern spelling because that is what a caller looks for,
but autocorrectionDisabled(_:) is inlined and exports no symbol — this
reaches disableAutocorrection(_:), which is the same modifier and the
one SwiftUI still exports.
Sourcepub fn text_scale(self, scale: TextScale, enabled: bool) -> Self
pub fn text_scale(self, scale: TextScale, enabled: bool) -> Self
.textScale(_:isEnabled:)
Sourcepub fn dynamic_type_size(self, size: DynamicTypeSize) -> Self
pub fn dynamic_type_size(self, size: DynamicTypeSize) -> Self
.dynamicTypeSize(_:) — pin the size class rather than following the
system setting.
Sourcepub fn accent_color(self, color: Option<Color>) -> Self
pub fn accent_color(self, color: Option<Color>) -> Self
.accentColor(_:) — None restores the inherited accent.
Deprecated in SwiftUI in favour of View::tint, and kept because the
documentation still shows it.
Sourcepub fn underline_styled(
self,
active: bool,
pattern: LinePattern,
color: Option<Color>,
) -> Self
pub fn underline_styled( self, active: bool, pattern: LinePattern, color: Option<Color>, ) -> Self
.underline(_:pattern:color:) — None keeps the text’s own colour.
active is not decoration: this writes the environment, so passing
false is how a subtree turns off an underline it would otherwise
inherit. There is no other way to say that.
Sourcepub fn strikethrough(self) -> Self
pub fn strikethrough(self) -> Self
.strikethrough()
Sourcepub fn strikethrough_styled(
self,
active: bool,
pattern: LinePattern,
color: Option<Color>,
) -> Self
pub fn strikethrough_styled( self, active: bool, pattern: LinePattern, color: Option<Color>, ) -> Self
.strikethrough(_:pattern:color:) — active: false turns off an
inherited strikethrough, as with View::underline_styled.
Examples found in repository?
59fn row(i: usize, it: &Item) -> View {
60 hstack_spacing(
61 &[
62 // The checkmark is the button, so the whole symbol is the target.
63 button_labelled(
64 system_image(if it.done { "checkmark.circle.fill" } else { "circle" })
65 .symbol_rendering_mode(Some(views::SymbolRenderingMode::Hierarchical))
66 .view()
67 .fg_system(if it.done { SystemColor::Green } else { SystemColor::Gray }),
68 move || toggle(i),
69 )
70 .button_style(views::ButtonStyle::Bordered),
71 text(&it.title)
72 .strikethrough_styled(it.done, LinePattern::Solid, None)
73 .fg_system(if it.done { SystemColor::Gray } else { SystemColor::Primary }),
74 spacer(),
75 ],
76 10.0,
77 )
78 .padding_edges(EdgeSet::Vertical, Some(6.0))
79 .a11y_label(&it.title)
80 .a11y_value(if it.done { "Done" } else { "Not done" })
81}Sourcepub fn truncation_mode(self, mode: TruncationMode) -> Self
pub fn truncation_mode(self, mode: TruncationMode) -> Self
.truncationMode(_:) — which end of over-long text gets the ellipsis.
Sourcepub fn line_height(self, height: Option<LineHeightKind>) -> Self
pub fn line_height(self, height: Option<LineHeightKind>) -> Self
.lineHeight(_:) — None restores the font’s own leading.
Sourcepub fn font_design(self, design: Design) -> Self
pub fn font_design(self, design: Design) -> Self
.fontDesign(_:) — .monospaced and friends, without restating the size.
Sourcepub fn font_width(self, width: Option<FontWidth>) -> Self
pub fn font_width(self, width: Option<FontWidth>) -> Self
.fontWidth(_:) — None restores the default width.
Sourcepub fn redacted(self, reasons: RedactionReasons) -> Self
pub fn redacted(self, reasons: RedactionReasons) -> Self
.redacted(reason:) — the placeholder treatment, for loading states.
Sourcepub fn text_field_style(self, style: TextFieldStyle) -> Self
pub fn text_field_style(self, style: TextFieldStyle) -> Self
.textFieldStyle(_:) — .roundedBorder is the one that looks like a
field rather than a line of text.
Examples found in repository?
43fn body() -> View {
44 let s = settings();
45
46 form![
47 section![header: text("Account");
48 hstack![
49 text("Name"),
50 spacer(),
51 textfield_bound("Your name", &s.name).text_field_style(
52 views::TextFieldStyle::RoundedBorderTextFieldStyle,
53 ),
54 ],
55 toggle_bound("Notifications", &s.notify),
56 ],
57 section![header: text("Playback");
58 vstack_aligned(&[
59 hstack![
60 text("Volume"),
61 spacer(),
62 text!("{:.0}%", s.volume.get() * 100.0).fg_system(SystemColor::Gray),
63 ],
64 slider_bound(&s.volume, 0.0, 1.0),
65 ], HorizontalAlignment::Leading),
66 stepper_bound("Refresh every", &s.refresh, 1.0, 60.0, 1.0),
67 ],
68 section![header: text("Appearance");
69 picker_bound!(
70 "Theme",
71 &s.theme,
72 text(THEMES[0]).tag_int(0),
73 text(THEMES[1]).tag_int(1),
74 text(THEMES[2]).tag_int(2),
75 )
76 .picker_style(PickerStyle::InlinePickerStyle),
77 ],
78 section![
79 button("About", show_about)
80 .a11y_hint("Opens a panel describing this app"),
81 ],
82 ]
83 .form_style(FormStyle::GroupedFormStyle)
84 .sheet_bound(&s.about, about_panel())
85}More examples
83fn body() -> View {
84 let todos = items().lock().unwrap().clone();
85 let remaining = todos.iter().filter(|i| !i.done).count();
86
87 vstack_aligned_spacing(
88 &[
89 hstack![
90 text("Todo").text_style(TextStyle::LargeTitle).bold(),
91 spacer(),
92 text!("{remaining} left").fg_system(SystemColor::Gray),
93 ],
94 hstack_spacing(
95 &[
96 textfield_bound("What needs doing?", draft())
97 .text_field_style(views::TextFieldStyle::RoundedBorderTextFieldStyle)
98 .on_submit(SubmitTrigger::Text, add)
99 .submit_label(SubmitLabel::Done),
100 button("Add", add).button_style(views::ButtonStyle::BorderedProminent),
101 ],
102 8.0,
103 ),
104 // The empty state is a branch, so it arrives and leaves rather than
105 // appearing from nothing.
106 view_if!(
107 todos.is_empty(),
108 vstack_spacing(
109 &[
110 system_image("checkmark.seal").view().font_size(40.0)
111 .fg_system(SystemColor::Green),
112 text("Nothing left to do").fg_system(SystemColor::Gray),
113 ],
114 8.0,
115 )
116 .frame_optional(None, Some(160.0), Alignment::Center)
117 .transition(Transition::ScaleWithOpacity { scale: 0.8, anchor: (0.5, 0.5) }),
118 list(for_each_items(
119 &todos.iter().cloned().enumerate().collect::<Vec<_>>(),
120 |(i, it)| row(*i, it),
121 ))
122 .list_style(views::ListStyle::PlainListStyle)
123 ),
124 ],
125 HorizontalAlignment::Leading,
126 Some(14.0),
127 )
128 .padding(20.0)
129}Sourcepub fn submit_label(self, label: SubmitLabel) -> Self
pub fn submit_label(self, label: SubmitLabel) -> Self
.submitLabel(_:) — what the return key says.
Examples found in repository?
83fn body() -> View {
84 let todos = items().lock().unwrap().clone();
85 let remaining = todos.iter().filter(|i| !i.done).count();
86
87 vstack_aligned_spacing(
88 &[
89 hstack![
90 text("Todo").text_style(TextStyle::LargeTitle).bold(),
91 spacer(),
92 text!("{remaining} left").fg_system(SystemColor::Gray),
93 ],
94 hstack_spacing(
95 &[
96 textfield_bound("What needs doing?", draft())
97 .text_field_style(views::TextFieldStyle::RoundedBorderTextFieldStyle)
98 .on_submit(SubmitTrigger::Text, add)
99 .submit_label(SubmitLabel::Done),
100 button("Add", add).button_style(views::ButtonStyle::BorderedProminent),
101 ],
102 8.0,
103 ),
104 // The empty state is a branch, so it arrives and leaves rather than
105 // appearing from nothing.
106 view_if!(
107 todos.is_empty(),
108 vstack_spacing(
109 &[
110 system_image("checkmark.seal").view().font_size(40.0)
111 .fg_system(SystemColor::Green),
112 text("Nothing left to do").fg_system(SystemColor::Gray),
113 ],
114 8.0,
115 )
116 .frame_optional(None, Some(160.0), Alignment::Center)
117 .transition(Transition::ScaleWithOpacity { scale: 0.8, anchor: (0.5, 0.5) }),
118 list(for_each_items(
119 &todos.iter().cloned().enumerate().collect::<Vec<_>>(),
120 |(i, it)| row(*i, it),
121 ))
122 .list_style(views::ListStyle::PlainListStyle)
123 ),
124 ],
125 HorizontalAlignment::Leading,
126 Some(14.0),
127 )
128 .padding(20.0)
129}Sourcepub fn on_submit(
self,
trigger: SubmitTrigger,
action: impl Fn() + 'static,
) -> Self
pub fn on_submit( self, trigger: SubmitTrigger, action: impl Fn() + 'static, ) -> Self
.onSubmit(of:_:) — the return key, or a search field’s, or a
collection’s, depending on the trigger.
Examples found in repository?
83fn body() -> View {
84 let todos = items().lock().unwrap().clone();
85 let remaining = todos.iter().filter(|i| !i.done).count();
86
87 vstack_aligned_spacing(
88 &[
89 hstack![
90 text("Todo").text_style(TextStyle::LargeTitle).bold(),
91 spacer(),
92 text!("{remaining} left").fg_system(SystemColor::Gray),
93 ],
94 hstack_spacing(
95 &[
96 textfield_bound("What needs doing?", draft())
97 .text_field_style(views::TextFieldStyle::RoundedBorderTextFieldStyle)
98 .on_submit(SubmitTrigger::Text, add)
99 .submit_label(SubmitLabel::Done),
100 button("Add", add).button_style(views::ButtonStyle::BorderedProminent),
101 ],
102 8.0,
103 ),
104 // The empty state is a branch, so it arrives and leaves rather than
105 // appearing from nothing.
106 view_if!(
107 todos.is_empty(),
108 vstack_spacing(
109 &[
110 system_image("checkmark.seal").view().font_size(40.0)
111 .fg_system(SystemColor::Green),
112 text("Nothing left to do").fg_system(SystemColor::Gray),
113 ],
114 8.0,
115 )
116 .frame_optional(None, Some(160.0), Alignment::Center)
117 .transition(Transition::ScaleWithOpacity { scale: 0.8, anchor: (0.5, 0.5) }),
118 list(for_each_items(
119 &todos.iter().cloned().enumerate().collect::<Vec<_>>(),
120 |(i, it)| row(*i, it),
121 ))
122 .list_style(views::ListStyle::PlainListStyle)
123 ),
124 ],
125 HorizontalAlignment::Leading,
126 Some(14.0),
127 )
128 .padding(20.0)
129}Sourcepub fn text_content_type(self, kind: Option<TextContentKind>) -> Self
pub fn text_content_type(self, kind: Option<TextContentKind>) -> Self
.textContentType(_:) — what the field holds, which is what lets the
system offer a saved password or a one-time code. None clears it.
Sourcepub fn keyboard_shortcut(self, shortcut: KeyboardShortcut) -> Self
pub fn keyboard_shortcut(self, shortcut: KeyboardShortcut) -> Self
.keyboardShortcut(_:) — .defaultAction is return, .cancelAction is
escape, which is what makes a button the one a sheet’s return key hits.
Examples found in repository?
More examples
54fn body() -> View {
55 vstack_aligned_spacing(
56 &[
57 text("System").text_style(TextStyle::LargeTitle).bold(),
58 grid(&[grid_row(&[tile(0), tile(1), tile(2)])]),
59 divider(),
60 // A gauge over the busiest reading, which is a different control
61 // from the rings and reads the same state.
62 vstack_aligned(
63 &[
64 text("Busiest").font_size(12.0).fg_system(SystemColor::Gray),
65 gauge(reading(1), 0.0, 1.0, text("Memory"))
66 .gauge_style(views::GaugeStyle::AccessoryLinearCapacityGaugeStyle)
67 .tint_system(SystemColor::Orange),
68 ],
69 HorizontalAlignment::Leading,
70 ),
71 spacer(),
72 button("Refresh", refresh)
73 .button_style(views::ButtonStyle::BorderedProminent)
74 .keyboard_shortcut(KeyboardShortcut::DefaultAction),
75 ],
76 HorizontalAlignment::Leading,
77 Some(16.0),
78 )
79 .padding(20.0)
80 // Animate whatever changed, rather than snapping to the new reading.
81 .animation(LOAD[0].load(Ordering::Relaxed) as i64)
82}Sourcepub fn list_row_background(self, background: Option<View>) -> Self
pub fn list_row_background(self, background: Option<View>) -> Self
.listRowBackground(_:) — None restores the default.
Source§impl View
impl View
Sourcepub fn new(handle: ViewHandle) -> Self
pub fn new(handle: ViewHandle) -> Self
Wrap a handle so the chainable modifiers can be used on it.
Sourcepub fn handle(&self) -> &ViewHandle
pub fn handle(&self) -> &ViewHandle
Get the underlying handle.
Sourcepub fn into_handle(self) -> ViewHandle
pub fn into_handle(self) -> ViewHandle
Consume and return the handle.
Examples found in repository?
More examples
82fn content_view() -> swiftui_native::ViewHandle {
83 swiftui_native::state::root_view(|_| body().into_handle())
84}
85
86/// Screens written here as *data*, not as Rust.
87///
88/// Each is a string this file could have read from disk instead; they are
89/// inline so the example runs with no arguments and so the renders are
90/// reproducible. Between them they reach stacks, shapes, controls, text
91/// styling and nesting — the same span the hand-written examples cover, with
92/// nothing about them in the compiled code.
93const DEMOS: &[(&str, &str)] = &[
94 (
95 "readout",
96 r#"
97// A status readout. Nothing here is a Rust type.
98vstack spacing=14 pad=20 align=leading {
99 text "Deployment" style=large_title bold
100 text "3 of 4 regions healthy" color=secondary size=13
101
102 divider
103
104 hstack spacing=12 {
105 circle color=green frame=14x14
106 text "us-east" size=14
107 spacer
108 text "ok" color=green size=13
109 }
110 hstack spacing=12 {
111 circle color=green frame=14x14
112 text "us-west" size=14
113 spacer
114 text "ok" color=green size=13
115 }
116 hstack spacing=12 {
117 circle color=orange frame=14x14
118 text "eu-central" size=14
119 spacer
120 text "degraded" color=orange size=13
121 }
122 hstack spacing=12 {
123 circle color=gray frame=14x14
124 text "ap-south" size=14
125 spacer
126 text "draining" color=gray size=13
127 }
128
129 divider
130 text "Rollout" size=12 color=secondary
131 progress 0.62
132 spacer
133 button "Promote"
134}
135"#,
136 ),
137 (
138 "card",
139 r#"
140// A card, to show layering and a hex colour.
141zstack align=center frame=320x200 {
142 color #1d2b53 frame=300x180 corner=16
143 vstack spacing=10 pad=24 align=leading {
144 text "Boarding pass" style=title2 bold color=white
145 text "LHR to SFO" color=white size=14 opacity=0.8
146 spacer
147 hstack spacing=16 {
148 vstack spacing=2 align=leading {
149 text "GATE" size=10 color=white opacity=0.6
150 text "B14" style=title3 bold color=white
151 }
152 vstack spacing=2 align=leading {
153 text "SEAT" size=10 color=white opacity=0.6
154 text "22A" style=title3 bold color=white
155 }
156 spacer
157 image "airplane"
158 }
159 }
160}
161"#,
162 ),
163 (
164 "gauges",
165 r#"
166// Three gauges and a grouped block, from data alone.
167vstack spacing=16 pad=20 align=leading {
168 text "Capacity" style=title bold
169 gauge 0.34 label="CPU"
170 gauge 0.71 label="Memory"
171 gauge 0.12 label="Disk"
172 divider
173 group_box {
174 vstack spacing=6 align=leading {
175 text "Notes" style=headline
176 text "Every view on this screen was named by a string." size=12 color=secondary
177 text "The binary has no VStack<...> type baked in for it." size=12 color=secondary
178 }
179 }
180 spacer
181}
182"#,
183 ),
184];
185
186fn demo(name: &str) -> Option<&'static str> {
187 DEMOS.iter().find(|(n, _)| *n == name).map(|(_, s)| *s)
188}
189
190/// Read a spec from a path, a demo name, or stdin for `-`.
191fn load(arg: &str) -> Result<String, String> {
192 if arg == "-" {
193 use std::io::Read;
194 let mut s = String::new();
195 std::io::stdin().read_to_string(&mut s).map_err(|e| e.to_string())?;
196 return Ok(s);
197 }
198 if let Some(d) = demo(arg) {
199 return Ok(d.to_string());
200 }
201 std::fs::read_to_string(arg).map_err(|e| format!("{arg}: {e}"))
202}
203
204/// Read specs from stdin and render each as it arrives.
205///
206/// A blank line submits. This is the shortest demonstration there is: the same
207/// process, still running, drawing a screen typed a moment ago.
208fn repl() {
209 use std::io::{BufRead, Write};
210 eprintln!("Type a screen. Blank line renders it; Ctrl-D quits.");
211 eprintln!("Names: {}", spec::NAMES.join(" "));
212 let stdin = std::io::stdin();
213 let mut buf = String::new();
214 let mut n = 0usize;
215 loop {
216 eprint!("> ");
217 let _ = std::io::stderr().flush();
218 let mut line = String::new();
219 match stdin.lock().read_line(&mut line) {
220 Ok(0) => break,
221 Ok(_) => {}
222 Err(e) => {
223 eprintln!("{e}");
224 break;
225 }
226 }
227 if line.trim().is_empty() {
228 if buf.trim().is_empty() {
229 continue;
230 }
231 match spec::parse(&buf).and_then(|nodes| spec::build(&nodes)) {
232 Ok(v) => {
233 n += 1;
234 let out = format!(
235 "{}/../../target/dynamic_ui_repl_{n}.png",
236 env!("CARGO_MANIFEST_DIR")
237 );
238 let handle = v.into_handle();
239 eprintln!(" {}", swiftui_native::diag::type_name(
240 swiftui_native::views::meta_of(&handle)
241 ));
242 if swiftui_native::render::render(&handle, 420, 420).write_png(&out) {
243 eprintln!(" wrote {out}");
244 }
245 }
246 Err(e) => eprintln!(" {e}"),
247 }
248 buf.clear();
249 } else {
250 buf.push_str(&line);
251 }
252 }
253}
254
255/// Print the Swift type a spec builds.
256///
257/// The strongest short proof that this is real SwiftUI and not a lookalike: the
258/// name comes from the Swift runtime's own metadata, and it is a different name
259/// for every different spec.
260fn print_type(arg: &str) -> i32 {
261 match load(arg).and_then(|s| {
262 spec::parse(&s).and_then(|nodes| spec::build(&nodes)).map(|v| v.into_handle())
263 }) {
264 Ok(h) => {
265 println!(
266 "{}",
267 swiftui_native::diag::type_name(swiftui_native::views::meta_of(&h))
268 );
269 0
270 }
271 Err(e) => {
272 eprintln!("{e}");
273 1
274 }
275 }
276}
277
278#[cfg(target_os = "macos")]
279fn main() {
280 let args: Vec<String> = std::env::args().skip(1).collect();
281 let flag = |f: &str| args.iter().any(|a| a == f);
282
283 if flag("--names") {
284 println!("{}", spec::NAMES.join("\n"));
285 return;
286 }
287 if flag("--repl") {
288 return repl();
289 }
290 if let Some(i) = args.iter().position(|a| a == "--type") {
291 let Some(arg) = args.get(i + 1) else {
292 eprintln!("--type wants a spec: a path, `-`, or a demo name");
293 std::process::exit(2);
294 };
295 std::process::exit(print_type(arg));
296 }
297 if flag("--render") {
298 // One PNG per built-in spec. Different text, different Swift type,
299 // different picture — from one binary, in one process.
300 for (name, src) in DEMOS {
301 set_spec(src);
302 // The spec's own view, for the type name: `content_view` wraps it
303 // in the runtime-synthesised `RustView` that carries `@State`, and
304 // that wrapper is the same whatever the spec says. What differs —
305 // and what makes the point — is the type underneath it.
306 let built = body().into_handle();
307 let out = format!("{}/../../target/dynamic_ui_{name}.png", env!("CARGO_MANIFEST_DIR"));
308 let ok = swiftui_native::render::render(&content_view(), 380, 420).write_png(&out);
309 println!(
310 "{name:10} {}\n {}",
311 swiftui_native::diag::type_name(swiftui_native::views::meta_of(&built)),
312 if ok { out } else { "render failed".to_string() }
313 );
314 }
315 return;
316 }
317 if flag("--sim") {
318 return simulator::main(&simulator::Bundle {
319 example: "dynamic_ui",
320 bundle_id: "dev.rswift.DynamicUI",
321 executable: "DynamicUI",
322 display_name: "Dynamic UI",
323 launch_args: &[],
324 });
325 }
326
327 // A path or a demo name, else the first demo.
328 if let Some(arg) = args.iter().find(|a| !a.starts_with("--")) {
329 match load(arg) {
330 Ok(s) => set_spec(&s),
331 Err(e) => {
332 eprintln!("{e}");
333 std::process::exit(1);
334 }
335 }
336 }
337 show_window(&content_view(), "Dynamic UI", 380.0, 460.0);
338}