개발하는 두더지

[C/C++/C#/UWP] UWP SplashScreen (스플래쉬스크린) 구현하기 본문

C,C++

[C/C++/C#/UWP] UWP SplashScreen (스플래쉬스크린) 구현하기

덜지 2016. 10. 24. 17:40

SplashScreen 이란?


한마디로 로딩화면을 의미합니다. 

어플리케이션을 구동할 때 로딩화면과 함께 어플리케이션 정보, 저작권 정보를 표시해주거나  초기화 작업등을 수행합니다. 

UWP에서 새로운 프로젝트를 만들면 기본 SplashScreen 를 제공합니다. 

하지만 눈깜짝할 사이에 사라지므로 Customize된 SplashScreen이 필요합니다.



SplashScreen 클래스를 사용해야하는데 클래스 구성은 아래와 같이 되어있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
namespace Windows.ApplicationModel.Activation
{
    //
    // 요약:
    //     앱의 시작 화면에 대한 닫기 이벤트 및 이미지 위치 정보를 제공합니다.
    [ContractVersion(typeof(UniversalApiContract), 65536)]
    public sealed class SplashScreen : ISplashScreen
    {
        //
        // 요약:
        //     창 위치를 기준으로 할 때 응용 프로그램 시작 화면 이미지의 상대 좌표입니다.
        //
        // 반환 값:
        //     창 위치를 기준으로 할 때 장치의 dpi(인치당 도트 수)로 배율 조정된 시작 화면 이미지의 상대 좌표입니다.
        public Rect ImageLocation { get; }
 
        //
        // 요약:
        //     응용 프로그램의 시작 화면이 해제될 때 발생합니다.
        public event TypedEventHandler<SplashScreen, System.Object> Dismissed;
    }
}
cs






UWP Extended SplashScreen 만들기


준비물 1

620x300 픽셀의 이미지 준비




위와 같은 화면과 프로그레스링(ProgressRing으로 로딩화면을 만들어보도록 하겠습니다.





3초 뒤에 메인 페이지로 이동




모바일 버전








파일->새로만들기->프로젝트->비어 있는 앱(유니버셜 Windows)

"SplashScreenTest" 라는 이름으로 프로젝트를 만듭니다.




솔루션 탐색기에서 "Images" 라는 폴더를 만들고 스플래쉬 스크린 이미지 파일을 Import합니다.




솔루션 탐색기 -> 추가 -> 새항목 -> 빈 페이지 

"ExtendedSplash.xaml" 페이지를 만들어줍니다.







파일을 생성했으면  Package.appxmanifest 파일을 오른쪽 버튼 클릭 후 -> 코드보기 를 클릭합니다.

그리고 SplashScreen 요소를 그림과 같이 변경합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  <Applications>
    <Application Id="App"
      Executable="$targetnametoken$.exe"
      EntryPoint="SplashScreenTest.App">
      <uap:VisualElements
        DisplayName="SplashScreenTest"
        Square150x150Logo="Assets\Square150x150Logo.png"
        Square44x44Logo="Assets\Square44x44Logo.png"
        Description="SplashScreenTest"
        BackgroundColor="transparent">
        <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
        <!--<uap:SplashScreen Image="Assets\SplashScreen.png"/>-->
        <uap:SplashScreen Image="Images\SplashScreen.png" BackgroundColor="#99D9EA"/>
      </uap:VisualElements>
    </Application>
  </Applications>
cs









EntendedSplash.xaml 는 UI 를 구성하는 뷰의 소스코드입니다.

배경색, 캔버스 안에 이미지뷰, 프로그레스링, 텍스트블럭 4가지의 요소로 구성했습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<Page
    x:Class="SplashScreenTest.ExtendedSplash"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:SplashScreenTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" Background="#99D9EA">
 
    <Grid Background="#99D9EA">
        <Canvas>
            <Image x:Name="extendedSplashImage" Source="Images/SplashScreen.png"/>
        </Canvas>
        <ProgressRing Name="splashProgressRing" IsActive="True" Height="30" Width="30" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="20" Foreground="White"/>
        <TextBlock x:Name="textBlock" HorizontalAlignment="Left" VerticalAlignment="Bottom" Width="Auto" Margin="50"/>
    </Grid>
</Page>
 
cs





Background는 SplashScreen.png의 배경색을 가져왔습니다. 

VS2015에서 이미지 파일을 열어서 배경색의 값을 알아올수 있습니다.












ExtendedSplash.xaml.cs 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Graphics.Display;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
 
// 빈 페이지 항목 템플릿에 대한 설명은 http://go.microsoft.com/fwlink/?LinkId=234238에 나와 있습니다.
 
namespace SplashScreenTest
{
    /// <summary>
    /// 자체적으로 사용하거나 프레임 내에서 탐색할 수 있는 빈 페이지입니다.
    /// </summary>
    public sealed partial class ExtendedSplash : Page
    {
        internal Rect splashImageRect;
        internal bool dismissed = false;
        internal Frame rootFrame;
 
        private SplashScreen splash;
        private double ScaleFactor;
        public ExtendedSplash(SplashScreen splashscreen , bool loadState)
        {
            this.InitializeComponent();   // 페이지 초기화
            DismissExtendedSplash();     // 3초 후 페이지 이동 코드
 
            Window.Current.SizeChanged += new WindowSizeChangedEventHandler(ExtendedSplash_OnResize);   // 윈도우 사이즈 변경시 이벤트를 받을 핸들러 설정
            ScaleFactor = (double)DisplayInformation.GetForCurrentView().ResolutionScale / 100;   // 현재 실제 디스플레이 정보를 가져와서 배율값을 구합니다.
 
            splash = splashscreen; 
            if (splash != null)
            {
                splash.Dismissed += new TypedEventHandler<SplashScreen, Object>(DismissedEventHandler);
                splashImageRect = splash.ImageLocation;
                PositionImage();
            }
 
            RestoreStateAsync(loadState);
        }
 
        async private void RestoreStateAsync(bool loadState)
        {
            if (loadState)
            {
                await SuspensionManager.RestoreAsync();
            }
        }
 
        void DismissedEventHandler(SplashScreen sender, object args)
        {
            dismissed = true
        }
 
        void ExtendedSplash_OnResize(object sender, WindowSizeChangedEventArgs e)
        {
            if(splash != null)
            {
                splashImageRect = splash.ImageLocation;   // 스플래쉬이미지의 상대좌표를 저장
                PositionImage();
            }
        }
 
        void PositionImage()
        {
            extendedSplashImage.SetValue(Canvas.LeftProperty, splashImageRect.Left);
            extendedSplashImage.SetValue(Canvas.TopProperty, splashImageRect.Top);
            extendedSplashImage.Height = splashImageRect.Height / ScaleFactor;
            extendedSplashImage.Width = splashImageRect.Width / ScaleFactor;
 
            // 현재 활성화 된 창의 크기가 변경되 스플래쉬이미지의 시작점, 가로, 세로의 길이를 출력
            textBlock.Text = splashImageRect.Left + " , " +
                            splashImageRect.Top + " , " +
                            extendedSplashImage.Width + " , " +
                            extendedSplashImage.Height;
        }
 
        async void DismissExtendedSplash()
        {
            await Task.Delay(TimeSpan.FromSeconds(3));      //3초간 딜레이 후 페이지 이동
            rootFrame = new Frame();                        //프레임 객체 생성
            MainPage mainPage = new MainPage();
            rootFrame.Content = mainPage;
            Window.Current.Content = rootFrame;             //현재 활성화된 창의 컨텐츠에 프레임객체를 설정
            rootFrame.Navigate(typeof(MainPage));           //프레임에서 페이지 이동.
        }
    }
}
 
cs









추가로 어플리케이션의 진입점 코드도 변경해야 합니다


App.xaml.cs 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
 
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
 
namespace SplashScreenTest
{
    /// <summary>
    /// 기본 응용 프로그램 클래스를 보완하는 응용 프로그램별 동작을 제공합니다.
    /// </summary>
    sealed partial class App : Application
    {
        /// <summary>
        /// Singleton 응용 프로그램 개체를 초기화합니다. 이것은 실행되는 작성 코드의 첫 번째
        /// 줄이며 따라서 main() 또는 WinMain()과 논리적으로 동일합니다.
        /// </summary>
        public App()
        {
            this.InitializeComponent();
            this.Suspending += OnSuspending;
        }
 
        /// <summary>
        /// 최종 사용자가 응용 프로그램을 정상적으로 시작할 때 호출됩니다. 다른 진입점은
        /// 특정 파일을 여는 등 응용 프로그램을 시작할 때
        /// </summary>
        /// <param name="e">시작 요청 및 프로세스에 대한 정보입니다.</param>
        protected override void OnLaunched(LaunchActivatedEventArgs e)
        {
#if DEBUG
            if (System.Diagnostics.Debugger.IsAttached)
            {
                this.DebugSettings.EnableFrameRateCounter = true;
            }
#endif
            Frame rootFrame = Window.Current.Content as Frame;
 
            // 창에 콘텐츠가 이미 있는 경우 앱 초기화를 반복하지 말고,
            // 창이 활성화되어 있는지 확인하십시오.
            if (rootFrame == null)
            {
                // 탐색 컨텍스트로 사용할 프레임을 만들고 첫 페이지로 이동합니다.
                rootFrame = new Frame();
 
                rootFrame.NavigationFailed += OnNavigationFailed;
 
                if (e.PreviousExecutionState != ApplicationExecutionState.Running)
                {
                    bool loadState = (e.PreviousExecutionState == ApplicationExecutionState.Terminated);
                    ExtendedSplash extendedSplash = new ExtendedSplash(e.SplashScreen, loadState);
                    rootFrame.Content = extendedSplash;
                    Window.Current.Content = rootFrame;
                }
 
                // 현재 창에 프레임 넣기
                Window.Current.Content = rootFrame;
            }
 
            if (e.PrelaunchActivated == false)
            {
                if (rootFrame.Content == null)
                {
                    // 탐색 스택이 복원되지 않으면 첫 번째 페이지로 돌아가고
                    // 필요한 정보를 탐색 매개 변수로 전달하여 새 페이지를
                    // 구성합니다.
                    rootFrame.Navigate(typeof(MainPage), e.Arguments);
                }
                // 현재 창이 활성 창인지 확인
                Window.Current.Activate();
            }
        }
 
        /// <summary>
        /// 특정 페이지 탐색에 실패한 경우 호출됨
        /// </summary>
        /// <param name="sender">탐색에 실패한 프레임</param>
        /// <param name="e">탐색 실패에 대한 정보</param>
        void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
        }
 
        /// <summary>
        /// 응용 프로그램 실행이 일시 중단된 경우 호출됩니다.  응용 프로그램이 종료될지
        /// 또는 메모리 콘텐츠를 변경하지 않고 다시 시작할지 여부를 결정하지 않은 채
        /// 응용 프로그램 상태가 저장됩니다.
        /// </summary>
        /// <param name="sender">일시 중단 요청의 소스입니다.</param>
        /// <param name="e">일시 중단 요청에 대한 세부 정보입니다.</param>
        async private void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();
            //TODO: 응용 프로그램 상태를 저장하고 백그라운드 작업을 모두 중지합니다.
            await SuspensionManager.SaveAsync();
            deferral.Complete();
        }
    }
}
 
cs





Comments