Xamarin.Forms TabbedPage

Download Sample 샘플 다운로드

탭 Xamarin.FormsTabbedPage 목록과 더 큰 세부 정보 영역으로 구성되며, 각 탭은 세부 정보 영역에 콘텐츠를 로드합니다. 다음 스크린샷은 iOS 및 Android의 TabbedPage를 보여줍니다.

Screenshot of a TabbedPage containing three tabs, on iOS and Android

iOS에서 탭 목록은 화면 맨 아래에 나타나고 세부 내용 영역이 위에 위치합니다. 각 탭은 제목과 아이콘으로 구성되며 알파 채널이 있는 PNG 파일이어야 합니다. 세로 방향에서는 탭 제목 위에 탭 모음 아이콘이 표시됩니다. 가로 방향에서는 아이콘 및 제목이 나란히 표시됩니다. 또한 디바이스 및 방향에 따라 일반 또는 작은 탭 표시줄이 표시될 수도 있습니다. 6개 이상의 탭이 있는 경우 다른 탭에 액세스하는 데 사용할 수 있는 자세히 탭이 표시됩니다.

Android에서는 탭 목록이 화면 맨 위에 표시되고 세부 정보 영역은 아래에 위치합니다. 각 탭은 제목과 아이콘으로 구성되며 알파 채널이 있는 PNG 파일이어야 합니다. 그러나 탭은 특정 플랫폼에서 화면 아래쪽으로 이동할 수 있습니다. 6개 이상의 탭이 있고 탭 목록이 화면 아래쪽에 있는 경우 추가 탭에 액세스하는 데 사용할 수 있는 자세히 탭이 나타납니다. 아이콘 요구 사항에 대한 자세한 내용은 material.io의 Tabs 및 developer.android.com의 다양한 픽셀 밀도 지원을 참조하세요. 화면 아래쪽으로 탭을 이동하는 방법에 대한 자세한 내용은 TabbedPage 도구 모음 배치 및 색 설정을 참조하세요.

UWP(유니버설 Windows 플랫폼)에서는 탭 목록이 화면 맨 위에 표시되고 세부 정보 영역은 아래에 표시됩니다. 각 탭은 제목으로 구성됩니다. 그러나 플랫폼별로 각 탭에 아이콘을 추가할 수 있습니다. 자세한 내용은 Windows의 TabbedPage 아이콘을 참조하세요.

SVG(스케일링 가능한 벡터 그래픽) 파일을 TabbedPage에서 탭 아이콘으로 표시할 수 있습니다.

  • iOS TabbedRenderer 클래스에는 지정된 소스에서 탭 아이콘을 로드하는 데 사용할 수 있는 재정의 가능한 GetIcon 메서드가 포함됩니다. 또한 필요한 경우 선택하거나 선택하지 않은 버전의 아이콘을 제공할 수 있습니다.
  • Android AppCompat TabbedPageRenderer 클래스에는 사용자 지정된 Drawable에서 탭 아이콘을 로드하는 데 사용할 수 있는 재정의 가능한 SetTabIconImageSource 메서드가 포함됩니다. 또는 SVG 파일을 Xamarin.Forms가 자동으로 표시할 수 있는 벡터 드로어블 리소스로 변환할 수 있습니다. SVG 파일을 벡터 드로어블 리소스로 변환하는 방법에 대한 자세한 내용은 developer.android.com에서 Add multi-density vector graphics(다중 밀도 벡터 그래픽 추가)를 참조하세요.

자세한 내용은 Xamarin.Forms TabbedPage with SVG tab icons(SVG 탭 아이콘이 있는 Xamarin.Forms TabbedPage)를 참조하세요.

TabbedPage 만들기

두 방법을 TabbedPage를 만드는 데 사용할 수 있습니다.

사용자가 각 탭을 선택하면 두 가지 방법으로 TabbedPage는 각 페이지를 표시합니다.

Important

TabbedPageNavigationPageContentPage 인스턴스만으로 채우는 것이 좋습니다. 이렇게 하면 모든 플랫폼에서 일관된 사용자 환경을 보장하는 데 도움이 됩니다.

또한 TabbedPage는 다음 속성을 정의합니다.

이 모든 속성은 BindableProperty 개체에서 지원되며, 이는 속성에 스타일을 지정할 수 있으며 속성이 데이터 바인딩의 대상이 될 수 있음을 의미합니다.

Warning

TabbedPage에서 각 Page 개체는 TabbedPage가 생성될 때 만들어집니다. 이로 인해 특히 TabbedPage가 애플리케이션의 루트 페이지인 경우 사용자 환경이 저하될 수 있습니다. 그러나 Xamarin.Forms Shell을 사용하면 탐색에 대한 응답으로 탭 표시줄을 통해 액세스되는 페이지를 요청에 따라 만들 수 있습니다. 자세한 내용은 Xamarin.Forms Shell을 참조하세요.

페이지 컬렉션으로 TabbedPage 채우기

TabbedPage를 자식 Page 개체 컬렉션(예: ContentPage 개체의 컬렉션)으로 채울 수 있습니다. 이렇게 하려면 Page 개체를 TabbedPage.Children 컬렉션에 추가합니다. 이 작업은 다음과 같이 XAML에서 수행합니다.

<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            xmlns:local="clr-namespace:TabbedPageWithNavigationPage;assembly=TabbedPageWithNavigationPage"
            x:Class="TabbedPageWithNavigationPage.MainPage">
    <local:TodayPage />
    <NavigationPage Title="Schedule" IconImageSource="schedule.png">
        <x:Arguments>
            <local:SchedulePage />
        </x:Arguments>
    </NavigationPage>
</TabbedPage>

참고 항목

TabbedPage가 파생되는 MultiPage<T> 클래스의 Children 속성은 MultiPage<T>ContentProperty입니다. 따라서 XAML에서 Children 속성에 Page 개체를 명시적으로 할당할 필요가 없습니다.

해당하는 C# 코드는 다음과 같습니다.

public class MainPageCS : TabbedPage
{
  public MainPageCS ()
  {
    NavigationPage navigationPage = new NavigationPage (new SchedulePageCS ());
    navigationPage.IconImageSource = "schedule.png";
    navigationPage.Title = "Schedule";

    Children.Add (new TodayPageCS ());
    Children.Add (navigationPage);
  }
}

이 예제에서 TabbedPage는 두 개의 Page 개체로 채워집니다. 첫 번째 자식은 ContentPage 개체이고 두 번째 자식은 ContentPage 개체를 포함하는 NavigationPage입니다.

다음 스크린샷에서는 TabbedPageContentPage 개체를 보여줍니다.

Screenshot of a TabbedPage containing three tabs, on iOS and Android

다른 탭을 선택하면 해당 탭을 나타내는 ContentPage 개체가 표시됩니다.

Screenshot of a TabbedPage containing tabs, on iOS and Android

일정 탭에서 ContentPage 개체가 NavigationPage 개체에 래핑됩니다.

Warning

NavigationPageTabbedPage에 배치할 수 있지만 TabbedPageNavigationPage에 배치하지 않는 것이 좋습니다. iOS의 경우 UITabBarController가 항상 UINavigationController에 대한 래퍼의 역할을 하기 때문입니다. 자세한 내용은 iOS 개발자 라이브러리에서 결합된 보기 컨트롤러 인터페이스를 참조하세요.

ContentPage 개체가 NavigationPage 개체에 래핑된 경우 탭 내 탐색을 수행할 수 있습니다. 이렇게 하려면 ContentPage 개체의 Navigation 속성에서 PushAsync 메서드를 호출합니다.

await Navigation.PushAsync (new UpcomingAppointmentsPage ());

탐색하는 페이지는 PushAsync 메서드에 대한 인수로 지정됩니다. 이 예제에서는 UpcomingAppointmentsPage 페이지가 탐색 스택으로 푸시되어 활성 페이지가 됩니다.

Screenshot of navigation within a tab, on iOS and Android

NavigationPage 클래스를 사용하는 검색을 수행하는 방법에 대한 자세한 내용은 계층적 검색을 참조하세요.

템플릿으로 TabbedPage 채우기

ItemsSource 속성에 데이터 컬렉션을 할당하고 데이터를 Page 개체로 템플릿화하는 ItemTemplate 속성에 DataTemplate을 할당하여 TabbedPage를 페이지로 채울 수 있습니다. 이 작업은 다음과 같이 XAML에서 수행합니다.

<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:TabbedPageDemo;assembly=TabbedPageDemo"
            x:Class="TabbedPageDemo.TabbedPageDemoPage"
            ItemsSource="{x:Static local:MonkeyDataModel.All}">            
  <TabbedPage.Resources>
    <ResourceDictionary>
      <local:NonNullToBooleanConverter x:Key="booleanConverter" />
    </ResourceDictionary>
  </TabbedPage.Resources>
  <TabbedPage.ItemTemplate>
    <DataTemplate>
      <ContentPage Title="{Binding Name}" IconImageSource="monkeyicon.png">
        <StackLayout Padding="5, 25">
          <Label Text="{Binding Name}" Font="Bold,Large" HorizontalOptions="Center" />
          <Image Source="{Binding PhotoUrl}" WidthRequest="200" HeightRequest="200" />
          <StackLayout Padding="50, 10">
            <StackLayout Orientation="Horizontal">
              <Label Text="Family:" HorizontalOptions="FillAndExpand" />
              <Label Text="{Binding Family}" Font="Bold,Medium" />
            </StackLayout>
            ...
          </StackLayout>
        </StackLayout>
      </ContentPage>
    </DataTemplate>
  </TabbedPage.ItemTemplate>
</TabbedPage>

해당하는 C# 코드는 다음과 같습니다.

public class TabbedPageDemoPageCS : TabbedPage
{
  public TabbedPageDemoPageCS ()
  {
    var booleanConverter = new NonNullToBooleanConverter ();

    ItemTemplate = new DataTemplate (() =>
    {
      var nameLabel = new Label
      {
        FontSize = Device.GetNamedSize (NamedSize.Large, typeof(Label)),
        FontAttributes = FontAttributes.Bold,
        HorizontalOptions = LayoutOptions.Center
      };
      nameLabel.SetBinding (Label.TextProperty, "Name");

      var image = new Image { WidthRequest = 200, HeightRequest = 200 };
      image.SetBinding (Image.SourceProperty, "PhotoUrl");

      var familyLabel = new Label
      {
        FontSize = Device.GetNamedSize (NamedSize.Medium, typeof(Label)),
        FontAttributes = FontAttributes.Bold
      };
      familyLabel.SetBinding (Label.TextProperty, "Family");
      ...

      var contentPage = new ContentPage
      {
        IconImageSource = "monkeyicon.png",
        Content = new StackLayout {
          Padding = new Thickness (5, 25),
          Children =
          {
            nameLabel,
            image,
            new StackLayout
            {
              Padding = new Thickness (50, 10),
              Children =
              {
                new StackLayout
                {
                  Orientation = StackOrientation.Horizontal,
                  Children =
                  {
                    new Label { Text = "Family:", HorizontalOptions = LayoutOptions.FillAndExpand },
                    familyLabel
                  }
                },
                // ...
              }
            }
          }
        }
      };
      contentPage.SetBinding (TitleProperty, "Name");
      return contentPage;
    });
    ItemsSource = MonkeyDataModel.All;
  }
}

이 예제에서 각 탭은 ImageLabel 개체를 사용하여 탭의 데이터를 표시하는 ContentPage 개체로 구성됩니다.

Screenshot of a templated TabbedPage, on iOS and Android

다른 탭을 선택하면 해당 탭을 나타내는 ContentPage 개체가 표시됩니다.