다음을 통해 공유


Xamarin.Forms FlyoutPage

플라이아웃 페이지는 일반적으로 다음 스크린샷과 같이 항목 목록을 표시합니다.

플라이아웃 페이지 구성 요소

항목 목록의 위치는 각 플랫폼에서 동일하며, 항목 중 하나를 선택하면 해당 세부 정보 페이지로 이동합니다. 또한 플라이아웃 페이지에는 활성 세부 정보 페이지로 이동하는 데 사용할 수 있는 단추가 포함된 탐색 모음이 있습니다.

  • iOS의 경우 탐색 모음이 페이지의 위쪽에 있으며, 여기에는 세부 정보 페이지로 이동하는 단추가 있습니다. 또한 플라이아웃을 왼쪽으로 살짝 밀어 활성 세부 정보 페이지로 이동할 수 있습니다.
  • Android의 경우 탐색 모음이 페이지의 위쪽에 있으며, 여기에는 제목, 아이콘 및 세부 정보 페이지로 이동하는 단추가 표시됩니다. 아이콘은 Android 플랫폼 관련 프로젝트의 MainActivity 클래스를 데코레이팅하는 [Activity] 특성에 정의됩니다. 플라이아웃 페이지를 왼쪽으로 살짝 밀거나, 화면의 오른쪽 끝에 있는 세부 정보 페이지를 탭하거나, 화면의 아래쪽에 있는 ‘뒤로’ 단추를 탭하여 활성 세부 정보 페이지로 이동할 수도 있습니다.
  • UWP(유니버설 Windows 플랫폼)의 경우 탐색 모음이 페이지의 위쪽에 있으며, 여기에는 세부 정보 페이지로 이동하는 단추가 있습니다.

세부 정보 페이지에는 플라이아웃 페이지에서 선택한 항목에 해당하는 데이터가 표시됩니다. 다음 스크린샷에는 세부 정보 페이지의 주요 구성 요소가 나와 있습니다.

세부 정보 페이지 구성 요소

세부 정보 페이지에는 콘텐츠가 플랫폼에 따라 달라지는 탐색 모음이 있습니다.

  • iOS의 경우 탐색 모음이 페이지의 위쪽에 있으며, 여기에는 제목이 표시되고, 세부 정보 페이지 인스턴스가 NavigationPage 인스턴스에 래핑된 경우 플라이아웃 페이지로 돌아가는 단추가 있습니다. 세부 정보 페이지를 오른쪽으로 살짝 밀어서 플라이아웃 페이지로 돌아갈 수도 있습니다.
  • Android의 경우 탐색 모음이 페이지의 위쪽에 있으며, 여기에는 제목, 아이콘 및 플라이아웃 페이지로 돌아가는 단추가 표시됩니다. 아이콘은 Android 플랫폼 관련 프로젝트의 MainActivity 클래스를 데코레이팅하는 [Activity] 특성에 정의됩니다.
  • UWP의 경우 탐색 모음이 페이지의 위쪽에 있으며, 여기에는 제목이 표시되고, 플라이아웃 페이지로 돌아가는 단추가 있습니다.

플라이아웃 페이지와 세부 정보 페이지 간의 탐색 동작은 플랫폼에 따라 다릅니다.

  • iOS의 경우 플라이아웃 페이지를 왼쪽에서 밀면 세부 정보 페이지가 오른쪽으로 ‘밀리고’ 세부 정보 페이지의 왼쪽 부분이 계속 표시됩니다.
  • Android의 경우 세부 정보 페이지와 플라이아웃 페이지가 서로 ‘겹쳐집니다’.
  • UWP의 경우 플라이아웃 페이지는 FlyoutLayoutBehavior 속성이 Popover로 설정된 경우 세부 정보 페이지의 남은 부분에서 슬라이드됩니다.

iOS와 Android의 플라이아웃 페이지가 세로 모드의 플라이아웃 페이지와 비슷한 너비를 갖고 있으므로 더 많은 세부 페이지가 표시된다는 점을 제외하고는 가로 모드에서도 이와 비슷한 동작이 관찰됩니다.

탐색 동작을 제어하는 방법에 대한 자세한 내용은 세부 정보 페이지 레이아웃 동작 제어를 참조하세요.

FlyoutPage 만들기

FlyoutPage는 각각 플라이아웃 페이지와 세부 정보 페이지를 가져오고 설정하는 데 사용되는 Page 형식의 FlyoutDetail 속성을 포함합니다.

Important

FlyoutPage는 루트 페이지로 설계되었으며, 이 페이지를 다른 페이지 형식의 자식 페이지로 사용하면 예기치 않고 일관되지 않은 동작이 발생할 수 있습니다. 또한 FlyoutPage의 플라이아웃 페이지는 항상 ContentPage 인스턴스여야 하며 세부 정보 페이지는 TabbedPage, NavigationPageContentPage 인스턴스로 채우는 것이 좋습니다. 이렇게 하면 모든 플랫폼에서 일관된 사용자 환경을 보장하는 데 도움이 됩니다.

다음 XAML 코드 예제에서는 FlyoutDetail 속성을 설정하는 FlyoutPage를 보여 줍니다.

<FlyoutPage xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            xmlns:local="clr-namespace:FlyoutPageNavigation;assembly=FlyoutPageNavigation"
            x:Class="FlyoutPageNavigation.MainPage">
    <FlyoutPage.Flyout>
        <local:FlyoutMenuPage x:Name="flyoutPage" />
    </FlyoutPage.Flyout>
    <FlyoutPage.Detail>
        <NavigationPage>
            <x:Arguments>
                <local:ContactsPage />
            </x:Arguments>
        </NavigationPage>
    </FlyoutPage.Detail>
</FlyoutPage>

다음 코드 예제에서는 C#에서 만든 해당 FlyoutPage를 보여줍니다.

public class MainPageCS : FlyoutPage
{
    FlyoutMenuPageCS flyoutPage;

    public MainPageCS()
    {
        flyoutPage = new FlyoutMenuPageCS();
        Flyout = flyoutPage;
        Detail = new NavigationPage(new ContactsPageCS());
        ...
    }
    ...
}    

Flyout 속성이 ContentPage 인스턴스로 설정됩니다. Detail 속성이 ContentPage 인스턴스가 포함된 NavigationPage로 설정됩니다.

플라이아웃 페이지 만들기

다음 XAML 코드 예제에서는 Flyout 속성을 통해 참조되는 FlyoutMenuPage 개체의 선언을 보여 줍니다.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="using:FlyoutPageNavigation"
             x:Class="FlyoutPageNavigation.FlyoutMenuPage"
             Padding="0,40,0,0"
             IconImageSource="hamburger.png"
             Title="Personal Organiser">
    <StackLayout>
        <ListView x:Name="listView" x:FieldModifier="public">
            <ListView.ItemsSource>
                <x:Array Type="{x:Type local:FlyoutPageItem}">
                    <local:FlyoutPageItem Title="Contacts" IconSource="contacts.png" TargetType="{x:Type local:ContactsPage}" />
                    <local:FlyoutPageItem Title="TodoList" IconSource="todo.png" TargetType="{x:Type local:TodoListPage}" />
                    <local:FlyoutPageItem Title="Reminders" IconSource="reminders.png" TargetType="{x:Type local:ReminderPage}" />
                </x:Array>
            </ListView.ItemsSource>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid Padding="5,10">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="30"/>
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>
                            <Image Source="{Binding IconSource}" />
                            <Label Grid.Column="1" Text="{Binding Title}" />
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

이 페이지는 해당 ItemsSource 속성을 FlyoutPageItem 개체의 배열로 설정하여 XAML 형식 데이터로 채워지는 ListView로 구성됩니다. 각 FlyoutPageItemTitle, IconSourceTargetType 속성을 정의합니다.

DataTemplate은 각각의 FlyoutPageItem을 표시하기 위해 ListView.ItemTemplate 속성에 할당됩니다. DataTemplate에는 ImageLabel로 구성된 ViewCell이 포함됩니다. Image에는 IconSource 속성 값이 표시되고, Label에는 각 FlyoutPageItem에 대한 Title 속성 값이 표시됩니다.

이 페이지에는 해당 TitleIconImageSource 속성이 설정되어 있습니다. 세부 정보 페이지에 제목 표시줄이 있으면 아이콘이 세부 정보 페이지에 표시됩니다. 세부 정보 페이지 인스턴스를 NavigationPage 인스턴스에 래핑하여 iOS에서 이를 활성화해야 합니다.

참고 항목

Flyout 페이지에는 해당 Title 속성이 설정되어 있어야 하며, 그렇지 않으면 예외가 발생합니다.

다음 코드 예제에서는 C#에서 만든 해당 페이지를 보여 줍니다.

public class FlyoutMenuPageCS : ContentPage
{
    ListView listView;
    public ListView ListView { get { return listView; } }

    public FlyoutMenuPageCS()
    {
        var flyoutPageItems = new List<FlyoutPageItem>();
        flyoutPageItems.Add(new FlyoutPageItem
        {
            Title = "Contacts",
            IconSource = "contacts.png",
            TargetType = typeof(ContactsPageCS)
        });
        flyoutPageItems.Add(new FlyoutPageItem
        {
            Title = "TodoList",
            IconSource = "todo.png",
            TargetType = typeof(TodoListPageCS)
        });
        flyoutPageItems.Add(new FlyoutPageItem
        {
            Title = "Reminders",
            IconSource = "reminders.png",
            TargetType = typeof(ReminderPageCS)
        });

        listView = new ListView
        {
            ItemsSource = flyoutPageItems,
            ItemTemplate = new DataTemplate(() =>
            {
                var grid = new Grid { Padding = new Thickness(5, 10) };
                grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(30) });
                grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Star });

                var image = new Image();
                image.SetBinding(Image.SourceProperty, "IconSource");
                var label = new Label { VerticalOptions = LayoutOptions.FillAndExpand };
                label.SetBinding(Label.TextProperty, "Title");

                grid.Children.Add(image);
                grid.Children.Add(label, 1, 0);

                return new ViewCell { View = grid };
            }),
            SeparatorVisibility = SeparatorVisibility.None
        };

        IconImageSource = "hamburger.png";
        Title = "Personal Organiser";
        Padding = new Thickness(0, 40, 0, 0);
        Content = new StackLayout
        {
            Children = { listView }
        };
    }
}

다음 스크린샷에서는 각 플랫폼의 플라이아웃 페이지를 보여 줍니다.

플라이아웃 페이지 예제

세부 정보 페이지 만들기 및 표시

MainPageFlyoutPage 인스턴스에서 ItemSelected 이벤트를 처리할 이벤트 처리기를 등록할 수 있도록 FlyoutMenuPage 인스턴스에는 해당 ListView 인스턴스를 공개하는 ListView 속성이 포함됩니다. 이렇게 하면 MainPage 인스턴스에서 Detail 속성을 선택한 ListView 항목을 나타내는 페이지로 설정할 수 있습니다. 다음 코드 예제에서는 이벤트 처리기를 보여 줍니다.

public partial class MainPage : FlyoutPage
{
    public MainPage()
    {
        ...
        flyoutPage.listView.ItemSelected += OnItemSelected;
    }

    void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
        var item = e.SelectedItem as FlyoutPageItem;
        if (item != null)
        {
            Detail = new NavigationPage((Page)Activator.CreateInstance(item.TargetType));
            flyoutPage.listView.SelectedItem = null;
            IsPresented = false;
        }
    }
}

OnItemSelected 메서드에서 수행하는 작업은 다음과 같습니다.

  • ListView 인스턴스에서 SelectedItem을 검색하여 null이 아닌 경우 세부 정보 페이지를 FlyoutPageItemTargetType 속성에 저장된 페이지 형식의 새 인스턴스로 설정합니다. FlyoutMenuPageIconImageSource 속성을 통해 참조된 아이콘이 iOS의 세부 정보 페이지에 표시되도록 페이지 형식이 NavigationPage 인스턴스에 래핑됩니다.
  • 다음에 FlyoutMenuPage가 표시되면 ListView 항목이 선택되지 않도록 ListView에서 선택한 항목이 null로 설정됩니다.
  • 세부 정보 페이지는 FlyoutPage.IsPresented 속성을 false로 설정하여 사용자에게 표시됩니다. 이 속성은 플라이아웃 페이지 또는 세부 정보 페이지의 표시 여부를 제어합니다. 플라이아웃 페이지를 표시하려면 true로 설정하고, 세부 정보 페이지를 표시하려면 false로 설정해야 합니다.

다음 스크린샷에서는 플라이아웃 페이지에서 선택된 후 표시된 ContactPage 세부 정보 페이지를 보여 줍니다.

세부 정보 페이지 예제

세부 정보 페이지 레이아웃 동작 제어

FlyoutPage에서 플라이아웃 페이지 및 세부 정보 페이지를 관리하는 방법은 애플리케이션이 휴대폰 또는 태블릿에서 어느 것에서 실행 중인지와 디바이스의 방향 및 FlyoutLayoutBehavior 속성의 값에 따라 달라집니다. 이 속성은 세부 정보 페이지를 표시하는 방법을 결정합니다. 가능한 값은 다음과 같습니다.

  • Default – 페이지가 플랫폼 기본값을 사용하여 표시됩니다.
  • Popover – 세부 정보 페이지가 플라이아웃 페이지 전체 또는 일부분을 가립니다.
  • Split – 플라이아웃 페이지는 왼쪽에 표시되고 세부 정보 페이지는 오른쪽에 표시됩니다.
  • SplitOnLandscape – 디바이스가 가로 방향일 때 분할 화면이 사용됩니다.
  • SplitOnPortrait – 디바이스가 세로 방향일 때 분할 화면이 사용됩니다.

다음 XAML 코드 예제에서는 FlyoutLayoutBehavior 속성을 FlyoutPage에 설정하는 방법을 보여 줍니다.

<FlyoutPage xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            x:Class="FlyoutPageNavigation.MainPage"
            FlyoutLayoutBehavior="Popover">
  ...
</FlyoutPage>

다음 코드 예제에서는 C#에서 만든 해당 FlyoutPage를 보여줍니다.

public class MainPageCS : FlyoutPage
{
    FlyoutMenuPageCS flyoutPage;

    public MainPageCS()
    {
        ...
        FlyoutLayoutBehavior = FlyoutLayoutBehavior.Popover;
    }
}

Important

FlyoutLayoutBehavior 속성의 값은 태블릿 또는 데스크톱에서 실행되는 애플리케이션에만 영향을 줍니다. 휴대폰에서 실행되는 애플리케이션에는 항상 동작이 있습니다 Popover .