次要工具栏项目不适合屏幕

问题描述 投票:0回答:1

我有一个使用FreshMvvm的Xamarin.Forms应用,我使用了二级ToolbarItems。为了在iOS中做到这一点,我不得不做一个自定义的渲染器(与Android中不同)。在这里给了我一个如何实现它的解决方案。在iOS中,ToolbarItems看起来并不正确。

这个解决方案对我来说是完美的。但是到了现在,工具栏菜单变长了,其中的一些元素不适合iPhone的屏幕。我可以滑动菜单,看到所有的元素,但只要我一松开屏幕,视图就会重新跳起来,虽然用手指握住它,但元素却无法点击。请问如何解决这个问题?能不能把菜单做成包起来,或者是其他的?在安卓系统上,菜单停留在我滚动的地方,我可以点击每个项目。在安卓系统上,菜单停留在我滚动的地方,我可以点击每一个项目。在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);
        }
    }
}
}

ADDITION:

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.comDavidShochetPublic)。

xamarin.forms xamarin.ios
1个回答
1
投票

好吧,我还是不能用你更新的代码重现这个问题。我不知道这是否是一个解决方案,我只是想澄清一下我的评论。

在你的代码中,你添加了 _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);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.