■ Shell 엘리먼트를 사용해 태양 일출/일몰 및 달 위상 정보를 조회하는 방법을 보여준다.
▶ Platforms/Android/AndroidManifest.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application android:allowBackup="true" android:icon="@android:mipmap/sym_def_app_icon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> </manifest> |
▶ Platforms/iOS/info.plist
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 |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>LSRequiresIPhoneOS</key> <true/> <key>UIDeviceFamily</key> <array> <integer>1</integer> <integer>2</integer> </array> <key>UIRequiredDeviceCapabilities</key> <array> <string>arm64</string> </array> <key>UISupportedInterfaceOrientations</key> <array> <string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeRight</string> </array> <key>UISupportedInterfaceOrientations~ipad</key> <array> <string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortraitUpsideDown</string> <string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeRight</string> </array> <key>XSAppIconAssets</key> <string>Assets.xcassets/appicon.appiconset</string> <key>NSLocationAlwaysAndWhenInUseUsageDescription</key> <string>Need the location to display sunrise and sunset times</string> </dict> </plist> |
▶ Platforms/MacCatalyst/info.plist
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 |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>UIDeviceFamily</key> <array> <integer>1</integer> <integer>2</integer> </array> <key>UIRequiredDeviceCapabilities</key> <array> <string>arm64</string> </array> <key>UISupportedInterfaceOrientations</key> <array> <string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeRight</string> </array> <key>UISupportedInterfaceOrientations~ipad</key> <array> <string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortraitUpsideDown</string> <string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeRight</string> </array> <key>XSAppIconAssets</key> <string>Assets.xcassets/appicon.appiconset</string> <key>NSLocationUsageDescription</key> <string>Need location to display sunrise and sunset info</string> </dict> </plist> |
▶ Platforms/Windows/Package.appxmanifest
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 |
<?xml version="1.0" encoding="utf-8"?> <Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" IgnorableNamespaces="uap rescap"> <Identity Publisher="CN=User Name" /> <Properties> <PublisherDisplayName>User Name</PublisherDisplayName> </Properties> <Dependencies> <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" /> <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" /> </Dependencies> <Resources> <Resource Language="x-generate" /> </Resources> <Applications> <Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$"> <uap:VisualElements /> </Application> </Applications> <Capabilities> <rescap:Capability Name="runFullTrust" /> <DeviceCapability Name="location" /> </Capabilities> </Package> |
▶ DATA/MoonPhaseCalculator.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 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
namespace TestProject { /// <summary> /// 달 위상 계산기 /// </summary> public static class MoonPhaseCalculator { //////////////////////////////////////////////////////////////////////////////////////////////////// Enumeration ////////////////////////////////////////////////////////////////////////////////////////// Public #region 위상 - Phase /// <summary> /// 위상 /// </summary> public enum Phase { /// <summary> /// 삭(신월) /// </summary> New, /// <summary> /// 초승달 /// </summary> WaxingCrescent, /// <summary> /// 상현달 /// </summary> FirstQuarter, /// <summary> /// 소망월 /// </summary> WaxingGibbous, /// <summary> /// 보름달 /// </summary> Full, /// <summary> /// 기망월 /// </summary> WaningGibbous, /// <summary> /// 하현달 /// </summary> LastQuarter, /// <summary> /// 그믐달 /// </summary> WaningCrescent, } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 달 공전 일수 /// </summary> private static double _moonCycleDayLength = 29.530588853; /// <summary> /// 참조 신월 날짜 /// </summary> private static DateTime _referenceNewMoonDate = new DateTime(2017, 11, 18); #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Public #region 위상 구하기 - GetPhase(date) /// <summary> /// 위상 구하기 /// </summary> /// <param name="date">날짜</param> /// <returns>위상</returns> public static Phase GetPhase(DateTime date) { return GetPhase(GetPhaseValue(date)); } #endregion #region 위상 텍스트 구하기 - GetPhaseText(phase) /// <summary> /// 위상 텍스트 구하기 /// </summary> /// <param name="phase">위상</param> /// <returns>위상 텍스트</returns> public static string GetPhaseText(Phase phase) { switch(phase) { case Phase.New : return "삭(신월)"; case Phase.WaxingCrescent : return "초승달"; case Phase.FirstQuarter : return "상현달"; case Phase.WaxingGibbous : return "소망월"; case Phase.Full : return "보름달"; case Phase.WaningGibbous : return "기망월"; case Phase.LastQuarter : return "하현달"; case Phase.WaningCrescent : return "그믐달"; default : return string.Empty; } } #endregion //////////////////////////////////////////////////////////////////////////////// Public #region 위상 값 구하기 - GetPhaseValue(date) /// <summary> /// 위상 값 구하기 /// </summary> /// <param name="date">날짜</param> /// <returns>위상 값</returns> private static double GetPhaseValue(DateTime date) { double phaseValue = (date - _referenceNewMoonDate).TotalDays; return phaseValue % _moonCycleDayLength; } #endregion #region 위상 구하기 - GetPhase(phaseValue) /// <summary> /// 위상 구하기 /// </summary> /// <param name="phaseValue">위상 값</param> /// <returns>위상</returns> private static Phase GetPhase(double phaseValue) { if(phaseValue < 1 ) return Phase.New; if(phaseValue < 7 ) return Phase.WaxingCrescent; if(phaseValue < 8 ) return Phase.FirstQuarter; if(phaseValue < 14) return Phase.WaxingGibbous; if(phaseValue < 15) return Phase.Full; if(phaseValue < 22) return Phase.WaningGibbous; if(phaseValue < 23) return Phase.LastQuarter; if(phaseValue < 29) return Phase.WaningCrescent; return Phase.New; } #endregion } } |
▶ DATA/ILocationService.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
namespace TestProject { /// <summary> /// 위치 서비스 인터페이스 /// </summary> public interface ILocationService { //////////////////////////////////////////////////////////////////////////////////////////////////// Method #region 위치 구하기 - GetLocation() /// <summary> /// 위치 구하기 /// </summary> /// <returns>(위도, 경도)</returns> Task<(double Latitude, double Longitude)> GetLocation(); #endregion } } |
▶ DATA/LocationService.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 |
namespace TestProject { /// <summary> /// 위치 서비스 /// </summary> public class LocationService : ILocationService { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public #region 위치 구하기 - GetLocation() /// <summary> /// 위치 구하기 /// </summary> /// <returns>(위도, 경로)</returns> public async Task<(double Latitude, double Longitude)> GetLocation() { double latitude = 0d; double longitude = 0d; PermissionStatus status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>(); if(status == PermissionStatus.Granted) { GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Default, TimeSpan.FromSeconds(10)); Location location = await Geolocation.GetLocationAsync(request); latitude = location.Latitude; longitude = location.Longitude; } return (latitude, longitude); } #endregion } } |
▶ DATA/SunriseService.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 |
using System.Text.Json; namespace TestProject { /// <summary> /// 일출 서비스 /// </summary> public class SunriseService { //////////////////////////////////////////////////////////////////////////////////////////////////// Class ////////////////////////////////////////////////////////////////////////////////////////// Private #region 일출/일몰 결과 - SunriseSunsetResults /// <summary> /// 일출/일몰 결과 /// </summary> private class SunriseSunsetResults { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 일출 - Sunrise /// <summary> /// 일출 /// </summary> public string Sunrise { get; set; } #endregion #region 일몰 - Sunset /// <summary> /// 일몰 /// </summary> public string Sunset { get; set; } #endregion } #endregion #region 일출/일몰 데이터 - SunriseSunsetData /// <summary> /// 일출/일몰 데이터 /// </summary> private class SunriseSunsetData { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 결과 - Results /// <summary> /// 결과 /// </summary> public SunriseSunsetResults Results { get; set; } #endregion } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 서비스 URL /// </summary> private const string SERVICE_URL = "https://api.sunrise-sunset.org"; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public #region 데이터 시간 구하기 - GetData(latitude, longitude) /// <summary> /// 데이터 구하기 /// </summary> /// <param name="latitude">위도</param> /// <param name="longitude">경도</param> /// <returns>(일출 시간, 일몰 시간)</returns> public async Task<(DateTime SunriseTime, DateTime SunsetTime)> GetData(double latitude, double longitude) { string url = $"{SERVICE_URL}/json?lat={latitude}&lng={longitude}&date=today"; HttpClient client = new HttpClient(); client.DefaultRequestHeaders.Add("Accept", "application/json"); string json = await client.GetStringAsync(url); JsonSerializerOptions options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; SunriseSunsetData data = JsonSerializer.Deserialize<SunriseSunsetData>(json, options); return (DateTime.Parse(data.Results.Sunrise), DateTime.Parse(data.Results.Sunset)); } #endregion } } |
▶ PAGE/MoonPhasePage.xaml
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 |
<?xml version="1.0" encoding="utf-8" ?> <ContentPage x:Class="TestProject.MoonPhasePage" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" Title="달 위상" BackgroundColor="Black"> <ContentPage.Resources> <ResourceDictionary> <Style TargetType="Label"> <Setter Property="HorizontalOptions" Value="Center" /> <Setter Property="TextColor" Value="White" /> </Style> </ResourceDictionary> </ContentPage.Resources> <Grid> <Image Aspect="AspectFill" Source="starfield.png" /> <Grid HorizontalOptions="Center" VerticalOptions="Center" RowSpacing="10" ColumnSpacing="10"> <Grid.RowDefinitions> <RowDefinition Height="auto" /> <RowDefinition Height="auto" /> <RowDefinition Height="auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="auto" /> </Grid.ColumnDefinitions> <StackLayout Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="4" Spacing="10"> <Label x:Name="dateLabel" FontAttributes="Bold" Text="" /> <Label x:Name="moonPhaseIconLabel" FontSize="96" Text="" /> <Label x:Name="moonPhaseTextLabel" FontAttributes="Bold" Text="" /> </StackLayout> <Label x:Name="phaseIconLabel1" Grid.Row="1" Grid.Column="0" FontSize="48" /> <Label x:Name="phaseIconLabel2" Grid.Row="1" Grid.Column="1" FontSize="48" /> <Label x:Name="phaseIconLabel3" Grid.Row="1" Grid.Column="2" FontSize="48" /> <Label x:Name="phaseIconLabel4" Grid.Row="1" Grid.Column="3" FontSize="48" /> <Label x:Name="phaseTextLabel1" Grid.Row="2" Grid.Column="0" FontSize="Medium" FontAttributes="Bold" /> <Label x:Name="phaseTextLabel2" Grid.Row="2" Grid.Column="1" FontSize="Medium" FontAttributes="Bold" /> <Label x:Name="phaseTextLabel3" Grid.Row="2" Grid.Column="2" FontSize="Medium" FontAttributes="Bold" /> <Label x:Name="phaseTextLabel4" Grid.Row="2" Grid.Column="3" FontSize="Medium" FontAttributes="Bold" /> </Grid> </Grid> </ContentPage> |
▶ PAGE/MoonPhasePage.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 |
namespace TestProject; /// <summary> /// 달 위상 페이지 /// </summary> public partial class MoonPhasePage : ContentPage { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 달 위상 딕셔너리 /// </summary> private static Dictionary<MoonPhaseCalculator.Phase, string> _moonPhaseDictionary = new Dictionary<MoonPhaseCalculator.Phase, string> { { MoonPhaseCalculator.Phase.New , "🌑" }, { MoonPhaseCalculator.Phase.WaxingCrescent, "🌒" }, { MoonPhaseCalculator.Phase.FirstQuarter , "🌓" }, { MoonPhaseCalculator.Phase.WaxingGibbous , "🌔" }, { MoonPhaseCalculator.Phase.Full , "🌕" }, { MoonPhaseCalculator.Phase.WaningGibbous , "🌖" }, { MoonPhaseCalculator.Phase.LastQuarter , "🌗" }, { MoonPhaseCalculator.Phase.WaningCrescent, "🌘" } }; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MoonPhasePage() /// <summary> /// 생성자 /// </summary> public MoonPhasePage() { InitializeComponent(); MoonPhaseCalculator.Phase phase = MoonPhaseCalculator.GetPhase(DateTime.Now); this.dateLabel.Text = DateTime.Today.ToString("yyyy/MM/dd"); this.moonPhaseIconLabel.Text = _moonPhaseDictionary[phase]; this.moonPhaseTextLabel.Text = MoonPhaseCalculator.GetPhaseText(phase); SetMoonPhaseLabels(this.phaseIconLabel1, this.phaseTextLabel1, 1); SetMoonPhaseLabels(this.phaseIconLabel2, this.phaseTextLabel2, 2); SetMoonPhaseLabels(this.phaseIconLabel3, this.phaseTextLabel3, 3); SetMoonPhaseLabels(this.phaseIconLabel4, this.phaseTextLabel4, 4); } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region 달 위상 레이블 설정하기 - SetMoonPhaseLabels(phaseIconLabel, phaseTextLabel, dayOffset) /// <summary> /// 달 위상 레이블 설정하기 /// </summary> /// <param name="phaseIconLabel">위상 아이콘 레이블</param> /// <param name="phaseTextLabel">위상 텍스트 레이블</param> /// <param name="dayOffset">날짜 오프셋</param> private void SetMoonPhaseLabels(Label phaseIconLabel, Label phaseTextLabel, int dayOffset) { MoonPhaseCalculator.Phase phase = MoonPhaseCalculator.GetPhase(DateTime.Now.AddDays(dayOffset)); phaseIconLabel.Text = _moonPhaseDictionary[phase]; phaseTextLabel.Text = DateTime.Now.AddDays(dayOffset).ToString("MM/dd"); } #endregion } |
▶ PAGE/SunrisePage.xaml
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 |
<?xml version="1.0" encoding="utf-8" ?> <ContentPage x:Class="TestProject.SunrisePage" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" Title="일출"> <ContentPage.Resources> <ResourceDictionary> <Style TargetType="Label"> <Setter Property="HorizontalOptions" Value="Center" /> </Style> </ResourceDictionary> </ContentPage.Resources> <StackLayout HorizontalOptions="Center" VerticalOptions="Center" Padding="10"> <Label x:Name="dateLabel" WidthRequest="200" HorizontalTextAlignment="Center" FontAttributes="Bold" /> <ActivityIndicator x:Name="activityIndicator" IsRunning="False" Color="Orange" /> <Grid Padding="10" RowSpacing="10" ColumnSpacing="10"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Label Grid.Row="0" Grid.Column="0" FontSize="72" Text="🌅" /> <Label Grid.Row="0" Grid.Column="1" FontSize="72" Text="☀️" /> <Label Grid.Row="0" Grid.Column="2" FontSize="72" Text="🌇" /> <Label Grid.Row="1" Grid.Column="0" FontAttributes="Bold" Text="일출" /> <Label Grid.Row="1" Grid.Column="1" FontAttributes="Bold" Text="일광" /> <Label Grid.Row="1" Grid.Column="2" FontAttributes="Bold" Text="일몰" /> <Label x:Name="sunriseTimeLabel" Grid.Row="2" Grid.Column="0" WidthRequest="100" HorizontalTextAlignment="Center" FontAttributes="None" /> <Label x:Name="daylightTimeLabel" Grid.Row="2" Grid.Column="1" WidthRequest="150" HorizontalTextAlignment="Center" FontAttributes="None" /> <Label x:Name="sunsetTimeLabel" Grid.Row="2" Grid.Column="2" WidthRequest="100" HorizontalTextAlignment="Center" FontAttributes="None" /> </Grid> </StackLayout> </ContentPage> |
▶ PAGE/SunrisePage.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 |
namespace TestProject; /// <summary> /// 일출 페이지 /// </summary> public partial class SunrisePage : ContentPage { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Private #region 위치 서비스 - LocationService /// <summary> /// 위치 서비스 /// </summary> private ILocationService LocationService { get; set; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - SunrisePage() /// <summary> /// 생성자 /// </summary> public SunrisePage() { InitializeComponent(); LocationService = new LocationService(); } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Protected #region 표시시 처리하기 - OnAppearing() /// <summary> /// 표시시 처리하기 /// </summary> protected override async void OnAppearing() { base.OnAppearing(); this.activityIndicator.IsRunning = true; (DateTime SunriseTime, DateTime SunsetTime, TimeSpan DaylightTime) data = await GetData(); this.dateLabel.Text = DateTime.Today.ToString("yyyy-MM-dd"); this.sunriseTimeLabel.Text = data.SunriseTime.ToString("HH:mm"); this.daylightTimeLabel.Text = $"{data.DaylightTime.Hours} 시간 {data.DaylightTime.Minutes} 분"; this.sunsetTimeLabel.Text = data.SunsetTime.ToString("HH:mm"); this.activityIndicator.IsRunning = false; } #endregion ////////////////////////////////////////////////////////////////////////////////////////// Private #region 데이터 구하기 - GetData() /// <summary> /// 데이터 구하기 /// </summary> /// <returns>(일출 시간, 일몰 시간, 일광 시간)</returns> private async Task<(DateTime SunriseTime, DateTime SunsetTime, TimeSpan DaylightTime)> GetData() { (double Latitude, double Longitude) location = await LocationService.GetLocation(); (DateTime SunriseTime, DateTime SunsetTime) data = await new SunriseService().GetData(location.Latitude, location.Longitude); DateTime sunriseTime = data.SunriseTime.ToLocalTime(); DateTime sunsetTime = data.SunsetTime.ToLocalTime(); TimeSpan daylightTime = sunsetTime.TimeOfDay - sunriseTime.TimeOfDay; return (sunriseTime, sunsetTime, daylightTime); } #endregion } |
▶ PAGE/AstronomicalBodyListPage.xaml
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 |
<?xml version="1.0" encoding="utf-8" ?> <ContentPage x:Class="TestProject.AstronomicalBodyListPage" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" Title="천체 목록"> <ContentPage.Resources> <ResourceDictionary> <Style TargetType="Button"> <Setter Property="BorderColor" Value="DarkGray" /> <Setter Property="FontSize" Value="100" /> </Style> <Style TargetType="Label"> <Setter Property="HorizontalOptions" Value="Center" /> <Setter Property="VerticalOptions" Value="End" /> <Setter Property="Margin" Value="5" /> <Setter Property="FontAttributes" Value="Bold" /> </Style> </ResourceDictionary> </ContentPage.Resources> <Grid Margin="10" RowDefinitions="*,*" ColumnDefinitions="*,*"> <Button x:Name="earthButton" Grid.Row="0" Grid.Column="0" Margin="10" Text="🌎" /> <Button x:Name="moonButton" Grid.Row="0" Grid.Column="1" Margin="10" Text="🌕" /> <Button x:Name="sunButton" Grid.Row="1" Grid.Column="0" Margin="10" Text="☀️" /> <Button x:Name="cometButton" Grid.Row="1" Grid.Column="1" Margin="10" Text="☄" /> </Grid> </ContentPage> |
▶ PAGE/AstronomicalBodyListPage.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 |
namespace TestProject; /// <summary> /// 천체 페이지 /// </summary> public partial class AstronomicalBodyListPage : ContentPage { //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - AstronomicalBodyListPage() /// <summary> /// 생성자 /// </summary> public AstronomicalBodyListPage() { InitializeComponent(); } #endregion } |
▶ PAGE/AboutPage.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?xml version="1.0" encoding="utf-8" ?> <ContentPage x:Class="TestProject.AboutPage" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" Title="Contoso 천문학 정보"> <StackLayout Padding="10" Spacing="5"> <Label Text="버전 1.0.0" /> <Label Text="일출/일몰 데이터 : https://sunrise-sunset.org/api" /> <Label Text="아이콘 제공 : Font Awesome" /> </StackLayout> </ContentPage> |
▶ PAGE/AboutPage.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 |
namespace TestProject; /// <summary> /// ABOUT 페이지 /// </summary> public partial class AboutPage : ContentPage { //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - AboutPage() /// <summary> /// 생성자 /// </summary> public AboutPage() { InitializeComponent(); } #endregion } |
▶ AppShell.xaml
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 |
<?xml version="1.0" encoding="UTF-8" ?> <Shell x:Class="TestProject.AppShell" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:TestProject"> <Shell.FlyoutHeader> <Grid HeightRequest="100" BackgroundColor="DarkSlateBlue"> <Image Source="moon.png" /> </Grid> </Shell.FlyoutHeader> <FlyoutItem Icon="moon.png" Title="천문"> <ShellContent Icon="moon.png" Title="달" ContentTemplate="{DataTemplate local:MoonPhasePage}" /> <ShellContent Icon="sun.png" Title="일광" ContentTemplate="{DataTemplate local:SunrisePage}" /> <ShellContent Icon="comet.png" Title="천체" ContentTemplate="{DataTemplate local:AstronomicalBodyListPage}" /> </FlyoutItem> <FlyoutItem Icon="question.png" Title="정보"> <ShellContent ContentTemplate="{DataTemplate local:AboutPage}" /> </FlyoutItem> </Shell> |
▶ AppShell.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 |
namespace TestProject; /// <summary> /// 앱 셸 /// </summary> public partial class AppShell : Shell { //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - AppShell() /// <summary> /// 생성자 /// </summary> public AppShell() { InitializeComponent(); } #endregion } |
▶ App.xaml
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 |
<?xml version = "1.0" encoding = "UTF-8" ?> <Application x:Class="TestProject.App" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> <Application.Resources> <Color x:Key="PrimaryColorKey">#512bd4</Color> <Color x:Key="WhiteColorKey">White</Color> <Color x:Key="BlackColorKey">Black</Color> <Color x:Key="LightGrayColorKey">#e5e5e1</Color> <Color x:Key="DarkGrayColorKey">#505050</Color> <Style TargetType="Page" ApplyToDerivedTypes="True"> <Setter Property="Padding" Value="0" /> <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource WhiteColorKey}, Dark={StaticResource BlackColorKey}}" /> </Style> <Style TargetType="Shell" ApplyToDerivedTypes="True"> <Setter Property="Shell.BackgroundColor" Value="{AppThemeBinding Light={StaticResource PrimaryColorKey}, Dark={StaticResource BlackColorKey}}" /> <Setter Property="Shell.ForegroundColor" Value="{OnPlatform WinUI={StaticResource PrimaryColorKey}, Default={StaticResource WhiteColorKey}}" /> <Setter Property="Shell.TitleColor" Value="{AppThemeBinding Light={StaticResource LightGrayColorKey}, Dark={StaticResource WhiteColorKey}}" /> <Setter Property="Shell.DisabledColor" Value="{AppThemeBinding Light={StaticResource LightGrayColorKey}, Dark={StaticResource DarkGrayColorKey}}" /> <Setter Property="Shell.UnselectedColor" Value="{AppThemeBinding Light={StaticResource LightGrayColorKey}, Dark={StaticResource LightGrayColorKey}}" /> <Setter Property="Shell.NavBarHasShadow" Value="False" /> <Setter Property="Shell.TabBarBackgroundColor" Value="{AppThemeBinding Light={StaticResource WhiteColorKey}, Dark={StaticResource BlackColorKey}}" /> <Setter Property="Shell.TabBarForegroundColor" Value="{AppThemeBinding Light={StaticResource PrimaryColorKey}, Dark={StaticResource WhiteColorKey}}" /> <Setter Property="Shell.TabBarTitleColor" Value="{AppThemeBinding Light={StaticResource PrimaryColorKey}, Dark={StaticResource WhiteColorKey}}" /> <Setter Property="Shell.TabBarUnselectedColor" Value="{AppThemeBinding Light={StaticResource DarkGrayColorKey}, Dark={StaticResource LightGrayColorKey}}" /> </Style> <Style TargetType="Label"> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource BlackColorKey}, Dark={StaticResource WhiteColorKey}}" /> <Setter Property="FontFamily" Value="OpenSansRegular" /> <Setter Property="FontSize" Value="14" /> </Style> <Style TargetType="Button"> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource WhiteColorKey}, Dark={StaticResource PrimaryColorKey}}" /> <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource PrimaryColorKey}, Dark={StaticResource WhiteColorKey}}" /> <Setter Property="FontFamily" Value="OpenSansRegular"/> <Setter Property="FontSize" Value="14" /> <Setter Property="CornerRadius" Value="8" /> <Setter Property="Padding" Value="14,10" /> <Setter Property="VisualStateManager.VisualStateGroups"> <VisualStateGroupList> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal" /> <VisualState x:Name="Disabled"> <VisualState.Setters> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource DarkGrayColorKey}, Dark={StaticResource LightGrayColorKey}}" /> <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource LightGrayColorKey}, Dark={StaticResource DarkGrayColorKey}}" /> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateGroupList> </Setter> </Style> <Style TargetType="ActivityIndicator"> <Setter Property="Color" Value="{AppThemeBinding Light={StaticResource PrimaryColorKey}, Dark={StaticResource WhiteColorKey}}" /> </Style> </Application.Resources> </Application> |
▶ 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 |
namespace TestProject; /// <summary> /// 앱 /// </summary> public partial class App : Application { //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - App() /// <summary> /// 생성자 /// </summary> public App() { InitializeComponent(); MainPage = new AppShell(); } #endregion } |
▶ MauiProgram.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 |
namespace TestProject; /// <summary> /// MAUI 프로그램 /// </summary> public static class MauiProgram { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Public #region MAUI 앱 생성하기 - CreateMauiApp() /// <summary> /// MAUI 앱 생성하기 /// </summary> /// <returns>MAUI 앱</returns> public static MauiApp CreateMauiApp() { MauiAppBuilder builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .ConfigureFonts ( fontCollection => { fontCollection.AddFont("OpenSans-Regular.ttf" , "OpenSansRegular" ); fontCollection.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); } ); return builder.Build(); } #endregion } |