Diese Seite wurde maschinell übersetzt und kann Fehler enthalten. Das englische Original lesen

API

nsh/mobile

nsh/mobile enthält die Fähigkeiten speziell für iOS und Android: die Tab-Leiste des Systems, TabBar, auf beiden Plattformen; InputAccessoryView, eine Leiste über der Tastatur, auf iOS; und BackHandler, die Zurück-Taste, auf Android. Rust-Code verwendet nsh_core::mobile und nsh_core::prelude; TSX importiert nsh/mobile. Das Modul lässt sich auf jeder Plattform importieren, sodass ein Bundle überall läuft: Auf den anderen Plattformen beanspruchen seine Komponenten keinen Platz und seine Aufrufe kehren sofort zurück. isAvailable verrät, ob die App auf iOS oder Android läuft (platform.os aus nsh sagt, auf welchem von beiden). Was Desktops bieten, steht in nsh/desktop.

use nsh_core::mobile::{TabBarItem, tab_bar};

#Geltungsbereich

Dieses Modul stellt Fähigkeiten bereit, die speziell für mobile Plattformen gelten, etwa die System-Tab-Leiste für die Navigation auf oberster Ebene einer App. Gemeinsame Steuerelemente gehören zu nsh/base: Dessen Switch etwa teilt Verhalten und API über Smartphones, Desktops und das Web hinweg, wobei Track, Thumb und Zustandsstile von der App geliefert werden. TabBar dient der Navigation mobiler Apps; Tabs dient tabulatorbasierten Inhalten über Plattformen hinweg. Hierher gehören nur Fähigkeiten mit mobilspezifischer Interaktionssemantik. Ein System-Erscheinungsbild, eine Größe oder eine Animation allein ändert nichts an der gemeinsamen Rolle eines allgemeinen Steuerelements. Diese Unterscheidung bestimmt, welche Fähigkeiten hierher gehören (Ziele und Designprinzipien).

#isAvailable

const isAvailable: boolean;

true auf iOS, im iOS-Simulator, auf Mac Catalyst und Android; false andernorts. Rust: matches!(os(), Os::Ios | Os::Android).

#TabBar

Eine Tab-Leiste wechselt zwischen den Bereichen auf oberster Ebene einer App: Aufzeichnungen und Statistiken, Posteingang und Einstellungen. TabBar ist die systemeigene Leiste, sieht also aus und verhält sich wie die Apps des Systems: UITabBar auf iOS und iPadOS (Liquid Glass und dessen Auswahl ab iOS 26), die Navigationsleiste von Material 3 auf Android, in den Systemfarben, hell und dunkel. Die App liefert die Tabs (items), gibt an, welcher ausgewählt ist (selectedIndex), erfährt die Wahl des Nutzers (onChange), platziert die Leiste mit class und style und zeigt den Inhalt des ausgewählten Bereichs selbst an. Für Tabs innerhalb einer Seite und auf jeder Plattform verwende Tabs von nsh/base.

use nsh_core::{
    mobile::{TabBarItem, tab_bar},
    prelude::*,
};

fn sections() -> impl IntoElement {
    let section = signal(0u32);
    view()
        .flex_1()
        .child(text(move || match section.get() {
            0 => "Records",
            _ => "Stats",
        }))
        .child(
            tab_bar()
                .items(vec![
                    TabBarItem::new("Records").icon("list.bullet"),
                    TabBarItem::new("Stats").icon("chart.bar"),
                ])
                .selected_index(section)
                .on_change(move |index: &u32| section.set(*index))
                .absolute()
                .left_0()
                .right_0()
                .bottom_0(),
        )
}

TabBar stammt aus nsh/mobile, in Rust aus nsh_core::mobile. Die Auswahl gehört der App: Ein Tippen meldet onChange mit dem Index des Tabs ({ index }), die Leiste zeigt die Wahl sofort an, wie es die des Systems tut, und die App zeigt den entsprechenden Bereich an und gibt den Index als selectedIndex zurück. Die Höhe entspricht der des Systems, sofern der Stil sie offenlässt. In Rust erzeugt tab_bar() eine Leiste, mit einem Setter pro Prop (.items(..), .selected_index(..)), einem Listener pro Event (.on_change(..)) und den typisierten Stilmethoden; TabBarItem::new(title).icon(name) erzeugt einen Tab.

#Props

Prop Rust Typ Standard Beschreibung
items .items(..) TabBarItem[] [] Die Tabs in ihrer Reihenfolge.
selectedIndex .selected_index(..) number 0 Der ausgewählte Tab, per Index; ein Index hinter den Tabs wählt keinen aus.
hidden .hidden(..) boolean false iOS: Blendet die Leiste ohne Übergang aus. Die App besitzt diesen Wert über Pushes und Pops hinweg. Die Leiste wird angezeigt, wenn sowohl dieser Prop als auch die hidesBottomBarWhenPushed-Anforderung des sichtbaren Stacks false sind.
class, style Stilmethoden string, StyleProp<ViewStyle> keiner Wo die Leiste liegt: Position und Größe. Ihr Aussehen ist das des Systems, wobei der ausgewählte Tab die primary des Themes verwendet.
testID .test_id(..) string keiner Findet die Leiste in Tests und nsh test --trace.

#TabBarItem

Feld Rust Typ Beschreibung
title TabBarItem::new(title) string Der Titel des Tabs, den Screenreader vorlesen.
icon .icon(name) string Das Symbol des Tabs, über den plattformeigenen Namen: ein SF Symbol auf iOS ("house"), ein Drawable der App auf Android (res/drawable/home.xml ist "home", "android:ic_menu_search" das des Systems). platform.select wählt eines pro Plattform aus.

#Events

Event Rust Beschreibung
onChange .on_change(|index: &u32| ..) Der Nutzer hat einen Tab gewählt: { index }, dessen Index. Die Leiste zeigt die Wahl sofort an; die App zeigt den Inhalt des Tabs an und setzt selectedIndex.

#Plattformhinweise

  • iOS und Mac Catalyst: UITabBar mit dem Erscheinungsbild des Systems für die jeweilige iOS-Version: die schwebende Liquid-Glass-Leiste und deren Auswahl ab iOS 26. Symbole sind SF Symbols. Die primary des Themes ist der tintColor der Leiste, die Farbe des ausgewählten Tabs; die anderen Tabs behalten die Farbe des Systems.
  • Android: Die Navigationsleiste von Material 3, aufgebaut aus den Views der Plattform: ein Symbol in seinem aktiven Indikator über jedem Label, ein Ripple beim Drücken, die dynamischen Farben des Systems ab Android 12 und davor die Basisfarben von Material, hell oder dunkel gemäß dem Erscheinungsbild der App. Am unteren Fensterrand reicht sie unter die Navigationsleiste und ist um deren Inset höher, wie bei Material. Symbole sind Drawables der App (von der Leiste eingefärbt). Symbol und Label des ausgewählten Tabs verwenden die primary des Themes, über einem aktiven Indikator in dieser Farbe mit 12 % Deckkraft; die anderen Tabs behalten die Farbe des Systems.
  • Desktops (macOS, Windows, Linux, GPUI) und das Web: Die Bereiche werden mit Tabs im Look der App angezeigt. TabBar beansprucht dort keinen Platz, sodass ein Layout beide Fälle abdeckt, ausgewählt durch platform.os (Geräte-API von nsh).

#InputAccessoryView

Auf iOS und Mac Catalyst; auf Android ist sie eine leere, versteckte View.

function InputAccessoryView(props: InputAccessoryViewProps): JSX.Element;

interface InputAccessoryViewProps {
  nativeID: string;
  style?: StyleProp<ViewStyle>;
  class?: string;
  children?: JSX.Element;
}

Eine Leiste über der Tastatur (inputAccessoryView von UIKit), die angezeigt wird, solange ein Eingabefeld den Fokus hat, dessen ios={{ inputAccessoryViewID }} zu ihrer nativeID passt. Rust: input_accessory_view(native_id), angezeigt für die Eingabefelder, deren .input_accessory(native_id) passt. Sie ist so breit wie das Fenster und so hoch wie ihr Inhalt und bewegt sich nativ mit der Tastatur.

Prop Typ Rust Beschreibung
nativeID string input_accessory_view(native_id) Eingabefelder mit dieser inputAccessoryViewID zeigen die Leiste an.
style StyleProp<ViewStyle> Styled-Methoden (.bg(…)) Der Stil der Leiste (zum Beispiel ihr Hintergrund).
class string Tailwind-Klassen.
children JSX.Element .child(…) Der Inhalt der Leiste.

Sie rendert an der Stelle im Baum, an der sie platziert wird, nichts, und auf Android überhaupt nichts, sodass du sie neben dem Eingabefeld platzieren kannst, zu dem sie gehört.

use nsh_core::prelude::*;

#[component]
fn Note() -> impl IntoElement {
    let note = signal(String::new());
    let field = element_ref();
    view()
        .child(
            input()
                .element_ref(&field)
                .value(note)
                .on_change(move |value: &str| note.set(value.to_string()))
                .placeholder("Write a note")
                .input_accessory("note-bar"),
        )
        .child(
            input_accessory_view("note-bar").bg(rgb(0xf1f5f9)).child(
                view()
                    .flex_row()
                    .items_center()
                    .p(px(10.0))
                    .child(
                        text(move || format!("{} characters", note.with(|n| n.chars().count())))
                            .flex_1()
                            .text_color(rgb(0x64748b)),
                    )
                    .child(text("Done").font_weight(FontWeight::SEMIBOLD).on_press(move || field.blur())),
            ),
        )
}

Siehe auch Formulare und Tastatur.

#BackHandler

Auf Android; auf iOS werden die Listener behalten, aber nie aufgerufen, und exitApp() kehrt sofort zurück.

const BackHandler: {
  on(event: "press", listener: () => boolean | void): () => void;
  exitApp(): void;
};

Die Zurück-Taste und die Zurück-Geste des Systems. Dialoge behandeln den Zurück-Druck zuerst (ein Dialog wird geschlossen); danach laufen die Listener von BackHandler, der zuletzt hinzugefügte zuerst; behandelt ihn keiner von ihnen, wird der oberste Navigationsstack zurückgenommen, und gibt es keine Seite mehr, zu der man zurückkehren kann, wird die App beendet.

Member Rust Beschreibung
on("press", listener) on_back_press(listener) listener gibt true zurück, wenn er den Druck behandelt hat. Gibt eine Funktion zurück, die das Lauschen beendet; ein Listener, der hinzugefügt wird, während eine Komponente rendert (oder ein Effekt läuft), endet mit ihr, in Rust wie in TSX.
exitApp() der Listener gibt false zurück Verlässt die App. Ein Rust-Listener, der false zurückgibt, lässt den Druck weiterlaufen, sodass der Stack zurückgeht oder die App beendet wird.
use nsh_base::alert_dialog;
use nsh_core::prelude::*;

#[component]
fn Editor() -> impl IntoElement {
    let dirty = signal(false);
    on_back_press(move || {
        if !dirty.get_untracked() {
            return false; // let the app go back or exit
        }
        spawn(async move {
            let answer = alert_dialog().title("Discard changes?").cancel("keep", "Keep").destructive("discard", "Discard").show().await;
            if answer.is_ok_and(|r| r.action.as_deref() == Some("discard")) {
                dirty.set(false); // the next back press leaves
            }
        });
        true
    });
    // ...
}

Die Statusleiste wird auf iOS und Android gleichermaßen von statusBar der Seiten und Dialoge aus nsh/base gesetzt.