gpt4 book ai didi

c# - 如何在 xamarin 表单中设置 MasterDetailPage 的宽度

转载 作者:太空宇宙 更新时间:2023-11-03 13:13:34 25 4
gpt4 key购买 nike

我在适用于 ios 和 android 的 Xamarin 表单上使用 MasterDetailPage for app。

但是 MasterDetailPage 菜单的宽度太大,我想调整它。

如何在 Android 和 iOS 上为 MasterDetailPage 设置自定义宽度?

我的 MasterDetailPage 初始化代码:

            MyChatsMasterView _myChatsMasterView;
MyChatsView _myChatsView;

public MyChatsMasterDetailView(MyChatsMasterView myChatsMasterView, MyChatsView myChatsView)
{
NavigationPage.SetHasNavigationBar(this, false);

InitializeComponent();
this.MasterBehavior = MasterBehavior.Popover;

_myChatsMasterView = myChatsMasterView;
_myChatsView = myChatsView;

Master = _myChatsMasterView;
Detail = _myChatsView;

_myChatsMasterView.SetDetailView(this);
}

最佳答案

我通过从 Xamarin.Forms 源复制渲染器解决了这个问题。基本上我需要一个宽度为 400 dp 的母版,以便在其中正确显示日历。

这是我做的:

共享库


我创建了一个 SplitViewPage,派生自 MasterDetail 页面:

<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CompApp.Views.SplitViewPage">
<MasterDetailPage.Master>
<ContentPage Title=" "/>
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<ContentPage Title=" "/>
</MasterDetailPage.Detail>
</MasterDetailPage>

安卓


由于主宽度在内部类“MasterDetailContainer”中是一个常量,我从基类复制了代码(参见 here)到名为“DroidMasterDetailContainer.cs”的新类,同时将类可见性从内部更改为公共(public)。

我对代码做了两处修改:

  1. 我将 const int DefaultMasterSize = 320 更改为 const int DefaultMasterSize = 400
  2. 我注释掉了行 _childView.ClearValue(Platform.RendererProperty);(第 116 行,位于 void DisposeChildRenderers() 中,因为 Platform.RendererProperty 不可访问

接下来要做的是将 MasterDetailRenderer 的代码(参见 here)复制到一个新类(在我的例子中为“SplitViewPageRenderer.cs”)

using System;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Support.V4.Widget;
using Android.Views;
using MyApp.Droid.Renderer;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Xamarin.Forms.Platform.Android.AppCompat;
using AColor = Android.Graphics.Drawables.ColorDrawable;

using AView = Android.Views.View;

[assembly: ExportRenderer(typeof(SplitViewPage), typeof(SplitViewPageRenderer))]
namespace MyApp.Droid.Renderer
{
public class SplitViewPageRenderer : DrawerLayout, IVisualElementRenderer, DrawerLayout.IDrawerListener
{
public SplitViewPageRenderer(Context context) : base(context)
{

}

//from Android source code
const uint DefaultScrimColor = 0x99000000;
int _currentLockMode = -1;
DroidMasterDetailContainer _detailLayout;
bool _isPresentingFromCore;
DroidMasterDetailContainer _masterLayout;
MasterDetailPage _page;
bool _presented;

[Obsolete("This constructor is obsolete as of version 2.5. Please use MasterDetailRenderer(Context) instead.")]
public SplitViewPageRenderer() : base(Forms.Context)
{
}

IMasterDetailPageController MasterDetailPageController => _page as IMasterDetailPageController;

public bool Presented
{
get { return _presented; }
set
{
if (value == _presented)
return;
UpdateSplitViewLayout();
_presented = value;
if (_page.MasterBehavior == MasterBehavior.Default && MasterDetailPageController.ShouldShowSplitMode)
return;
if (_presented)
OpenDrawer(_masterLayout);
else
CloseDrawer(_masterLayout);
}
}

IPageController MasterPageController => _page.Master as IPageController;
IPageController DetailPageController => _page.Detail as IPageController;
IPageController PageController => Element as IPageController;

public void OnDrawerClosed(AView drawerView)
{
}

public void OnDrawerOpened(AView drawerView)
{
}

public void OnDrawerSlide(AView drawerView, float slideOffset)
{
}

public void OnDrawerStateChanged(int newState)
{
_presented = IsDrawerVisible(_masterLayout);
UpdateIsPresented();
}

public VisualElement Element
{
get { return _page; }
}

public event EventHandler<VisualElementChangedEventArgs> ElementChanged;

event EventHandler<PropertyChangedEventArgs> ElementPropertyChanged;
event EventHandler<PropertyChangedEventArgs> IVisualElementRenderer.ElementPropertyChanged
{
add { ElementPropertyChanged += value; }
remove { ElementPropertyChanged -= value; }
}

public SizeRequest GetDesiredSize(int widthConstraint, int heightConstraint)
{
Measure(widthConstraint, heightConstraint);
return new SizeRequest(new Size(MeasuredWidth, MeasuredHeight));
}

public void SetElement(VisualElement element)
{
MasterDetailPage oldElement = _page;
_page = element as MasterDetailPage;

_detailLayout = new DroidMasterDetailContainer(_page, false, Context) { LayoutParameters = new LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent) };

_masterLayout = new DroidMasterDetailContainer(_page, true, Context)
{
LayoutParameters = new LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent) { Gravity = (int)GravityFlags.Start }
};

AddView(_detailLayout);

AddView(_masterLayout);

var activity = Context as Activity;
activity.ActionBar.SetDisplayShowHomeEnabled(true);
activity.ActionBar.SetHomeButtonEnabled(true);

UpdateBackgroundColor(_page);
UpdateBackgroundImage(_page);

OnElementChanged(oldElement, element);

if (oldElement != null)
((IMasterDetailPageController)oldElement).BackButtonPressed -= OnBackButtonPressed;

if (_page != null)
MasterDetailPageController.BackButtonPressed += OnBackButtonPressed;

if (Tracker == null)
Tracker = new VisualElementTracker(this);

_page.PropertyChanged += HandlePropertyChanged;
_page.Appearing += MasterDetailPageAppearing;
_page.Disappearing += MasterDetailPageDisappearing;

UpdateMaster();
UpdateDetail();

Device.Info.PropertyChanged += DeviceInfoPropertyChanged;
SetGestureState();

Presented = _page.IsPresented;

AddDrawerListener(this);

//if (element != null)
// element.SendViewInitialized(this);

if (element != null && !string.IsNullOrEmpty(element.AutomationId))
ContentDescription = element.AutomationId;
}

public VisualElementTracker Tracker { get; private set; }

public void UpdateLayout()
{
if (Tracker != null)
Tracker.UpdateLayout();
}

public ViewGroup ViewGroup => this;
AView IVisualElementRenderer.View => this;

protected override void Dispose(bool disposing)
{
if (disposing)
{
if (Tracker != null)
{
Tracker.Dispose();
Tracker = null;
}

if (_detailLayout != null)
{
_detailLayout.Dispose();
_detailLayout = null;
}

if (_masterLayout != null)
{
_masterLayout.Dispose();
_masterLayout = null;
}

Device.Info.PropertyChanged -= DeviceInfoPropertyChanged;

if (_page != null)
{
MasterDetailPageController.BackButtonPressed -= OnBackButtonPressed;
_page.PropertyChanged -= HandlePropertyChanged;
_page.Appearing -= MasterDetailPageAppearing;
_page.Disappearing -= MasterDetailPageDisappearing;
//_page.ClearValue(Platform.RendererProperty);
_page = null;
}
}

base.Dispose(disposing);
}

protected override void OnAttachedToWindow()
{
base.OnAttachedToWindow();
PageController.SendAppearing();
}

protected override void OnDetachedFromWindow()
{
base.OnDetachedFromWindow();
PageController.SendDisappearing();
}

protected virtual void OnElementChanged(VisualElement oldElement, VisualElement newElement)
{
EventHandler<VisualElementChangedEventArgs> changed = ElementChanged;
if (changed != null)
changed(this, new VisualElementChangedEventArgs(oldElement, newElement));
}

protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
//hack to make the split layout handle touches the full width
if (MasterDetailPageController.ShouldShowSplitMode && _masterLayout != null)
_masterLayout.Right = r;
}

async void DeviceInfoPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "CurrentOrientation")
{
if (!MasterDetailPageController.ShouldShowSplitMode && Presented)
{
MasterDetailPageController.CanChangeIsPresented = true;
//hack : when the orientation changes and we try to close the Master on Android
//sometimes Android picks the width of the screen previous to the rotation
//this leaves a little of the master visible, the hack is to delay for 50ms closing the drawer
await Task.Delay(50);
CloseDrawer(_masterLayout);
}
UpdateSplitViewLayout();
}
}

void HandleMasterPropertyChanged(object sender, PropertyChangedEventArgs e)
{
//if (e.PropertyName == Page.TitleProperty.PropertyName || e.PropertyName == Page.IconProperty.PropertyName)
//((Platform)_page.Platform).UpdateMasterDetailToggle(true);
}

void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
{
ElementPropertyChanged?.Invoke(this, e);
if (e.PropertyName == "Master")
UpdateMaster();
else if (e.PropertyName == "Detail")
{
UpdateDetail();
//((Platform)_page.Platform).UpdateActionBar();
}
else if (e.PropertyName == MasterDetailPage.IsPresentedProperty.PropertyName)
{
_isPresentingFromCore = true;
Presented = _page.IsPresented;
_isPresentingFromCore = false;
}
else if (e.PropertyName == "IsGestureEnabled")
SetGestureState();
else if (e.PropertyName == Page.BackgroundImageProperty.PropertyName)
UpdateBackgroundImage(_page);
if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
UpdateBackgroundColor(_page);
}

void MasterDetailPageAppearing(object sender, EventArgs e)
{
MasterPageController?.SendAppearing();
DetailPageController?.SendAppearing();
}

void MasterDetailPageDisappearing(object sender, EventArgs e)
{
MasterPageController?.SendDisappearing();
DetailPageController?.SendDisappearing();
}

void OnBackButtonPressed(object sender, BackButtonPressedEventArgs backButtonPressedEventArgs)
{
if (IsDrawerOpen((int)GravityFlags.Start))
{
if (_currentLockMode != LockModeLockedOpen)
{
CloseDrawer((int)GravityFlags.Start);
backButtonPressedEventArgs.Handled = true;
}
}
}

void SetGestureState()
{
SetDrawerLockMode(_page.IsGestureEnabled ? LockModeUnlocked : LockModeLockedClosed);
}

void IVisualElementRenderer.SetLabelFor(int? id)
{
}

void SetLockMode(int lockMode)
{
if (_currentLockMode != lockMode)
{
SetDrawerLockMode(lockMode);
_currentLockMode = lockMode;
}
}

void UpdateBackgroundColor(Page view)
{
if (view.BackgroundColor != Color.Default)
SetBackgroundColor(view.BackgroundColor.ToAndroid());
}

void UpdateBackgroundImage(Page view)
{
if (!string.IsNullOrEmpty(view.BackgroundImage))
this.SetBackground(Context.GetDrawable(view.BackgroundImage));
}

void UpdateDetail()
{
Context.HideKeyboard(this);
_detailLayout.ChildView = _page.Detail;
}

void UpdateIsPresented()
{
if (_isPresentingFromCore)
return;
if (Presented != _page.IsPresented)
((IElementController)_page).SetValueFromRenderer(MasterDetailPage.IsPresentedProperty, Presented);
}

void UpdateMaster()
{
if (_masterLayout != null && _masterLayout.ChildView != null)
_masterLayout.ChildView.PropertyChanged -= HandleMasterPropertyChanged;
_masterLayout.ChildView = _page.Master;
if (_page.Master != null)
_page.Master.PropertyChanged += HandleMasterPropertyChanged;
}

void UpdateSplitViewLayout()
{
if (Device.Idiom == TargetIdiom.Tablet)
{
bool isShowingSplit = MasterDetailPageController.ShouldShowSplitMode
|| (MasterDetailPageController.ShouldShowSplitMode && _page.MasterBehavior != MasterBehavior.Default && _page.IsPresented);
SetLockMode(isShowingSplit ? LockModeLockedOpen : LockModeUnlocked);
unchecked
{
SetScrimColor(isShowingSplit ? Color.Transparent.ToAndroid() : (int)DefaultScrimColor);
}
//((Platform)_page.Platform).UpdateMasterDetailToggle();
}
}
}
}

请注意,我们没有为变量 _masterLayout 和 _detailLayout 使用内部类“MasterDetailContainer”,而是使用之前创建的“DroidMasterDetailContainer”。

iOS


基本上是同一个故事:获取 MasterDetailRenderer 代码(请参阅 here),创建您自己的类,粘贴代码和一些稍后的改编:

using CompApp.Customs;
using MyApp.iOS.Renderer;
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using System.ComponentModel;
using CoreGraphics;
using MyApp.Views;
using UIKit;
using Xamarin.Forms.Internals;
using System.Reflection;

[assembly: ExportRenderer(typeof(SplitViewPage), typeof(SplitViewPageRenderer))]
namespace MyApp.iOS.Renderer
{
public class SplitViewPageRenderer : UISplitViewController, IVisualElementRenderer, IEffectControlProvider
{
UIViewController _detailController;

bool _disposed;
EventTracker _events;
InnerDelegate _innerDelegate;
public static nfloat MasterWidth = 400;
EventedViewController _masterController;

SplitViewPage _masterDetailPage;

bool _masterVisible;

VisualElementTracker _tracker;

Page PageController => Element as Page;
Element ElementController => Element as Element;

protected SplitViewPage MasterDetailPage => _masterDetailPage ?? (_masterDetailPage = (SplitViewPage)Element);

public VisualElement Element { get; private set; }

public event EventHandler<VisualElementChangedEventArgs> ElementChanged;

UIBarButtonItem PresentButton
{
get { return _innerDelegate == null ? null : _innerDelegate.PresentButton; }
}

public UIView NativeView
{
get { return View; }
}

protected virtual void OnElementChanged(VisualElementChangedEventArgs e)
{
if (e.OldElement != null)
e.OldElement.PropertyChanged -= HandlePropertyChanged;

if (e.NewElement != null)
{
e.NewElement.PropertyChanged += HandlePropertyChanged;
}

if (UIDevice.CurrentDevice.Orientation == UIDeviceOrientation.LandscapeLeft || UIDevice.CurrentDevice.Orientation == UIDeviceOrientation.LandscapeRight)
{
PreferredDisplayMode = UISplitViewControllerDisplayMode.AllVisible;
}
else if (UIDevice.CurrentDevice.Orientation == UIDeviceOrientation.Portrait || UIDevice.CurrentDevice.Orientation == UIDeviceOrientation.PortraitUpsideDown)
{
PreferredDisplayMode = UISplitViewControllerDisplayMode.PrimaryOverlay;
}

MasterWidth = 400;
MasterDetailPage.Master.WidthRequest = 400;

MasterDetailPage.UpdateMasterBehavior();

var changed = ElementChanged;
if (changed != null)
changed(this, e);

UpdateControllers();
}

public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
{
return NativeView.GetSizeRequest(widthConstraint, heightConstraint);
}

public void SetElement(VisualElement element)
{
var oldElement = Element;
Element = element;

ViewControllers = new[] { _masterController = new EventedViewController(), _detailController = new ChildViewController() };

Delegate = _innerDelegate = new InnerDelegate(MasterDetailPage.MasterBehavior);
Element.BackgroundColor = Color.Transparent;
UpdateControllers();

_masterController.WillAppear += MasterControllerWillAppear;
_masterController.WillDisappear += MasterControllerWillDisappear;

PresentsWithGesture = MasterDetailPage.IsGestureEnabled;

OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));

EffectUtilities.RegisterEffectControlProvider(this, oldElement, element);

if (element != null)
{
MethodInfo sendViewInitialized = typeof(Xamarin.Forms.Forms).GetMethod("SendViewInitialized", BindingFlags.Static | BindingFlags.NonPublic);
sendViewInitialized?.Invoke(element, new object[] { element, NativeView });
}
}

public void SetElementSize(Size size)
{
Element.Layout(new Rectangle(Element.X, Element.Width, size.Width, size.Height));
}

public UIViewController ViewController
{
get { return this; }
}

public override void ViewDidAppear(bool animated)
{
PageController.SendAppearing();
base.ViewDidAppear(animated);
ToggleMaster();
}

public override void ViewDidDisappear(bool animated)
{
base.ViewDidDisappear(animated);
PageController?.SendDisappearing();
}

public override void ViewDidLayoutSubviews()
{
if (View.Subviews.Length < 2)
return;

var frameBounds = View.Bounds;
var masterBounds = _masterController.View.Frame;
var detailsBounds = _detailController.View.Frame;

nfloat statusBarHeight = UIApplication.SharedApplication.StatusBarFrame.Height;
masterBounds.Width = 400;
MasterWidth = (nfloat)Math.Max(MasterWidth, masterBounds.Width);
if (Xamarin.Forms.Device.Idiom == TargetIdiom.Tablet)
{
bool interfaceInLandscape = UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.LandscapeLeft || UIApplication.SharedApplication.StatusBarOrientation == UIInterfaceOrientation.LandscapeRight;
if (UIDevice.CurrentDevice.Orientation == UIDeviceOrientation.LandscapeLeft || UIDevice.CurrentDevice.Orientation == UIDeviceOrientation.LandscapeRight || interfaceInLandscape)
{
detailsBounds.X = 400;
detailsBounds.Width = frameBounds.Width - 400;
}
else
{
detailsBounds.X = 0;
detailsBounds.Width = frameBounds.Width;
}
_detailController.View.Frame = detailsBounds;
_masterController.View.Frame = new CGRect(masterBounds.X, masterBounds.Y, masterBounds.Width, masterBounds.Height);
if (!masterBounds.IsEmpty)
{
MasterDetailPage.MasterBounds = new Rectangle(masterBounds.X, masterBounds.Y, masterBounds.Width, masterBounds.Height);
}

if (!detailsBounds.IsEmpty)
{
MasterDetailPage.DetailBounds = new Rectangle(detailsBounds.X, detailsBounds.Y, detailsBounds.Width, detailsBounds.Height);
}
_masterController.View.SetNeedsLayout();
_detailController.View.SetNeedsLayout();

}
else
{
if (!masterBounds.IsEmpty)
{
MasterDetailPage.MasterBounds = new Rectangle(MasterWidth, 0, MasterWidth, masterBounds.Height);
}

if (!detailsBounds.IsEmpty)
{
MasterDetailPage.DetailBounds = new Rectangle(0, 0, detailsBounds.Width, detailsBounds.Height);
}
}


}

public override void ViewDidLoad()
{
base.ViewDidLoad();
UpdateBackground();
UpdateFlowDirection();
_tracker = new VisualElementTracker(this);
_events = new EventTracker(this);
_events.LoadEvents(NativeView);
}

public override void ViewWillDisappear(bool animated)
{
if (_masterVisible)
PerformButtonSelector();

base.ViewWillDisappear(animated);
}

public override void ViewWillLayoutSubviews()
{
base.ViewWillLayoutSubviews();
_masterController.View.BackgroundColor = UIColor.White;
CGRect bounds = _masterController.View.Bounds;
CGRect frame = _masterController.View.Frame;
(this.ViewController as UISplitViewController).MinimumPrimaryColumnWidth = 400;
(this.ViewController as UISplitViewController).MaximumPrimaryColumnWidth = 400;
}

public override void WillRotate(UIInterfaceOrientation toInterfaceOrientation, double duration)
{
// On IOS8 the MasterViewController ViewAppear/Disappear weren't being called correctly after rotation
// We now close the Master by using the new SplitView API, basicly we set it to hidden and right back to the Normal/AutomaticMode
if (!MasterDetailPage.ShouldShowSplitMode && _masterVisible)
{
MasterDetailPage.CanChangeIsPresented = true;
PreferredDisplayMode = UISplitViewControllerDisplayMode.PrimaryHidden;
PreferredDisplayMode = UISplitViewControllerDisplayMode.Automatic;
}

var masterBounds = _masterController.View.Frame;
MessagingCenter.Send<IVisualElementRenderer>(this, "Xamarin.UpdateToolbarButtons");

MasterDetailPage.UpdateMasterBehavior();
base.WillRotate(toInterfaceOrientation, duration);
}

public override void DidRotate(UIInterfaceOrientation fromInterfaceOrientation)
{
base.DidRotate(fromInterfaceOrientation);
var masterBounds = _masterController.View.Frame;

MasterWidth = (nfloat)Math.Max(MasterWidth, masterBounds.Width);

if (!masterBounds.IsEmpty)
{
MasterDetailPage.MasterBounds = new Rectangle(MasterWidth, 0, MasterWidth, masterBounds.Height);
}
}

public override UIViewController ChildViewControllerForStatusBarHidden()
{
if (((MasterDetailPage)Element).Detail != null)
return (UIViewController)Platform.GetRenderer(((MasterDetailPage)Element).Detail);
else
return base.ChildViewControllerForStatusBarHidden();
}

void ClearControllers()
{
foreach (var controller in _masterController.ChildViewControllers)
{
controller.View.RemoveFromSuperview();
controller.RemoveFromParentViewController();
}

foreach (var controller in _detailController.ChildViewControllers)
{
controller.View.RemoveFromSuperview();
controller.RemoveFromParentViewController();
}
}

void HandleMasterPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == Page.IconProperty.PropertyName || e.PropertyName == Page.TitleProperty.PropertyName)
MessagingCenter.Send<IVisualElementRenderer>(this, "Xamarin.UpdateToolbarButtons");
}

void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (_tracker == null)
return;

if (e.PropertyName == "Master" || e.PropertyName == "Detail")
UpdateControllers();
else if (e.PropertyName == Xamarin.Forms.MasterDetailPage.IsPresentedProperty.PropertyName)
ToggleMaster();
else if (e.PropertyName == Xamarin.Forms.MasterDetailPage.IsGestureEnabledProperty.PropertyName)
base.PresentsWithGesture = this.MasterDetailPage.IsGestureEnabled;
else if (e.PropertyName == "FlowDirection")
UpdateFlowDirection();
MessagingCenter.Send<IVisualElementRenderer>(this, "Xamarin.UpdateToolbarButtons");
}

void MasterControllerWillAppear(object sender, EventArgs e)
{
_masterVisible = true;
if (MasterDetailPage.CanChangeIsPresented)
ElementController.SetValueFromRenderer(Xamarin.Forms.MasterDetailPage.IsPresentedProperty, true);
}

void MasterControllerWillDisappear(object sender, EventArgs e)
{
_masterVisible = false;
if (MasterDetailPage.CanChangeIsPresented)
ElementController.SetValueFromRenderer(Xamarin.Forms.MasterDetailPage.IsPresentedProperty, false);
}

void PerformButtonSelector()
{
DisplayModeButtonItem.Target.PerformSelector(DisplayModeButtonItem.Action, DisplayModeButtonItem, 0);
}

void ToggleMaster()
{
if (_masterVisible == MasterDetailPage.IsPresented || MasterDetailPage.ShouldShowSplitMode)
return;

PerformButtonSelector();
}

void UpdateBackground()
{
if (!string.IsNullOrEmpty(((Page)Element).BackgroundImage))
View.BackgroundColor = UIColor.FromPatternImage(UIImage.FromBundle(((Page)Element).BackgroundImage));
else if (Element.BackgroundColor == Color.Default)
View.BackgroundColor = UIColor.White;
else
View.BackgroundColor = Element.BackgroundColor.ToUIColor();
}

void UpdateControllers()
{
MasterDetailPage.Master.PropertyChanged -= HandleMasterPropertyChanged;

if (Platform.GetRenderer(MasterDetailPage.Master) == null)
Platform.SetRenderer(MasterDetailPage.Master, Platform.CreateRenderer(MasterDetailPage.Master));
if (Platform.GetRenderer(MasterDetailPage.Detail) == null)
Platform.SetRenderer(MasterDetailPage.Detail, Platform.CreateRenderer(MasterDetailPage.Detail));

ClearControllers();

MasterDetailPage.Master.PropertyChanged += HandleMasterPropertyChanged;

var master = Platform.GetRenderer(MasterDetailPage.Master).ViewController;
var detail = Platform.GetRenderer(MasterDetailPage.Detail).ViewController;

_masterController.View.AddSubview(master.View);
_masterController.AddChildViewController(master);

_detailController.View.AddSubview(detail.View);
_detailController.AddChildViewController(detail);
}

void UpdateFlowDirection()
{
bool ios9orLater = UIDevice.CurrentDevice.CheckSystemVersion(9, 0);

if (NativeView == null || View == null || !ios9orLater)
return;
View.SemanticContentAttribute = UISemanticContentAttribute.ForceLeftToRight;
}

class InnerDelegate : UISplitViewControllerDelegate
{
readonly MasterBehavior _masterPresentedDefaultState;

public InnerDelegate(MasterBehavior masterPresentedDefaultState)
{
_masterPresentedDefaultState = masterPresentedDefaultState;
}

public UIBarButtonItem PresentButton { get; set; }

public override bool ShouldHideViewController(UISplitViewController svc, UIViewController viewController, UIInterfaceOrientation inOrientation)
{
bool willHideViewController;
switch (_masterPresentedDefaultState)
{
case MasterBehavior.Split:
willHideViewController = false;
break;
case MasterBehavior.Popover:
willHideViewController = true;
break;
case MasterBehavior.SplitOnPortrait:
willHideViewController = !(inOrientation == UIInterfaceOrientation.Portrait || inOrientation == UIInterfaceOrientation.PortraitUpsideDown);
break;
default:
willHideViewController = inOrientation == UIInterfaceOrientation.Portrait || inOrientation == UIInterfaceOrientation.PortraitUpsideDown;
break;
}
return willHideViewController;
}

public override void WillHideViewController(UISplitViewController svc, UIViewController aViewController, UIBarButtonItem barButtonItem, UIPopoverController pc)
{
PresentButton = barButtonItem;
}
}

void IEffectControlProvider.RegisterEffect(Effect effect)
{
VisualElementRenderer<VisualElement>.RegisterEffect(effect, View);
}

protected override void Dispose(bool disposing)
{
if (_disposed)
{
return;
}

_disposed = true;

if (disposing)
{
if (Element != null)
{
PageController.SendDisappearing();
Element.PropertyChanged -= HandlePropertyChanged;

if (MasterDetailPage?.Master != null)
{
MasterDetailPage.Master.PropertyChanged -= HandleMasterPropertyChanged;
}

Element = null;
}

if (_tracker != null)
{
_tracker.Dispose();
_tracker = null;
}

if (_events != null)
{
_events.Dispose();
_events = null;
}

if (_masterController != null)
{
_masterController.WillAppear -= MasterControllerWillAppear;
_masterController.WillDisappear -= MasterControllerWillDisappear;
}

ClearControllers();
}

base.Dispose(disposing);
}
}

internal class ChildViewController : UIViewController
{
public override void ViewDidLayoutSubviews()
{
foreach (var vc in ChildViewControllers)
{
CGRect rect = View.Bounds;
vc.View.Frame = rect;
}
}
}

internal class EventedViewController : ChildViewController
{
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);

var eh = WillAppear;
if (eh != null)
eh(this, EventArgs.Empty);
}

public override void ViewWillDisappear(bool animated)
{
base.ViewWillDisappear(animated);

var eh = WillDisappear;
if (eh != null)
eh(this, EventArgs.Empty);
}

public override void ViewDidLayoutSubviews()
{
CGRect rect = View.Bounds;
View.Bounds = rect;

foreach (var vc in ChildViewControllers)
{
rect = vc.View.Frame;
vc.View.Frame = rect;

rect = vc.View.Bounds;
vc.View.Bounds = rect;

}
}

public event EventHandler WillAppear;

public event EventHandler WillDisappear;
}
}

我只使用了 TabletMasterDetailRenderer,因为我使用 MasterDetailView 为平板电脑设备创建了一个特定的 View ,在主视图中包含一个日历 View ,并在详细 View 中显示所选条目的详细信息。

如果您需要它用于手机,请使用 PhoneMasterDetailRenderer 进行相同的更改应该也能正常工作。

关于c# - 如何在 xamarin 表单中设置 MasterDetailPage 的宽度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40400002/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com