Skip to content

TableView de

Edgar Mesquita edited this page Oct 20, 2026 · 4 revisions

Tabellenansicht

🌐 Diese Seite auf: English · Português · Español · Français · Deutsch

TableView ist ein Fenster auf ein Gitter, das größer ist als jeder Bildschirm, auf BEIDEN Achsen, wie es Flutters TableView ist: Du beschreibst, wie weit jede Zeile und jede Spalte reicht, gibst ihm einen Builder, der die Zelle an einer Zeile und einer Spalte beantwortet, und sagst, wie viele der ersten Zeilen und Spalten angeheftet bleiben. Es baut nur die Zellen in Sicht plus einen Rand darum, sodass Excels ganzes Blatt, 1 048 576 Zeilen mal 16 384 Spalten, kostet, was ein Bildschirm kostet. Es ist write-once: Dasselbe C# läuft als GPU-Malerei auf Photon und als DOM im Web.

TableView(
    rows: new UniformTableSpans(1_048_576 + 1, 28),
    columns: new SparseTableSpans(16_384 + 1, 96, new Dictionary<int, double> { [0] = 48, [3] = 180 }),
    cellBuilder: (row, column) => Text(row == 0 ? $"{column}" : $"{row}:{column}", TypeRole.Caption),
    pinnedRows: 1,
    pinnedColumns: 1,
    width: SizeValue.Fill,
    height: SizeValue.Fill,
    label: "Sheet")

Der Bildschirm /table des Dashboard-Samples ist dieses Gitter, jede Zelle zeigt ihre eigene Adresse, eine Kopfzeile und eine Spalte mit Zeilennummern bleiben angeheftet.

Zeilen und Spalten

Jede Achse ist ein TableSpans: wie viele Zeilen (oder Spalten) es gibt, wie weit sie insgesamt reichen, und die zwei Fragen, die der Viewport stellt, wo der Index i beginnt (OffsetOf) und welcher Index bei einem Versatz liegt (IndexAt).

  • UniformTableSpans(count, extent): Jede Zeile (oder Spalte) reicht gleich weit. Jeder Versatz ist eine Multiplikation.
  • SparseTableSpans(count, extent, extents): eine Standardausdehnung und die wenigen, die ihre eigene haben, wie in einem Blatt, in dem jemand Spalte D verbreitert hat. Die Ausnahmen werden sortiert mit einer laufenden Summe gehalten, sodass ein Versatz eine binäre Suche über sie kostet, wie lang die Achse auch ist.
  • Deine eigene: Leite von TableSpans ab und beantworte Count, Total, ExtentOf, OffsetOf und IndexAt.

Versätze sind auf beiden Zielen double: Eine Million Zeilen zu 28 reichen bis 29 360 128, über das hinaus, wo ein float noch Punkt für Punkt zählt.

Das Fenster, das es baut

Die Tabelle baut die Zeilen und Spalten, die der Viewport zeigt, plus overscan (standardmäßig 3) über jeden Rand hinaus. Das Fenster hat Hysterese: Ein Scroll, der das Sichtbare innerhalb der bereits gebauten Zellen hält, baut nichts, und der Viewport verschiebt diese Zellen von selbst. Die Tabelle baut erst wieder, wenn die sichtbaren Zeilen oder Spalten sie verlassen.

Eine Zelle wird über ihre Position geschlüsselt ("row:column"), sodass eine Zelle, die im Fenster bleibt, ihr Element und ihren Zustand behält, wenn sich das Fenster verschiebt.

Der erste Frame wird für ein übliches Fenster (1 024 × 768) gebaut statt für nichts, damit er Zellen zeigt; der Viewport meldet dann seine wirkliche Größe, und der nächste Frame baut dafür.

Angeheftete Zeilen und Spalten

pinnedRows und pinnedColumns halten die ersten Zeilen oben und die ersten Spalten am Anfang, während der Rest scrollt. Der Viewport zeichnet vier Bänder, jedes unter seinem eigenen Beschnitt: die Ecke, die sich nie bewegt; die angehefteten Zeilen, die sich seitlich mit dem Gitter bewegen; die angehefteten Spalten, die sich mit ihm nach unten bewegen; und den Körper, der sich in beide Richtungen bewegt. Eine Zelle wird im Band ihrer ersten Zeile und ihrer ersten Spalte gezeichnet.

Marken

marks werden ÜBER den Zellen gezeichnet, über dem Bereich, den jede abdeckt, und nehmen weder Druck noch Fokus an: eine Auswahl, eine Umrandung, das Band einer Suche. Jede ist ein TableViewCell, mit mark: true erzeugt, und ihre rows und columns sagen, wie viele Zeilen und Spalten sie abdeckt:

TableViewCell(row: 4, column: 2, Box(new BoxStyle { BorderWidth = 2, BorderColor = theme.FocusRing }),
    mark: true, rows: 3, columns: 2)

Eine Marke, die den Rand eines angehefteten Bandes kreuzt, wird dort abgeschnitten, ein Stück je Band, sodass sie in jedem Band zu sehen ist, das sie erreicht, und sich dort verbirgt, wo sie unter einem hindurchgeht.

Scrollen

Der Viewport BESITZT seinen Versatz, auf beiden Zielen: Der Browser scrollt nichts. Das ist keine Geschmacksfrage. Ein Browser zeichnet ein Element höchstens 16 777 214 px hoch, und Excels Zeilen reichen bis 29 Millionen, sodass ein Gitter, das der Browser scrollte, nie seine letzte Zeile erreichen könnte. Die Tabelle verschiebt ihre Zellen stattdessen per Transform und zeichnet ihre eigenen Scrollleisten.

  • Ein Mausrad und ein Trackpad bewegen beide Achsen. Die präzisen Deltas eines Trackpads bewegen das Gitter, wie es die Finger tun; eine Rastung des Mausrads gleitet bis zu ihrem Ziel. Umschalt dreht ein vertikales Rad auf die andere Achse.
  • Die Scrollleisten sitzen in Streifen am Ende- und am unteren Rand. Ein Schieber wird gezogen, und ein Druck auf die Spur bewegt eine Seite in Richtung des Zeigers.
  • Ein Finger, der über einen Slop von 12 Punkten hinaus wandert, schwenkt das Gitter, und ein Abheben während der Bewegung schleudert es. Ein Druck, der nie wandert, ist weiterhin ein Tippen auf die Zelle darunter.
  • Was das Gitter an einem Rand nicht aufnehmen kann, geht an den Scroller um es herum weiter, sodass eine Seite weiterscrollt, sobald das Gitter an seinem Ende ist.
  • Die Tastatur: die Tabelle ist selbst ein Halt der Tab-Reihenfolge, vor den Steuerelementen ihrer Zellen. Mit dem Fokus bewegen die Pfeile einen Schritt, Bild auf und Bild ab eine Seite, Pos1 und Ende zur ersten und letzten Zeile, und mit Strg oder Befehl auch zur ersten und letzten Spalte. Tab besucht die Steuerelemente der Zellen Zeile für Zeile.
  • Eine Maus oder der Zeiger eines Trackpads auf einem Telefon oder Tablet drückt die Zellen, wie auf einem Desktop; nur ein Finger schwenkt.
  • Bei reduzierter Bewegung landet jeder Schritt auf einmal.

request scrollt in deinem Auftrag, einmal je Version:

request: new TableScrollRequest(version) { Reveal = new TableRange(1_048_575, 0) }

Offset setzt das Gitter auf einen Versatz; Reveal bringt einen Bereich in Sicht, frei von den angehefteten Bändern. Eine Anforderung wird erfüllt, wenn ihre Version neu ist, sodass es nichts zweimal bewirkt, bei jedem Build dieselbe zu übergeben. Sie gilt, bis die Person das Gitter bewegt, sodass ein Layout, das sich in zwei Durchgängen setzt, eine Zeile, die die Tabelle vor und nach ihren festen Geschwistern misst, sie trotzdem dorthin bringt, wo der letzte Durchgang es sagt.

onScrolled sagt, wo das Gitter steht (ein TableOffset, quer und nach unten) und onViewportChanged, wie groß der Teil ist, in dem die Zellen scrollen, jeweils einmal je Änderung.

Ein Fenster geben

Eine Tabelle IST ein Fenster, also gib ihr eines: eine feste Größe oder SizeValue.Fill innerhalb von etwas, das eine Größe hat. Eine Fill-Achse ohne Grenze, was eine Seite, die auf dieser Achse scrollt, ihrem Inhalt übergibt, nimmt die sichtbare Ausdehnung des nächsten Scrollers um sie herum, oder die des Fensters, und das Entwicklungsprotokoll sagt das einmal und nennt die Ausdehnung, die es genommen hat. Ihr eigener Inhalt entscheidet nie über ihre Größe, und eine eigene Breite, die breiter ist als der Platz, den ihr Elternteil gibt, wird auf diesen Platz begrenzt, auf beiden Zielen.

Barrierefreiheit

Der Viewport ist eine durch label benannte Gruppe über den Zellen, die er hält. Die Zellen, die er nicht hält, sind überhaupt nicht im Baum, auf keinem der beiden Ziele. Tab erreicht die Steuerelemente in den Zellen, die er hält, und ein Steuerelement, das außerhalb des Fensters den Fokus erhält, wird in den sichtbaren Bereich gerollt, frei von den angehefteten Bändern. Eine Marke ist nie ein Halt der Tab-Reihenfolge, und ein Screenreader erreicht sie nicht.

Unter der Komponente

TableView ist eine Komponente über einem Knoten des Vokabulars, TableViewport, der die TableViewCells platziert, die er bekommt, und das Scroll-Modell trägt (ITableScrollModel, implementiert von TableScroll). Eine Komponente, die ihr eigenes Fenster bestimmt, wie es Spreadsheet tun wird, kann den Knoten direkt mit demselben Modell komponieren: Die Realisierer füttern das Modell mit dem Rad, dem Zeiger und der Uhr und zeichnen, was es antwortet.

Clone this wiki locally