사용자 지정 비디오 전송 컨트롤 만들기

MediaPlayerElement에는 Windows 앱 내에서 오디오와 비디오 콘텐츠의 컨트롤을 관리하기 위해 사용자 지정 가능한 XAML 전송 컨트롤이 있습니다. 여기서는 MediaTransportControls 템플릿을 사용자 지정하는 방법을 보여 줍니다. 오버플로 메뉴에 대한 작업을 수행하고 사용자 지정 단추를 추가하며 슬라이더를 수정하는 방법을 살펴보겠습니다.

중요 APIs: MediaPlayerElement, MediaPlayerElement.AreTransportControlsEnabled, MediaTransportControls

시작하기 전에, MediaPlayerElement 및 MediaTransportControls 클래스에 대해 잘 알고 있어야 합니다. 자세한 내용은 MediaPlayerElement 컨트롤 가이드를 참조하세요.

이 항목의 예제는 미디어 전송 컨트롤 샘플을 기반으로 합니다. 샘플을 다운로드하여 완료된 코드를 보고 실행할 수 있습니다.

참고 항목

MediaPlayerElement 는 Windows 10 버전 1607 및 이상 버전에서만 사용 가능합니다. 이전 버전의 Windows 10 전용 앱을 개발하는 경우 MediaElement 를 대신 사용합니다. 이 페이지의 모든 예제는 MediaElement 에서도 작동합니다.

템플릿을 언제 사용자 지정해야 하나요?

MediaPlayerElement 에는 대부분의 비디오 및 오디오 재생 앱에서 수정 없이 잘 작동하도록 설계된 빌트인 전송 컨트롤이 있습니다. 이 컨트롤은 MediaTransportControls 클래스에서 제공하며 미디어 재생, 중지, 탐색 단추를 비롯하여, 볼륨 조정, 전체 화면으로 전환, 두 번째 디바이스로 캐스팅, 자막 사용, 오디오 트랙 전환 및 재생 속도 조정을 처리하는 단추를 포함합니다. MediaTransportControls에는 각 버튼이 표시되고 활성화되는지 여부를 제어할 수 있는 속성이 있습니다. 또한 IsCompact 속성을 설정하여 컨트롤이 한 행 또는 두 행에 표시되는지 여부를 지정할 수 있습니다.

그러나 컨트롤의 모양을 추가로 사용자 지정하거나 동작을 변경해야 하는 시나리오가 있을 수 있습니다. 다음 몇 가지 예를 참조하세요.

  • 아이콘, 슬라이더 동작 및 색을 변경합니다.
  • 사용 빈도가 적은 명령 버튼을 오버플로 메뉴로 옮깁니다.
  • 컨트롤의 크기를 조정할 때 명령이 삭제되는 순서를 변경합니다.
  • 기본 집합에 없는 명령 단추를 제공합니다.

참고 항목

화면에 공간이 충분하지 않은 경우 미리 정의된 순서대로 화면에 표시되는 버튼을 기본 제공 전송 컨트롤에서 삭제합니다. 순서를 변경하거나 오버플로 메뉴에 맞지 않는 명령을 배치하려면 컨트롤을 사용자 지정해야 합니다.

기본 템플릿을 수정하여 컨트롤의 모양을 사용자 지정할 수 있습니다. 컨트롤의 동작을 수정하거나 새 명령을 추가하려면 MediaTransportControls에서 파생된 사용자 지정 컨트롤을 만듭니다.

사용자 지정 가능한 컨트롤 템플릿은 XAML 플랫폼에서 제공하는 강력한 기능이지만 고려해야 할 점도 있습니다. 템플릿을 사용자 지정하면, 앱의 정적 부분이 되므로 Microsoft에서 템플릿에 대한 플랫폼 업데이트를 받지 못합니다. Microsoft에서 템플릿 업데이트를 수행하는 경우, 새 템플릿을 가져와 다시 수정해야 템플릿 업데이트로 얻을 수 있는 이점을 가질 수 있습니다.

템플릿 구조

ControlTemplate 은 기본 스타일의 일부입니다. 기본 스타일을 프로젝트에 복사하여 수정할 수 있습니다. ControlTemplate은 다른 XAML 컨트롤 템플릿과 유사한 섹션으로 나뉩니다.

  • 템플릿의 첫 번째 섹션에는 MediaTransportControls의 다양한 구성 요소를 위한 Style 정의가 포함되어 있습니다.
  • 두 번째 섹션에서는 MediaTransportControls에서 사용하는 다양한 시각적 상태를 정의합니다.
  • 세 번째 섹션에는 다양한 MediaTransportControls 요소를 함께 보관하고 구성 요소가 배치되는 방법을 정의하는 Grid 가 포함되어 있습니다.

참고 항목

템플릿 수정에 대한 자세한 내용은 컨트롤 템플릿을 참조하세요. 텍스트 편집기 또는 IDE의 유사한 편집기를 사용하여 (Program Files)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\(SDK version)\Generic에 있는 XAML 파일을 열 수 있습니다. 각 컨트롤의 기본 스타일 및 템플릿은 generic.xaml 파일에 정의되어 있습니다. "MediaTransportControls"를 검색하여 generic.xaml에서 MediaTransportControls 템플릿을 찾을 수 있습니다.

다음 섹션에서는 전송 컨트롤의 몇몇 기본 요소를 사용자 지정하는 방법을 알아봅니다.

  • Slider: 사용자는 이 요소를 통해 미디어를 삭제할 수 있으며, 이 요소는 진행률도 표시합니다.
  • CommandBar: 모든 단추를 포함합니다. 자세한 내용은 MediaTransportControls 참조 항목의 분석 섹션을 참조하세요.

전송 컨트롤 사용자 지정

MediaTransportControls의 모양만 수정하려는 경우, 기본 컨트롤 스타일 및 템플릿의 복사본을 만들어 수정할 수 있습니다. 그러나 컨트롤의 기능을 추가하거나 수정하려는 경우 MediaTransportControls에서 파생되는 새 클래스를 만들어야 합니다.

컨트롤 다시 템플릿 지정

MediaTransportControls 기본 스타일 및 템플릿을 사용자 지정하려면

  1. MediaTransportControls 스타일 및 템플릿의 기본 스타일을 프로젝트의 ResourceDictionary에 복사합니다.
  2. 다음과 같이 스타일에 x:Key 값을 지정하여 식별합니다.
<Style TargetType="MediaTransportControls" x:Key="myTransportControlsStyle">
    <!-- Style content ... -->
</Style>
  1. MediaTransportControls를 사용하여 UI에 MediaPlayerElement를 추가합니다.
  2. 여기에 나온 것처럼, MediaTransportControls 요소의 Style 속성을 사용자 지정 Style 리소스로 설정합니다.
<MediaPlayerElement AreTransportControlsEnabled="True">
    <MediaPlayerElement.TransportControls>
        <MediaTransportControls Style="{StaticResource myTransportControlsStyle}"/>
    </MediaPlayerElement.TransportControls>
</MediaPlayerElement>

스타일 및 템플릿 수정에 대한 자세한 내용은 스타일 지정 컨트롤컨트롤 템플릿을 참조하세요.

파생 컨트롤 만들기

전송 컨트롤의 기능을 추가하거나 수정하려면 MediaTransportControls에서 파생된 새 클래스를 만들어야 합니다. 호출된 CustomMediaTransportControls 파생 클래스는 Media Transport Controls 샘플 및 이 페이지에 있는 기존 예제에서 볼 수 있습니다.

MediaTransportControls에서 파생된 새 클래스를 만들려면

  1. 새 클래스 파일을 프로젝트에 추가합니다.
    • Visual Studio에서 프로젝트 > 클래스 추가를 선택합니다. 새 항목 추가 대화 상자가 열립니다.
    • 새 항목 추가 대화 상자에서, 클래스 파일의 이름을 입력한 후 추가를 클릭합니다. (Media Transport Controls 샘플에서 클래스 이름을 CustomMediaTransportControls라고 지정합니다.)
  2. MediaTransportControls 클래스에서 파생한 클래스 코드를 수정합니다.
public sealed class CustomMediaTransportControls : MediaTransportControls
{
}
  1. MediaTransportControls 에 대한 기본 스타일을 프로젝트의 ResourceDictionary 에 복사합니다. 이 스타일 및 템플릿을 수정합니다. (미디어 전송 컨트롤 샘플에서 "테마"라는 새 폴더를 만들고 generic.xaml이라는 ResourceDictionary 파일을 폴더에 추가합니다.)
  2. 새 사용자 지정 컨트롤 형식으로 스타일의 TargetType 를 변경합니다. (샘플에서 TargetType은 local:CustomMediaTransportControls로 변경됩니다.)
xmlns:local="using:CustomMediaTransportControls">
...
<Style TargetType="local:CustomMediaTransportControls">
  1. 사용자 지정 클래스의 DefaultStyleKey 를 설정합니다. 이렇게 하여 local:CustomMediaTransportControls의 TargetType이 있는 Style을 사용하도록 사용자 지정 클래스에 지시합니다.
public sealed class CustomMediaTransportControls : MediaTransportControls
{
    public CustomMediaTransportControls()
    {
        this.DefaultStyleKey = typeof(CustomMediaTransportControls);
    }
}
  1. XAML 태그에 MediaPlayerElement 를 추가하고 사용자 지정 전송 컨트롤을 추가합니다. 한 가지 주의해야 할 점은 기본 버튼을 숨기고, 표시하고, 비활성화 및 활성화하는 API가 사용자 지정된 템플릿에서 계속 작동한다는 것입니다.
<MediaPlayerElement Name="MediaPlayerElement1" AreTransportControlsEnabled="True" Source="video.mp4">
    <MediaPlayerElement.TransportControls>
        <local:CustomMediaTransportControls x:Name="customMTC"
                                            IsFastForwardButtonVisible="True"
                                            IsFastForwardEnabled="True"
                                            IsFastRewindButtonVisible="True"
                                            IsFastRewindEnabled="True"
                                            IsPlaybackRateButtonVisible="True"
                                            IsPlaybackRateEnabled="True"
                                            IsCompact="False">
        </local:CustomMediaTransportControls>
    </MediaPlayerElement.TransportControls>
</MediaPlayerElement>

이제 컨트롤 스타일 및 템플릿을 수정하여 사용자 지정 컨트롤의 모양을 업데이트하고 컨트롤 코드를 수정하여 동작을 업데이트할 수 있습니다.

오버플로 메뉴 작업

MediaTransportControls 명령 버튼을 오버플로 메뉴로 이동시켜 사용 빈도가 적은 명령을 사용자가 필요로 할 때까지 보이지 않도록 할 수 있습니다.

MediaTransportControls 템플릿에서, 명령 버튼은 CommandBar 요소에 포함됩니다. 명령 모음에는 기본 명령 및 보조 명령의 개념이 있습니다. 기본 명령이란 (버튼을 비활성화하거나 단추를 숨기거나, 혹은 공간이 충분하지 않은 경우를 제외하면) 기본적으로 컨트롤에 표시되고 항상 보이는 버튼입니다. 보조 명령은 사용자가 줄임표(...) 단추를 클릭하면 나타나는 오버플로 메뉴에 보입니다. 자세한 내용은 앱 바 및 명령 모음 문서를 참조하세요.

명령 모음 기본 명령에서 오버플로 메뉴로 요소를 옮기려면, XAML 컨트롤 템플릿을 편집해야 합니다.

오버플로 메뉴로 명령을 이동하려면 다음을 수행합니다.

  1. 컨트롤 템플릿에서, 이름이 MediaControlsCommandBar 인 CommandBar 요소를 찾습니다.
  2. CommandBar의 XAML로 SecondaryCommands 섹션을 추가합니다. 위치는 PrimaryCommands의 닫는 태그 뒤에 입니다.
<CommandBar x:Name="MediaControlsCommandBar" ... >  
  <CommandBar.PrimaryCommands>
...
    <AppBarButton x:Name='PlaybackRateButton'
                    Style='{StaticResource AppBarButtonStyle}'
                    MediaTransportControlsHelper.DropoutOrder='4'
                    Visibility='Collapsed'>
      <AppBarButton.Icon>
        <FontIcon Glyph="&#xEC57;"/>
      </AppBarButton.Icon>
    </AppBarButton>
...
  </CommandBar.PrimaryCommands>
<!-- Add secondary commands (overflow menu) here -->
  <CommandBar.SecondaryCommands>
    ...
  </CommandBar.SecondaryCommands>
</CommandBar>
  1. 메뉴를 명령으로 채우려면, 원하는 AppBarButton 객체의 XAML을 잘라내어 PrimaryCommands에서 SecondaryCommands로 붙여 넣습니다. 이 예제에서는 PlaybackRateButton 를 오버플로 메뉴로 이동합니다.

  2. 버튼에 레이블을 추가하고 여기에 표시된 대로 스타일 정보를 제거합니다. 오버플로 메뉴는 텍스트 버튼으로 구성되므로, 버튼에 텍스트 레이블을 추가하고 버튼의 높이와 너비를 설정하는 스타일도 제거해야 합니다. 그렇지 않으면, 오버플로 메뉴에 올바르게 표시되지 않습니다.

<CommandBar.SecondaryCommands>
    <AppBarButton x:Name='PlaybackRateButton'
                  Label='Playback Rate'>
    </AppBarButton>
</CommandBar.SecondaryCommands>

Important

오버플로 메뉴에서 사용하려면 버튼이 계속 보이게 설정하고 활성화해야 합니다. 이 예제에서는, IsPlaybackRateButtonVisible 속성이 true가 아니면 PlaybackRateButton 요소가 오버플로 메뉴에 표시되지 않습니다. IsPlaybackRateEnabled 속성이 true가 아니면 활성화되지 않습니다. 이전 섹션에서 해당 속성 설정에 대해 나와 있습니다.

사용자 지정 버튼 추가

MediaTransportControls를 사용자 지정하려는 이유로 컨트롤에 사용자 지정 명령을 추가하기 위함을 들 수 있습니다. 명령 버튼 만들고 동작을 수정하는 절차는 추가를 기본 명령과 보조 명령 중 무엇으로 하든 관계 없이 동일합니다. 이 미디어 전송 컨트롤 샘플에서 "등급" 버튼이 기본 명령에 추가됩니다.

사용자 지정 명령 단추를 추가하려면

  1. AppBarButton 객체를 만들고 컨트롤 템플릿의 CommandBar에 추가합니다.
<AppBarButton x:Name="LikeButton"
              Icon="Like"
              Style="{StaticResource AppBarButtonStyle}"
              MediaTransportControlsHelper.DropoutOrder="3"
              VerticalAlignment="Center" />

적절한 위치의 명령 모음에 추가해야 합니다. (자세한 내용은 오버플로 메뉴 작업 섹션을 참조하세요.) UI의 위치는 버튼이 태그의 어느 위치에 있느냐에 따라 결정됩니다. 예를 들어 이 단추를 기본 명령의 마지막 요소로 표시하려면 이 단추를 기본 명령 목록의 맨 끝에 추가합니다.

단추 아이콘을 사용자 지정할 수도 있습니다. 자세한 내용은 AppBarButton 참조에서 확인할 수 있습니다.

  1. OnApplyTemplate 재정의에서, 템플릿으로부터 버튼을 가져와 Click 이벤트에 대한 처리기를 등록합니다. 이 코드는 CustomMediaTransportControls 클래스에서 진행합니다.
public sealed class CustomMediaTransportControls :  MediaTransportControls
{
    // ...

    protected override void OnApplyTemplate()
    {
        // Find the custom button and create an event handler for its Click event.
        var likeButton = GetTemplateChild("LikeButton") as Button;
        likeButton.Click += LikeButton_Click;
        base.OnApplyTemplate();
    }

    //...
}
  1. Click 이벤트 처리기에 코드를 추가하여 버튼을 클릭하면 발생하는 작업을 수행합니다. 다음은 클래스에 대한 전체 코드입니다.
public sealed class CustomMediaTransportControls : MediaTransportControls
{
    public event EventHandler< EventArgs> Liked;

    public CustomMediaTransportControls()
    {
        this.DefaultStyleKey = typeof(CustomMediaTransportControls);
    }

    protected override void OnApplyTemplate()
    {
        // Find the custom button and create an event handler for its Click event.
        var likeButton = GetTemplateChild("LikeButton") as Button;
        likeButton.Click += LikeButton_Click;
        base.OnApplyTemplate();
    }

    private void LikeButton_Click(object sender, RoutedEventArgs e)
    {
        // Raise an event on the custom control when 'like' is clicked.
        var handler = Liked;
        if (handler != null)
        {
            handler(this, EventArgs.Empty);
        }
    }
}

슬라이더 수정

MediaTransportControls의 "seek" 컨트롤은 Slider 요소에서 제공됩니다. 사용자 지정할 수 있는 방법으로 검색 동작의 세분성을 변경하는 것이 있습니다.

기본 검색 슬라이더는 100가지 부분으로 나뉘므로, 검색 동작은 여러 개 섹션으로 제한됩니다. 검색 슬라이더의 세분성을 변경하려면 MediaOpened 이벤트 처리기가 있는 MediaPlayerElement.MediaPlayer에서, 해당 이벤트 처리기의 XAML 시각적 트리로부터 슬라이더를 가져오면 됩니다. 이 예제에서는 VisualTreeHelper 를 사용하여 슬라이더에 대한 참조를 얻고, 미디어가 120분 보다 긴 경우 슬라이더의 기본 단계 빈도를 1%에서 0.1% (1000 steps)로 변경하는 방법을 보여 줍니다. MediaPlayerElement의 이름을 MediaPlayerElement1라고 지정합니다.

protected override void OnNavigatedTo(NavigationEventArgs e)
{
  MediaPlayerElement1.MediaPlayer.MediaOpened += MediaPlayerElement_MediaPlayer_MediaOpened;
  base.OnNavigatedTo(e);
}

private void MediaPlayerElement_MediaPlayer_MediaOpened(object sender, RoutedEventArgs e)
{
  FrameworkElement transportControlsTemplateRoot = (FrameworkElement)VisualTreeHelper.GetChild(MediaPlayerElement1.TransportControls, 0);
  Slider sliderControl = (Slider)transportControlsTemplateRoot.FindName("ProgressSlider");
  if (sliderControl != null && MediaPlayerElement1.NaturalDuration.TimeSpan.TotalMinutes > 120)
  {
    // Default is 1%. Change to 0.1% for more granular seeking.
    sliderControl.StepFrequency = 0.1;
  }
}