我试图确定当屏幕旋转(在Android中)使用这里详细的XLabs方法如何处理Xamarin窗体中的屏幕旋转/方向?我用起来有点麻烦。
我在MainActivity中重写OnConfigurationChanged方法
public override void OnConfigurationChanged (Android.Content.Res.Configuration newConfig)
{
base.OnConfigurationChanged (newConfig);
var xapp = Resolver.Resolve<IXFormsApp> ();
if (xapp == null)
return;
switch (newConfig.Orientation) {
case Android.Content.Res.Orientation.Landscape:
xapp.Orientation = XLabs.Enums.Orientation.Landscape;
break;
case Android.Content.Res.Orientation.Portrait:
//xapp.Orientation = XLabs.Enums.Orientation.Portrait;
break;
default:
break;
}
}
我在IXFormsApp的方向变量有麻烦,即xapp.Orientation。XLabs文档将其列为"保护集",编译器也是如此:
MainActivity.cs(109,5,109,21): error CS0200: Property or indexer 'XLabs.Platform.Mvvm.IXFormsApp.Orientation' cannot be assigned to -- it is read only
并且它不会自动设置(当我检查它在哪里使用时,它总是设置为'None'),所以我想知道如何利用它,事实上,如何使用XLabs/IXFormsApp来确定旋转?
在一个相关的说明,我也试图设置旋转处理程序(不知道为什么,但我想我会给它一个不寻常的结果)。
xapp.Rotation += (sender, args) =>
{
switch (args.Value)
{
case XLabs.Enums.Orientation.Landscape:
//xapp.Orientation = XLabs.Enums.Orientation.Landscape;
...
break;
case XLabs.Enums.Orientation.Portrait:
...
break;
default:
break;
}
};
如果我在Android代码中尝试,我会得到以下错误:
MainActivity.cs(60,4,60,22): error CS0019: Operator '+=' cannot be applied to operands of type 'System.EventHandler<XLabs.EventArgs<XLabs.Enums.Orientation>>' and 'lambda expression'
但是,如果我在Forms代码(使用结果的地方)中设置,就可以了(尽管处理程序似乎从来没有实际调用过)。有人知道为什么会这样吗?
我过去使用过两种不同的解决方案。
第一个是创建一个PageBase类,我所有的页面都继承它,而PageBase继承一个普通的页面。
我的PageBase有两个抽象方法(所以它的子方法必须填充它),它们是UpdateLandscape和UpdatePortait。孩子们将根据页面是横向布局还是纵向布局来填写这些方法。
Pages有一个OnSizeAllocated方法,如Daniel所说。我让PageBase覆盖它,并使它调用UpdateLandscape和UpdatePortait相应。
如果,正如你所说,你只是想检查它什么时候旋转,上面的工作很好,当你旋转你的手机时,OnSizeAllocated会被调用一个页面。
如果你正在检查横向和纵向,因为你希望你的代码能够随时检查,那么下面的第二个解决方案也可以工作。
我解决它的第二种方法是使用依赖服务来填充一个IDeviceInfo接口,并通过检查DeviceInfo. isportait()是否为真或假来编写所有动态的东西(这种方式我也让DeviceInfo有一个宽度和高度,所以我可以在任何时候请求屏幕尺寸)。
在Android上,我这样填写我的Android代码:
[assembly: Dependency (typeof(Namespace.DeviceInfoProvider))]
namespace Namespace
{
public class DeviceInfoProvider : IDeviceInfoProvider
{
public bool IsPortait () { return DeviceInfoManager.Width < DeviceInfoManager.Height; }
public int GetWidth () { return DeviceInfoManager.Width; }
public int GetHeight () { return DeviceInfoManager.Height; }
}
public static class DeviceInfoManager
{
public static MainActivity MainActivity { get; set; }
public static int Width { get { return MainActivity.GetWidth (); } }
public static int Height { get { return MainActivity.GetHeight (); } }
}
}
然后在MainActivity中我给了它这些方法:
public int GetWidth() {
return (int)(Resources.DisplayMetrics.WidthPixels / Resources.DisplayMetrics.Density);
}
public int GetHeight() {
return (int)(Resources.DisplayMetrics.HeightPixels / Resources.DisplayMetrics.Density);
}
在iOS端,我是这样填写的:
[assembly: Dependency (typeof(Namespace.DeviceInfoProvider))]
namespace Namespace {
public class DeviceInfoProvider : IDeviceInfoProvider {
public bool IsPortait() { return UIScreen.MainScreen.Bounds.Width < UIScreen.MainScreen.Bounds.Height; }
public int GetWidth() { return (int)UIScreen.MainScreen.Bounds.Width; }
public int GetHeight() { return (int)UIScreen.MainScreen.Bounds.Height; }
}
}
就我个人而言,我更喜欢用第二种方式来写,并让它检查"如果我们在肖像模式下,这里有不同之处"。这样一来,那些在肖像和风景之间没有区别的东西只需要写一次,只有不同的地方需要写两次。
你可以使用OnSizeAllocated方法覆盖来检测方向变化;
double previousWidth;
double previousHeight;
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
if (previousWidth != width || previousHeight != height)
{
previousWidth = width;
previousHeight = height;
if (width > height)
{
// landscape mode
}
else
{
// portrait mode
}
}
}