首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >辅助工具栏项不适合屏幕

辅助工具栏项不适合屏幕
EN

Stack Overflow用户
提问于 2020-04-22 14:07:52
回答 1查看 238关注 0票数 0

我有一个带有Xamarin.Forms的FreshMvvm应用程序,我使用二级ToolbarItems。要在iOS中实现它,我必须做一个定制的渲染器(与安卓系统不同)。我得到了一个关于如何在这里实现它的解决方案:ToolbarItems do not look right in iOS

这个解决方案对我来说非常有效。但到了现在,工具栏菜单越来越长,其中一些元素不适合iPhone的屏幕。我可以滑动菜单并看到所有的元素,但是一旦我释放屏幕,视图就会跳回来,当它被手指控制时,这些元素是不可点击的。如何解决这一问题?菜单能包起来吗?或者别的什么?在Android上,菜单停留在我滚动的位置,我可以点击每个项目。它也能让iOS上滚动的地方停留吗?

这是我渲染者的代码:

代码语言:javascript
复制
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);
        }
    }
}
}

增添:

代码语言:javascript
复制
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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-24 02:10:31

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

在代码中,将_table添加到视图中:

代码语言:javascript
复制
 _table = OpenDropDownMenu(Element as IAddToolbarItem);
 Add(_table);

我希望您尝试的是将_table添加到_transparentView中:

代码语言:javascript
复制
  _table = OpenDropDownMenu(Element as IAddToolbarItem);
  //Add(_table);
  _transparentView.Add(_table);

如果您能提供一个最小的、可复制的示例,这样我就可以在我这一边调试它,这样会更好。

更新:

我发现问题在这里,您设置了表_secondaryItems.Count() * rowHeight)的高度,它比工具栏菜单变长时的视图更长:

代码语言:javascript
复制
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

代码语言:javascript
复制
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);
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61367159

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档