跳到正文
浏览文档

Tabs

以 TabStrip 与 TabControl 形式提供默认、outline、pill、segmented 与 underline 五种外观的标签栏。

示例可交互
Tabs — Avalonia UIKit
Live demo unavailable
<TabControl Classes="underline" Width="320" HorizontalAlignment="Left">
  <TabItem Header="Account">
    <TextBlock Text="Make changes to your account here." Margin="0,12" />
  </TabItem>
  <TabItem Header="Profile">
    <TextBlock Text="Edit your public profile." Margin="0,12" />
  </TabItem>
  <TabItem Header="Settings">
    <TextBlock Text="Change your preferences." Margin="0,12" />
  </TabItem>
</TabControl>

用法

主题涵盖 TabStrip 与 TabStripItem(独立的标签栏),以及 TabControl 与 TabItem 的标签条(带内容的标签页)。外观是标签条或控件上的样式类:不加样式类即默认外观,也可以使用 outline、pill、segmented 或 underline。Pill、segmented 与 underline 以指示器呈现选中项,指示器沿 UIKit.Spring.Move 弹簧滑到选中的标签,并在选中项再次变化时中途反向;pill 的标签会随指示器滑动而淡入。尺寸:xsmall、small、large(不加则为 medium)。内容为图标的项请加 icon-only。标签只在键盘焦点时显示焦点环。借助 uikit:Tabs 附加属性,标签可以关闭、新增与拖拽(见关闭、添加与拖拽)。

示例

五种外观;最后一个 underline 标签处于禁用状态。

变体可交互
Live demo unavailable
<StackPanel Spacing="16" HorizontalAlignment="Left">
  <TabStrip Width="320" SelectedIndex="0">
    <TabStripItem Content="Account" />
    <TabStripItem Content="Profile" />
    <TabStripItem Content="Settings" />
  </TabStrip>
  <TabStrip Classes="outline" Width="320" SelectedIndex="0">
    <TabStripItem Content="Account" />
    <TabStripItem Content="Profile" />
    <TabStripItem Content="Settings" />
  </TabStrip>
  <TabStrip Classes="pill" Width="320" SelectedIndex="0">
    <TabStripItem Content="Account" />
    <TabStripItem Content="Profile" />
    <TabStripItem Content="Settings" />
  </TabStrip>
  <TabStrip Classes="segmented" Width="320" SelectedIndex="0">
    <TabStripItem Content="Account" />
    <TabStripItem Content="Profile" />
    <TabStripItem Content="Settings" />
  </TabStrip>
  <TabStrip Classes="underline" Width="320" SelectedIndex="0">
    <TabStripItem Content="Account" />
    <TabStripItem Content="Profile" />
    <TabStripItem Content="Settings" IsEnabled="False" />
  </TabStrip>
</StackPanel>

pill 标签条的四种尺寸。

尺寸可交互
Live demo unavailable
<StackPanel Spacing="16" HorizontalAlignment="Left">
  <TabStrip Classes="pill xsmall" SelectedIndex="0">
    <TabStripItem Content="Account" />
    <TabStripItem Content="Profile" />
    <TabStripItem Content="Settings" />
  </TabStrip>
  <TabStrip Classes="pill small" SelectedIndex="0">
    <TabStripItem Content="Account" />
    <TabStripItem Content="Profile" />
    <TabStripItem Content="Settings" />
  </TabStrip>
  <TabStrip Classes="pill" SelectedIndex="0">
    <TabStripItem Content="Account" />
    <TabStripItem Content="Profile" />
    <TabStripItem Content="Settings" />
  </TabStrip>
  <TabStrip Classes="pill large" SelectedIndex="0">
    <TabStripItem Content="Account" />
    <TabStripItem Content="Profile" />
    <TabStripItem Content="Settings" />
  </TabStrip>
</StackPanel>

icon-only 项分别位于 pill 与 segmented 标签条中。

仅图标可交互
Live demo unavailable
<StackPanel Spacing="16" HorizontalAlignment="Left">
  <TabStrip Classes="pill" SelectedIndex="0">
    <TabStripItem Classes="icon-only">
      <PathIcon Data="{StaticResource UIKit.Icon.Inbox}" />
    </TabStripItem>
    <TabStripItem Classes="icon-only">
      <PathIcon Data="{StaticResource UIKit.Icon.Star}" />
    </TabStripItem>
    <TabStripItem Classes="icon-only">
      <PathIcon Data="{StaticResource UIKit.Icon.User}" />
    </TabStripItem>
  </TabStrip>
  <TabStrip Classes="segmented" SelectedIndex="0">
    <TabStripItem Classes="icon-only">
      <PathIcon Data="{StaticResource UIKit.Icon.Inbox}" />
    </TabStripItem>
    <TabStripItem Classes="icon-only">
      <PathIcon Data="{StaticResource UIKit.Icon.Star}" />
    </TabStripItem>
    <TabStripItem Classes="icon-only">
      <PathIcon Data="{StaticResource UIKit.Icon.User}" />
    </TabStripItem>
  </TabStrip>
</StackPanel>

菜单、前缀与后缀

放不下的标签会横向滚动,选中的标签会滚动到可见区域。menu 样式类在标签条末尾添加一个下拉按钮,列出所有标签,选中项打勾、禁用项为禁用状态,并选中点选的那一个。uikit:Tabs.Prefix 与 uikit:Tabs.Suffix 把内容放在标签条的起始与末尾,位于滚动区域之外;使用后缀或菜单时,标签末尾会留出 12px 间距。它们在 TabStrip 与 TabControl 上行为一致。

在 400px 宽的标签条中放六个标签,并带菜单、前缀与后缀。

菜单可交互
Live demo unavailable
<TabStrip Classes="menu" Width="400" VerticalAlignment="Top" SelectedIndex="0">
  <uikit:Tabs.Prefix>
    <StackPanel Orientation="Horizontal" Margin="4,0">
      <Button Classes="ghost xsmall icon-only"><PathIcon Data="{StaticResource UIKit.Icon.ChevronLeft}" /></Button>
      <Button Classes="ghost xsmall icon-only"><PathIcon Data="{StaticResource UIKit.Icon.ChevronRight}" /></Button>
    </StackPanel>
  </uikit:Tabs.Prefix>
  <uikit:Tabs.Suffix>
    <StackPanel Orientation="Horizontal" Margin="4,0">
      <Button Classes="ghost xsmall icon-only"><PathIcon Data="{StaticResource UIKit.Icon.Inbox}" /></Button>
      <Button Classes="ghost xsmall icon-only"><PathIcon Data="{StaticResource UIKit.Icon.Ellipsis}" /></Button>
    </StackPanel>
  </uikit:Tabs.Suffix>
  <TabStripItem Content="Account" />
  <TabStripItem Content="Profile" />
  <TabStripItem Content="Settings" />
  <TabStripItem Content="Billing" />
  <TabStripItem Content="Notifications" IsEnabled="False" />
  <TabStripItem Content="Integrations" />
</TabStrip>

关闭、添加与拖拽

这些附加属性用于 TabStrip 或 TabControl。它们改变标签的来源列表:即 ItemsSource,必须是可变列表(例如 ObservableCollection),或者 Items。列表不可变的标签无法关闭或移动。

附加属性作用
uikit:Tabs.Closable每个标签中显示关闭按钮,与 GPUI Kit 的可关闭标签一致:标签内边距为 px_2,末尾是一个 ghost xsmall 的 Close 按钮。在标签条上设置时作用于每个标签;在标签上设置时作用于该标签。
uikit:Tabs.NewTabFactory在最后一个标签之后显示添加按钮。它把函数返回的项添加到末尾并选中它。
uikit:Tabs.Reorderable标签可沿标签条拖拽以重新排序:被拖拽的标签跟随指针,其他标签让出位置,放下后移动其项。被拖拽的标签带有 :dragging 伪类,并绘制在途经的标签之上:有指示器时带指示器,outline 与 underline 中则使用活动标签的背景。标签溢出时,若把标签按住不放,标签条会滚动。
uikit:Tabs.DragGroup配合 Reorderable,把标签拖到同组的另一条标签条上即可移入其中。不同窗口中的标签条可以交换标签;在浏览器中,只有同一视图内的标签条可以。
uikit:Tabs.DetachedWindowFactory配合 DragGroup,把标签拖离本组的所有标签条后,它会移入函数返回的窗口,该窗口跟随指针直到放下。仅在窗口中可用。

关闭按钮在移除标签之前会在标签条上引发 uikit:Tabs.TabClosing;设置 Cancel 可保留标签。关闭选中的标签会选中下一个。

一个可关闭的标签条:添加按钮会新建标签,标签可重新排序。最后一个标签无法关闭。

可关闭可交互
Live demo unavailable
<TabControl Name="Tabs" Width="480" HorizontalAlignment="Left"
            uikit:Tabs.Closable="True" uikit:Tabs.Reorderable="True"
            Loaded="OnLoaded">
  <TabItem Header="Account">
    <TextBlock Text="Make changes to your account here." Margin="0,12" />
  </TabItem>
  <TabItem Header="Profile">
    <TextBlock Text="Edit your public profile." Margin="0,12" />
  </TabItem>
  <TabItem Header="Settings">
    <TextBlock Text="Change your preferences." Margin="0,12" />
  </TabItem>
</TabControl>
Closable.axaml.cs
Tabs.SetNewTabFactory(tabs, () => new TabItem { Header = $"Tab {++added}", Content = new TextBlock { Text = "A new tab." } });
Tabs.AddTabClosingHandler(tabs, (_, args) => args.Cancel = tabs.ItemCount == 1);

通过拖拽重新排序标签。

重新排序可交互
Live demo unavailable
<TabStrip Classes="pill" SelectedIndex="0" uikit:Tabs.Reorderable="True">
  <TabStripItem Content="Account" />
  <TabStripItem Content="Profile" />
  <TabStripItem Content="Settings" />
  <TabStripItem Content="Billing" />
  <TabStripItem Content="Notifications" />
</TabStrip>

同一组的两个标签条:把一个标签从一侧拖到另一侧。

拖拽组可交互
Live demo unavailable
<StackPanel Spacing="16" HorizontalAlignment="Left">
  <TabStrip Width="360" SelectedIndex="0"
            uikit:Tabs.Reorderable="True" uikit:Tabs.DragGroup="files">
    <TabStripItem Content="index.html" />
    <TabStripItem Content="style.css" />
    <TabStripItem Content="app.js" />
  </TabStrip>
  <TabStrip Width="360" SelectedIndex="0"
            uikit:Tabs.Reorderable="True" uikit:Tabs.DragGroup="files">
    <TabStripItem Content="README.md" />
    <TabStripItem Content="LICENSE" />
  </TabStrip>
</StackPanel>

把标签拖出为窗口

uikit:Tabs.DetachedWindowFactory 接收被拖出标签的项,并返回它要移入的窗口。该窗口必须包含同组的 TabStrip 或 TabControl,为空且可重新排序;标签会被放入其中,窗口在指针下方显示并跟随指针。拖到同组的标签条上时,标签移回,窗口隐藏。以此方式创建的窗口在其最后一个标签被拖出或关闭时关闭;拖动其唯一的标签则会移动窗口本身。应用自行打开的窗口在标签条清空后仍保持打开。

MainWindow.axaml.cs
Tabs.SetDetachedWindowFactory(documents, _ => NewDocumentWindow());

static Window NewDocumentWindow()
{
    var tabs = new TabControl();
    Tabs.SetClosable(tabs, true);
    Tabs.SetReorderable(tabs, true);
    Tabs.SetDragGroup(tabs, "documents");
    Tabs.SetDetachedWindowFactory(tabs, _ => NewDocumentWindow());
    return new Window { Title = "Documents", Width = 640, Height = 400, Content = tabs };
}

页面没有窗口,因此该示例不会在实时演示中运行。