Xamarin.Forms 画面のサイズを取得する
コンストラクタでは、サイズが取得できない
次のようなコードを書くと、もれなくサイズの取得に失敗します。単純にContentPageのサイズ(WidthとHeight)を表示しているだけですが、綺麗に-1になってしまっています。
using Xamarin.Forms; namespace App1{ public class App : Application{ public App(){ MainPage = new MyPage(); } protected override void OnStart(){} protected override void OnSleep(){} protected override void OnResume(){} } class MyPage : ContentPage { public MyPage() { Content = new Label{ //ラベル1つ配置する HorizontalOptions = LayoutOptions.Center,//左右中央に配置 VerticalOptions = LayoutOptions.Center,//上下中央に配置 Text = string.Format("Width={0} Height={1}", Width, Height) //ContentPage.Width,ContentPage.Heightプロパティを表示する }; } } }
Android | iOS | WindowsPhone |
![]() |
![]() |
![]() |
-1 * -1 | -1 * -1 | -1 * -1 |
OnSizeAllocated
解決方法の1つとして、ContentPageのサイズが取得できてから、使用するという方法があります。Width,Heightプロパティの値が変化した時点で、OnSizeAllocatedメソッドが呼ばれるので、これをオーバライドする方法です。
まー、この例の場合は、プロパティ値をバインディングした方が手っ取り早いですが・・・
using Xamarin.Forms; namespace App1{ public class App : Application{ public App(){ MainPage = new MyPage(); } protected override void OnStart(){} protected override void OnSleep(){} protected override void OnResume(){} } class MyPage : ContentPage { private Label _label = new Label() { //クラス変数とする HorizontalOptions = LayoutOptions.Center,//左右中央に配置 VerticalOptions = LayoutOptions.Center,//上下中央に配置 }; public MyPage() { Content = _label; //ラベル1つ配置する } protected override void OnSizeAllocated(double width, double height) { base.OnSizeAllocated(width, height); label.Text = string.Format("Width={0} Height={1}", Width, Height);//ContentPage.Width,ContentPage.Heightプロパティを表示する } } }
下のように、サイズが表示されているのが確認できます。
Android | iOS | WindowsPhone |
![]() |
![]() |
![]() |
320 * 496 | 320 * 568 | 480 * 768 |
コンストラクタの前にサイズを確保する
どうしても、コンストラクタの時点でサイズが欲しい場合・・・
それは、もうAppクラスがインスタンス化される前に、確保するしかありません。
思い切って、Appクラスのコンストラクタを引数ありにして、ディスプレイのサイズを取得するように変更します。
※ここで、ターゲットがContentPageのサイズでなく、ディスプレイのサイズになっていることをご了承下さい。
ContentPageが画面いっぱいに構成されているアプリという前提です。
using Xamarin.Forms; namespace App1{ public class App : Application{ public int ScreenWidth { get; private set; } //スクリーンサイズ(幅) public int ScreenHeight { get; private set; }//スクリーンサイズ(高さ) public App(int w,int h){ // パラメータで初期化 ScreenHeight = h; ScreenWidth = w; MainPage = new MyPage(); } protected override void OnStart(){} protected override void OnSleep(){} protected override void OnResume(){} } class MyPage : ContentPage { public MyPage() { Content = new Label{ HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center, Text = string.Format("Width={0} Height={1}", ((App)Application.Current).ScreenWidth,((App)Application.Current).ScreenHeight) }; } } }
コンストラクタが引数ありになったので、当然、このままではコンパイルできません。
各プラットフォームで、コンストラクタを生成している部分をいじります。
Android
Androidでは、MainActivity.csを修正します。
Resources.DisplayMetrics.WidthPixels(HeightPixels)でデバイスの実サイズ(dip)を取得し、これをResources.DisplayMetrics.Densityでピクセルに変換しています。
画面サイズを取得して、これをコンストラクタの引数とします。
using Android.App; using Android.Content.PM; using Android.OS; using Xamarin.Forms; using Xamarin.Forms.Platform.Android; namespace App1.Droid{ [Activity(Label = "App1", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)] public class MainActivity : FormsApplicationActivity{ protected override void OnCreate(Bundle bundle){ base.OnCreate(bundle); Forms.Init(this, bundle); //スクリーンのサイズを取得する var w = (int)(Resources.DisplayMetrics.WidthPixels / Resources.DisplayMetrics.Density); var h = (int)(Resources.DisplayMetrics.HeightPixels / Resources.DisplayMetrics.Density); LoadApplication(new App(w,h));//スクリーンサイズをパラメータにしてAppクラスを生成する //LoadApplication(new App());//引数なしはエラーとなる } } }
iOS
iOSでは、AppDelegate.csを修正します。
UIScreen.MainScreen.Bounds.Width(Height)で画面サイズを取得して、これをコンストラクタの引数とします。
using Foundation; using UIKit; namespace App1.iOS{ [Register("AppDelegate")] public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate{ public override bool FinishedLaunching(UIApplication app, NSDictionary options){ global::Xamarin.Forms.Forms.Init(); //スクリーンのサイズを取得する var w = (int)UIScreen.MainScreen.Bounds.Width; var h = (int)UIScreen.MainScreen.Bounds.Height; LoadApplication(new App(w,h));//スクリーンサイズをパラメータにしてAppクラスを生成する //LoadApplication(new App()); //引数なしはエラーとなる return base.FinishedLaunching(app, options); } } }
WindowsPhone
WindowsPhoneでは、MainPage.xaml.csを修正します。
Application.Current.Host.Content.ActualWidth(ActualHeight)で画面サイズを取得して、これをコンストラクタの引数とします。
using Microsoft.Phone.Controls; using Xamarin.Forms; using Xamarin.Forms.Platform.WinPhone; using Application = System.Windows.Application; namespace App1.WinPhone{ public partial class MainPage : FormsApplicationPage{ public MainPage(){ InitializeComponent(); SupportedOrientations = SupportedPageOrientation.PortraitOrLandscape; Forms.Init(); //スクリーンのサイズを取得する var w = (int)Application.Current.Host.Content.ActualWidth; var h = (int)Application.Current.Host.Content.ActualHeight; LoadApplication(new App1.App(w,h));//スクリーンサイズをパラメータにしてAppクラスを生成する //LoadApplication(new App1.App());//引数なしはエラーとなる } } }
下のように、サイズが表示されているのが確認できます。
ただし、AndroidとWindowsPhoneでは、高さが微妙に違うので注意が必要です。
対象としている領域が違うのが原因です。
Android | iOS | WindowsPhone |
![]() |
![]() |
![]() |
320 * 521 | 320 * 568 | 480 * 800 |