我有一个带有Xamarin.Forms的FreshMvvm应用程序,我使用二级ToolbarItems。要在iOS中实现它,我必须做一个定制的渲染器(与安卓系统不同)。我得到了一个关于如何在这里实现它的解决方案:ToolbarItems do not look right in iOS
这个解决方案对我来说非常有效。但到了现在,工具栏菜单越来越长,其中一些元素不适合iPhone的屏幕。我可以滑动菜单并看到所有的元素,但是一旦我释放屏幕,视图就会跳回来,当它被手指控制时,这些元素是不可点击的。如何解决这一问题?菜单能包起来吗?或者别的什么?在Android上,菜单停留在我滚动的位置,我可以点击每个项目。它也能让iOS上滚动的地方停留吗?
这是我渲染者的代码:
using CoreGraphics;
using MobileApp.iOS.Renderers;
using MobileApp.iOS.Services;
using MobileApp.Pages;
using MobileApp.Services;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(CustomToolbarContentPage),
typeof(RightToolbarMenuCustomRenderer))]
namespace MobileApp.iOS.Renderers
{
class RightToolbarMenuCustomRenderer : PageRenderer
{
private List<ToolbarItem> _primaryItems;
private List<ToolbarItem> _secondaryItems;
private UITableView _table;
private UITapGestureRecognizer _tapGestureRecognizer;
private UIView _transparentView;
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
if (e.NewElement is IAddToolbarItem item)
{
item.ToolbarItemAdded += Item_ToolbarItemAdded;
}
base.OnElementChanged(e);
}
private void Item_ToolbarItemAdded(object sender, System.EventArgs e)
{
if (Element is ContentPage page)
{
_primaryItems = page.ToolbarItems.Where(i => i.Order == ToolbarItemOrder.Primary).ToList();
_secondaryItems = page.ToolbarItems.Where(i => i.Order == ToolbarItemOrder.Secondary).ToList();
_secondaryItems.ForEach(t => page.ToolbarItems.Remove(t));
}
var element = (ContentPage)Element;
if (_secondaryItems?.Count == 0 && element.ToolbarItems.Any(a => (a.IconImageSource as FileImageSource)?.File == "more.png"))
{
element.ToolbarItems.Clear();
}
else if (_secondaryItems?.Count >= 1 && !element.ToolbarItems.Any(a => (a.IconImageSource as FileImageSource)?.File == "more.png"))
{
element.ToolbarItems.Add(new ToolbarItem()
{
Order = ToolbarItemOrder.Primary,
IconImageSource = "more.png",
Priority = 1,
Command = new Command(ToggleDropDownMenuVisibility)
});
}
}
private void ToggleDropDownMenuVisibility()
{
if (!DoesTableExist())
{
if ((View?.Subviews != null)
&& (View.Subviews.Length > 0)
&& (View.Bounds != null)
&& (_secondaryItems != null)
&& (_secondaryItems.Count > 0))
{
_table = OpenDropDownMenu(Element as IAddToolbarItem);
Add(_table);
}
}
else
CloseDropDownMenu();
}
private bool DoesTableExist()
{
if (View?.Subviews != null)
{
foreach (var subview in View.Subviews)
{
if (_table != null && subview == _table)
{
return true;
}
}
}
if (_tapGestureRecognizer != null)
{
_transparentView?.RemoveGestureRecognizer(_tapGestureRecognizer);
_tapGestureRecognizer = null;
}
_table = null;
_tapGestureRecognizer = null;
return false;
}
private UITableView OpenDropDownMenu(IAddToolbarItem secondaryMenuSupport)
{
_transparentView = _transparentView = new UIView(new CGRect(0, 0, View.Bounds.Width, View.Bounds.Height))
{
BackgroundColor = UIColor.FromRGBA(0, 0, 0, 0)
};
_tapGestureRecognizer = new UITapGestureRecognizer(CloseDropDownMenu);
_transparentView.AddGestureRecognizer(_tapGestureRecognizer);
Add(_transparentView);
UITableView table = null;
if (_secondaryItems != null && _secondaryItems.Count > 0)
{
table = new UITableView(GetPositionForDropDownMenu(secondaryMenuSupport.RowHeight, secondaryMenuSupport.TableWidth))
{
Source = new TableSource(_secondaryItems, _transparentView),
ClipsToBounds = false
};
table.ScrollEnabled = true;
table.Layer.ShadowColor = secondaryMenuSupport.ShadowColor.ToCGColor();
table.Layer.ShadowOpacity = secondaryMenuSupport.ShadowOpacity;
table.Layer.ShadowRadius = secondaryMenuSupport.ShadowRadius;
table.Layer.ShadowOffset = new SizeF(secondaryMenuSupport.ShadowOffsetDimension, secondaryMenuSupport.ShadowOffsetDimension);
table.BackgroundColor = secondaryMenuSupport.MenuBackgroundColor.ToUIColor();
}
return table;
}
public override void ViewWillDisappear(bool animated)
{
CloseDropDownMenu();
base.ViewWillDisappear(animated);
}
private RectangleF GetPositionForDropDownMenu(float rowHeight, float tableWidth)
{
if ((View?.Bounds != null)
&& (_secondaryItems != null)
&& (_secondaryItems.Count > 0))
{
return new RectangleF(
(float)View.Bounds.Width - tableWidth,
0,
tableWidth,
_secondaryItems.Count() * rowHeight);
}
else
{
return new RectangleF(0.0f, 0.0f, 0.0f, 0.0f);
}
}
private void CloseDropDownMenu()
{
if (_table != null)
{
if (_tapGestureRecognizer != null)
{
_transparentView?.RemoveGestureRecognizer(_tapGestureRecognizer);
_tapGestureRecognizer = null;
}
if (View?.Subviews != null)
{
foreach (var subview in View.Subviews)
{
if (subview == _table)
{
_table.RemoveFromSuperview();
break;
}
}
if (_transparentView != null)
{
foreach (var subview in View.Subviews)
{
if (subview == _transparentView)
{
_transparentView.RemoveFromSuperview();
break;
}
}
}
}
_table = null;
_transparentView = null;
}
}
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
if (_table != null)
{
if (Element is IAddToolbarItem secondaryMenuSupport)
PositionExistingDropDownMenu(secondaryMenuSupport.RowHeight, secondaryMenuSupport.TableWidth);
}
}
private void PositionExistingDropDownMenu(float rowHeight, float tableWidth)
{
if ((View?.Bounds != null)
&& (_secondaryItems != null)
&& (_secondaryItems.Count > 0)
&& (_table != null))
{
_table.Frame = GetPositionForDropDownMenu(rowHeight, tableWidth);
}
}
}
}增添:
public class TableSource : UITableViewSource
{
List<ToolbarItem> _tableItems;
string[] _tableItemTexts;
string CellIdentifier = "TableCell";
UIView _tableSuperView = null;
public TableSource(List<ToolbarItem> items, UIView tableSuperView)
{
_tableItems = items;
_tableSuperView = tableSuperView;
_tableItemTexts = items.Select(a => a.Text).ToArray();
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return _tableItemTexts?.Length ?? 0;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell(CellIdentifier);
string item = _tableItemTexts[indexPath.Row];
if (cell == null)
{ cell = new UITableViewCell(UITableViewCellStyle.Default, CellIdentifier); }
cell.TextLabel.Text = item;
return cell;
}
public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
return 56;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
var command = _tableItems[indexPath.Row].Command;
command.Execute(_tableItems[indexPath.Row].CommandParameter);
tableView.DeselectRow(indexPath, true);
tableView.RemoveFromSuperview();
if (_tableSuperView != null)
{
_tableSuperView.RemoveFromSuperview();
}
}
}
public interface IAddToolbarItem
{
event EventHandler ToolbarItemAdded;
Color CellBackgroundColor { get; }
Color CellTextColor { get; }
Color MenuBackgroundColor { get; }
float RowHeight { get; }
Color ShadowColor { get; }
float ShadowOpacity { get; }
float ShadowRadius { get; }
float ShadowOffsetDimension { get; }
float TableWidth { get; }
}在这里,您可以下载复制问题的项目:https://github.com/DavidShochet/Public
发布于 2020-04-24 02:10:31
好吧,我还是不能用你更新的代码重现问题。如果这是一个解决方案的话,我不知道,我只想在这里澄清我的评论。
在代码中,将_table添加到视图中:
_table = OpenDropDownMenu(Element as IAddToolbarItem);
Add(_table);我希望您尝试的是将_table添加到_transparentView中:
_table = OpenDropDownMenu(Element as IAddToolbarItem);
//Add(_table);
_transparentView.Add(_table);如果您能提供一个最小的、可复制的示例,这样我就可以在我这一边调试它,这样会更好。
更新:
我发现问题在这里,您设置了表_secondaryItems.Count() * rowHeight)的高度,它比工具栏菜单变长时的视图更长:
private RectangleF GetPositionForDropDownMenu(float rowHeight, float tableWidth)
{
if ((View?.Bounds != null)
&& (_secondaryItems != null)
&& (_secondaryItems.Count > 0))
{
return new RectangleF(
(float)View.Bounds.Width - tableWidth,
0,
tableWidth,
//here is the cause
_secondaryItems.Count() * rowHeight);
}
else
{
return new RectangleF(0.0f, 0.0f, 0.0f, 0.0f);
}
}解决方案:将tablview的高度更改为(float)View.Bounds.Height
private RectangleF GetPositionForDropDownMenu(float rowHeight, float tableWidth)
{
if ((View?.Bounds != null)
&& (_secondaryItems != null)
&& (_secondaryItems.Count > 0))
{
return new RectangleF(
(float)View.Bounds.Width - tableWidth,
0,
tableWidth,
(float)View.Bounds.Height);
}
else
{
return new RectangleF(0.0f, 0.0f, 0.0f, 0.0f);
}
}https://stackoverflow.com/questions/61367159
复制相似问题