gpt4 book ai didi

xamarin.forms - 如何在自定义呈现器中呈现 xamarin.forms View

转载 作者:行者123 更新时间:2023-12-04 02:48:34 25 4
gpt4 key购买 nike

我有以下代码:

共享项目:

using System;
using Xamarin.Forms;

namespace XamarinForms.Framework.Controls
{
public enum DrawerPosition
{
Left,
Right
}

public interface ISideDrawerNativeEventProxy
{
void RaiseSlideChanged(float percentage);
}

public class SideDrawer : Grid, ISideDrawerNativeEventProxy
{
#region DrawerSize

public static BindableProperty DrawerSizeProperty = BindableProperty.Create<SideDrawer, MaxedPercentSize>(d => d.DrawerSize, new MaxedPercentSize(MaxedPercentSizeType.Width, 80, 400));

public MaxedPercentSize DrawerSize
{
get { return (MaxedPercentSize) GetValue(DrawerSizeProperty); }
set { SetValue(DrawerSizeProperty, value); }
}

#endregion DrawerSize

#region IsOpen

public static BindableProperty IsOpenProperty = BindableProperty.Create<SideDrawer, bool>(d => d.IsOpen, default(bool));

public bool IsOpen
{
get { return (bool) GetValue(IsOpenProperty); }
set { SetValue(IsOpenProperty, value); }
}

#endregion IsOpen

#region DrawerPosition

public static BindableProperty DrawerPositionProperty = BindableProperty.Create<SideDrawer, DrawerPosition>(d => d.DrawerPosition, default(DrawerPosition));

public DrawerPosition DrawerPosition
{
get { return (DrawerPosition) GetValue(DrawerPositionProperty); }
set { SetValue(DrawerPositionProperty, value); }
}

#endregion DrawerPosition

public static BindableProperty MainContentProperty = BindableProperty.Create<SideDrawer, View>(d => d.MainContent, default(View));

public View MainContent
{
get { return (View) GetValue(MainContentProperty); }
set { SetValue(MainContentProperty, value); }
}

public static BindableProperty DrawerContentProperty = BindableProperty.Create<SideDrawer, View>(d => d.DrawerContent, default(View));

public View DrawerContent
{
get { return (View) GetValue(DrawerContentProperty); }
set { SetValue(DrawerContentProperty, value); }
}

#region DrawerLength

public static BindableProperty DrawerLengthProperty = BindableProperty.Create<SideDrawer, int>(d => d.DrawerLength, default(int), defaultValueCreator: DrawerLengthDefault);

private static int DrawerLengthDefault(SideDrawer bindable)
{
return 300;
}

public int DrawerLength
{
get { return (int) GetValue(DrawerLengthProperty); }
set { SetValue(DrawerLengthProperty, value); }
}

#endregion DrawerLength

#region IsContentTranslated

public static BindableProperty IsContentTranslatedProperty = BindableProperty.Create<SideDrawer, bool>(d => d.IsContentTranslated, true);

public bool IsContentTranslated
{
get { return (bool) GetValue(IsContentTranslatedProperty); }
set { SetValue(IsContentTranslatedProperty, value); }
}

#endregion IsContentTranslated

void ISideDrawerNativeEventProxy.RaiseSlideChanged(float percentage)
{
}
}
}

安卓:

using System;
using System.ComponentModel;
using Android.Support.V4.Widget;
using Android.Views;
using Android.Widget;
using Mobile.XamarinForms.Droid.Controls.SideDrawer;
using Mobile.XamarinForms.Framework.Controls;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Android.Graphics;
using Application = Android.App.Application;
using Color = Android.Graphics.Color;
using RelativeLayout = Android.Widget.RelativeLayout;
using View = Android.Views.View;

[assembly: ExportRenderer(typeof(SideDrawer), typeof(SideDrawerRenderer))]
namespace Mobile.XamarinForms.Droid.Controls.SideDrawer
{
// public class SideDrawerRenderer : Xamarin.Forms.Platform.Android.AppCompat.ViewRenderer<Framework.Controls.SideDrawer, DrawerLayout>, DrawerLayout.IDrawerListener
public class SideDrawerRenderer : ViewRenderer<Framework.Controls.SideDrawer, DrawerLayout>, DrawerLayout.IDrawerListener
{
private DrawerLayout _nativeDrawerLayout;
private MarginLayoutParams _contentLayoutParameters;
private RelativeLayout _contentView;
private TextView _drawerView;

protected override void OnElementChanged(ElementChangedEventArgs<Framework.Controls.SideDrawer> e)
{
base.OnElementChanged(e);

if (this.Control == null)
{
InitializeNativeControl();
}
if (e.OldElement != null)
{
_nativeDrawerLayout.SetDrawerListener(null);
}
if (e.NewElement != null)
{
_nativeDrawerLayout.SetDrawerListener(this);
}
}

private void InitializeNativeControl()
{
_nativeDrawerLayout = new DrawerLayout(Context.ApplicationContext);
_nativeDrawerLayout.SetBackgroundColor(Element.BackgroundColor.ToAndroid());


_contentLayoutParameters = new MarginLayoutParams(LayoutParams.MatchParent, LayoutParams.MatchParent);
var layoutParamsDrawer = new DrawerLayout.LayoutParams(Element.DrawerLength, LinearLayout.LayoutParams.MatchParent);
layoutParamsDrawer.Gravity = GetDrawerGravity();

_drawerView = GetDrawerView(layoutParamsDrawer);
_contentView = GetContentView(_contentLayoutParameters);

// this one works, but i need the content from my forms property
var contentChild = new RelativeLayout(Context.ApplicationContext);
var contentChildLParams = new RelativeLayout.LayoutParams(300, 300);
contentChild.SetBackgroundColor(Color.Yellow);
_contentView.AddView(contentChild, contentChildLParams);

// i need to figure out how to make this work
// var contentRenderer = RendererFactory.GetRenderer(Element.MainContent);
// _contentView.AddView(contentRenderer.ViewGroup, new LayoutParams(LayoutParams.MatchParent, LayoutParams.MatchParent));

_nativeDrawerLayout.AddView(_drawerView);
_nativeDrawerLayout.AddView(_contentView);

SetNativeControl(_nativeDrawerLayout);
}

private int GetDrawerGravity()
{
switch (Element.DrawerPosition)
{
case DrawerPosition.Left:
return (int)GravityFlags.Start;
case DrawerPosition.Right:
return (int)GravityFlags.End;
default:
throw new ArgumentOutOfRangeException();
}
}

private RelativeLayout GetContentView(LayoutParams layoutParameters)
{
var view = new RelativeLayout(Context.ApplicationContext);
view.LayoutParameters = layoutParameters;
view.SetBackgroundColor(Color.Red);
return view;
}

private TextView GetDrawerView(LayoutParams layoutParameters)
{
var view = new TextView(Context.ApplicationContext);
view.LayoutParameters = layoutParameters;
view.SetBackgroundColor(Color.Purple);
view.SetTextColor(Color.Blue);
view.SetText("just some text", TextView.BufferType.Editable);
return view;
}

protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);

switch (e.PropertyName)
{
case nameof(Framework.Controls.SideDrawer.Height):
break;
case nameof(Framework.Controls.SideDrawer.Width):
break;
}
}

public void OnDrawerClosed(View drawerView)
{
Element.IsOpen = false;
System.Diagnostics.Debug.WriteLine("OnDrawerClosed");
}

public void OnDrawerOpened(View drawerView)
{
Element.IsOpen = true;
System.Diagnostics.Debug.WriteLine("OnDrawerOpened");
}

public void OnDrawerSlide(View drawerView, float slideOffset)
{
switch (Element.DrawerPosition)
{
case DrawerPosition.Left:
_contentView.TranslationX = (int) Math.Abs(Element.DrawerLength*slideOffset);
break;
case DrawerPosition.Right:
_contentView.TranslationX = (int) Math.Abs(Element.DrawerLength*slideOffset)*-1;
break;
default:
throw new ArgumentOutOfRangeException();
}

_nativeDrawerLayout.BringChildToFront(_drawerView);
_nativeDrawerLayout.RequestLayout();

((ISideDrawerNativeEventProxy) Element)?.RaiseSlideChanged(slideOffset);
}

public void OnDrawerStateChanged(int newState)
{
// not really needed
// System.Diagnostics.Debug.WriteLine($"OnDrawerStateChanged {newState}");
}
}
}

我如何输出例如的内容MainContent(共享项目属性)?

我无法在 xamarin 文档中找到任何关于此的信息,到目前为止,关于这个主题的支持相当安静(我猜他们太忙了)。

有人遇到过这个问题吗?

更新:Reproduction solution

最佳答案

安卓容器:

internal sealed class FormsElementWrapper : FormsViewGroup
{
public override bool OnInterceptTouchEvent(MotionEvent ev)
{
return false;
}

private readonly IVisualElementRenderer _view;

public FormsElementWrapper(Xamarin.Forms.View content) : base(Application.Context)
{
_view = content != null ? Platform.CreateRenderer(content) : null;
if (_view == null)
return;
AddView(_view.ViewGroup);
}

protected override void OnLayout(bool changed, int left, int top, int right, int bottom)
{
if (_view == null)
return;
_view.Element.Layout(new Rectangle(0.0, 0.0, ContextExtensions.FromPixels(Context, right - left), ContextExtensions.FromPixels(Context, bottom - top)));
_view.UpdateLayout();
}

protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
MeasureSpecMode widthMode = MeasureSpec.GetMode(widthMeasureSpec);
MeasureSpecMode heightMode = MeasureSpec.GetMode(heightMeasureSpec);
int widthSize = MeasureSpec.GetSize(widthMeasureSpec);
int heightSize = MeasureSpec.GetSize(heightMeasureSpec);
int pxHeight = (int) ContextExtensions.ToPixels(Context, _view.Element.HeightRequest);
int pxWidth = (int) ContextExtensions.ToPixels(Context, _view.Element.WidthRequest);
var measuredWidth = widthMode != MeasureSpecMode.Exactly ? (widthMode != MeasureSpecMode.AtMost ? pxHeight : Math.Min(pxHeight, widthSize)) : widthSize;
var measuredHeight = heightMode != MeasureSpecMode.Exactly ? (heightMode != MeasureSpecMode.AtMost ? pxWidth : Math.Min(pxWidth, heightSize)) : heightSize;
SetMeasuredDimension(measuredWidth, measuredHeight);
}
}

安卓抽屉:

using System;
using System.ComponentModel;
using Android.Support.V4.Widget;
using Android.Views;
using Android.Widget;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Color = Android.Graphics.Color;
using RelativeLayout = Android.Widget.RelativeLayout;
using View = Android.Views.View;

[assembly: ExportRenderer(typeof(SideDrawer), typeof(SideDrawerRenderer))]
namespace MyNamespace.SideDrawer
{
public class SideDrawerRenderer : ViewRenderer<SideDrawer, DrawerLayout>, DrawerLayout.IDrawerListener
{
private DrawerLayout _nativeDrawerLayout;
private FormsElementWrapper _contentView;
private FormsElementWrapper _drawerView;

protected override void OnElementChanged(ElementChangedEventArgs<Framework.Controls.SideDrawer> e)
{
base.OnElementChanged(e);

if (this.Control == null)
{
InitializeNativeControl();
}
if (e.OldElement != null)
{
_nativeDrawerLayout.SetDrawerListener(null);
}
if (e.NewElement != null)
{
_nativeDrawerLayout.SetDrawerListener(this);
}
}

private void InitializeNativeControl()
{
_nativeDrawerLayout = new DrawerLayout(Context.ApplicationContext);
_nativeDrawerLayout.SetBackgroundColor(Element.BackgroundColor.ToAndroid());

AddDrawerLayer(_nativeDrawerLayout);
AddContentLayer(_nativeDrawerLayout);

SetNativeControl(_nativeDrawerLayout);
}

private void AddContentLayer(DrawerLayout nativeDrawerLayout)
{
_contentView = new FormsElementWrapper(Element.MainContent);

nativeDrawerLayout.AddView(_contentView);
}

private void AddDrawerLayer(DrawerLayout nativeDrawerLayout)
{
_drawerView = new FormsElementWrapper(Element.DrawerContent);
UpdateDrawerLength();

nativeDrawerLayout.AddView(_drawerView);
}

private int GetDrawerGravity()
{
switch (Element.DrawerPosition)
{
case DrawerPosition.Left:
return (int)GravityFlags.Start;
case DrawerPosition.Right:
return (int)GravityFlags.End;
default:
throw new ArgumentOutOfRangeException();
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);

switch (e.PropertyName)
{
case nameof(Framework.Controls.SideDrawer.Height):
break;
case nameof(Framework.Controls.SideDrawer.Width):
break;
case nameof(Framework.Controls.SideDrawer.MainContent):
_contentView = new FormsElementWrapper(Element.MainContent);
break;
case nameof(Framework.Controls.SideDrawer.DrawerContent):
_drawerView = new FormsElementWrapper(Element.DrawerContent);
break;
case nameof(Framework.Controls.SideDrawer.IsOpen):
UpdateDrawerStateProgramatically();
break;
case nameof(Framework.Controls.SideDrawer.DrawerLength):
case nameof(Framework.Controls.SideDrawer.DrawerPosition):
UpdateDrawerLength();
break;
}
}

private void UpdateDrawerLength()
{
var layoutParamsDrawer = new DrawerLayout.LayoutParams(Element.DrawerLength, ViewGroup.LayoutParams.MatchParent);
layoutParamsDrawer.Gravity = GetDrawerGravity();
_drawerView.LayoutParameters = layoutParamsDrawer;
}

private void UpdateDrawerStateProgramatically()
{
if (Element.IsOpen)
{
Control.OpenDrawer(GetDrawerGravity());
}
else
{
Control.CloseDrawer(GetDrawerGravity());
}
}

public void OnDrawerClosed(View drawerView)
{
Element.IsOpen = false;
System.Diagnostics.Debug.WriteLine("OnDrawerClosed");
}

public void OnDrawerOpened(View drawerView)
{
Element.IsOpen = true;
System.Diagnostics.Debug.WriteLine("OnDrawerOpened");
}

public void OnDrawerSlide(View drawerView, float slideOffset)
{
switch (Element.DrawerPosition)
{
case DrawerPosition.Left:
_contentView.TranslationX = (int)Math.Abs(Element.DrawerLength * slideOffset);
break;
case DrawerPosition.Right:
_contentView.TranslationX = (int)Math.Abs(Element.DrawerLength * slideOffset) * -1;
break;
default:
throw new ArgumentOutOfRangeException();
}

_nativeDrawerLayout.BringChildToFront(_drawerView);
_nativeDrawerLayout.RequestLayout();

((ISideDrawerNativeEventProxy)Element)?.RaiseSlideChanged(slideOffset);
}

public void OnDrawerStateChanged(int newState)
{
}
}
}

Xamarin.Forms 控件:

public enum DrawerPosition
{
Left,
Right
}

public interface ISideDrawerNativeEventProxy
{
void RaiseSlideChanged(float percentage);
}

public class SideDrawer : Grid, ISideDrawerNativeEventProxy
{
#region IsOpen

public static BindableProperty IsOpenProperty = BindableProperty.Create<SideDrawer, bool>(d => d.IsOpen, default(bool), defaultBindingMode: BindingMode.TwoWay);

public bool IsOpen
{
get { return (bool) GetValue(IsOpenProperty); }
set { SetValue(IsOpenProperty, value); }
}

#endregion IsOpen

#region DrawerPosition

public static BindableProperty DrawerPositionProperty = BindableProperty.Create<SideDrawer, DrawerPosition>(d => d.DrawerPosition, default(DrawerPosition));

public DrawerPosition DrawerPosition
{
get { return (DrawerPosition) GetValue(DrawerPositionProperty); }
set { SetValue(DrawerPositionProperty, value); }
}

#endregion DrawerPosition

public static BindableProperty MainContentProperty = BindableProperty.Create<SideDrawer, View>(d => d.MainContent, default(View), propertyChanging: MainContentPropertyChanging, propertyChanged: MainContentPropertyChanged);

private static void MainContentPropertyChanged(BindableObject bindable, View oldValue, View newValue)
{
if (newValue == null)
return;
newValue.Parent = (View)bindable;
}

private static void MainContentPropertyChanging(BindableObject bindable, View oldValue, View newValue)
{
if (oldValue == null)
return;
oldValue.Parent = null;
}

public View MainContent
{
get { return (View) GetValue(MainContentProperty); }
set { SetValue(MainContentProperty, value); }
}

public static BindableProperty DrawerContentProperty = BindableProperty.Create<SideDrawer, View>(d => d.DrawerContent, default(View), propertyChanging: DrawerContentPropertyChanging, propertyChanged: DrawerContentPropertyChanged);

private static void DrawerContentPropertyChanged(BindableObject bindable, View oldValue, View newValue)
{
if (newValue == null)
return;
newValue.Parent = (View)bindable;
}

private static void DrawerContentPropertyChanging(BindableObject bindable, View oldValue, View newValue)
{
if (oldValue == null)
return;
oldValue.Parent = null;
}

public View DrawerContent
{
get { return (View) GetValue(DrawerContentProperty); }
set { SetValue(DrawerContentProperty, value); }
}

#region DrawerLength

public static BindableProperty DrawerLengthProperty = BindableProperty.Create<SideDrawer, int>(d => d.DrawerLength, default(int), defaultValueCreator: DrawerLengthDefault);

private static int DrawerLengthDefault(SideDrawer bindable)
{
return 300;
}

public int DrawerLength
{
get { return (int) GetValue(DrawerLengthProperty); }
set { SetValue(DrawerLengthProperty, value); }
}

#endregion DrawerLength

#region IsContentTranslated

public static BindableProperty IsContentTranslatedProperty = BindableProperty.Create<SideDrawer, bool>(d => d.IsContentTranslated, true);

public bool IsContentTranslated
{
get { return (bool) GetValue(IsContentTranslatedProperty); }
set { SetValue(IsContentTranslatedProperty, value); }
}

#endregion IsContentTranslated

void ISideDrawerNativeEventProxy.RaiseSlideChanged(float percentage)
{
}

protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();

if (MainContent != null)
SetInheritedBindingContext(MainContent, BindingContext);
if (DrawerContent != null)
SetInheritedBindingContext(DrawerContent, BindingContext);
}
}

我最初实现的主要缺陷是:

  • 缺少正在转发的测量数据
  • 不转发父层次结构
  • 不继承bindingcontext

关于xamarin.forms - 如何在自定义呈现器中呈现 xamarin.forms View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34264295/

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