【问题标题】:Custom UINavigationBar in MonoTouchMonoTouch 中的自定义 UINavigationBar
【发布时间】:2011-10-30 15:37:26
【问题描述】:

我目前正在尝试使用 MonoTouch 在 iOS 中为我​​的导航控制器创建自定义导航栏。无论您在应用程序的哪个位置,我正在开发的应用程序都需要在屏幕上显示一个可用的字符串,而且我不想实现这样的事情(我知道这有点不成比例,但是您应该能明白):

+-----------------------------------------+
|  /---------|                     +---+  |
| /   Back   |     Controller Name |btn|  |
|  \---------|                     +---+  |
+-----------------------------------------+
|     Current building <- global string   |
+-----------------------------------------+

底部栏应尽可能小(但不难阅读),原始导航栏可能需要比正常小一点。

另外,我尝试不使用设计器,而是自己编写所有 UI 代码,但如果这无法实现,那么我将关闭,因为必须使用设计器。目前我找到了一个在 MonoTouch 中创建自定义 UINavigationBar 的项目,但我不知道如何将其应用于我的 NavigationController(请参阅 NavigationBar 属性是只读的)。我正在谈论的项目可以在这里找到:https://github.com/mafis/Monotouch-Custom-Control/tree/master/CustomControls。另外,我希望实际导航栏(顶部)的设计是标准的 iOS 设计,并像通常的导航栏一样工作。

任何有关如何执行此操作的提示或指针将不胜感激。

【问题讨论】:

  • 我在同一条船上(不知道如何用我自己的实现替换默认 UINavigationBar,因为它是只读的)-在 iOS 中,您对具体类的覆盖被接受,因为它们只是消息.
  • 其实我解决了这个问题。但解决方案在另一台电脑上。我必须重写导航控制器,但除此之外它实际上非常简单。一旦我在我的工作电脑上,我会尝试上传解决方案。
  • 我中途了。我继承了 UINavigationController 并覆盖了虚拟 NavigationBar 属性,换成了我自己的子类 UINavigationBar。它可以工作,但它不会再呈现任何导航栏项目。即使在一个空的子类中。

标签: ios uinavigationcontroller xamarin.ios uinavigationbar


【解决方案1】:

这就是我最终解决这个问题的方法。我像这样子类化 UIViewController:

using System;
using MonoTouch.UIKit;
using MonoTouch.CoreGraphics;
using System.Drawing;
using System.Collections.Generic;
using FdvWeb.Core;
namespace FdvWeb
{
    [MonoTouch.Foundation.Preserve(AllMembers=true)]
    public class MainNavigationController : UINavigationController
    {
        private const float NAV_BAR_HEIGHT = 44;
        private readonly float buildingBarTop = 44;
        private readonly float buildingBarHeight = 17;
        private readonly float viewOffset;

        private readonly HashSet<UIViewController> modifiedViewControllers = new HashSet<UIViewController>();

        UITextView buildingTextView;

        [MonoTouch.Foundation.Preserve]
        public MainNavigationController ()
        {
            viewOffset = buildingBarTop + buildingBarHeight - NAV_BAR_HEIGHT;

            var tt = new UITextView (new RectangleF (0, buildingBarTop, 320, buildingBarHeight));

            NavigationBarHidden = false;
            NavigationBar.AddSubview (tt);
            tt.Font = UIFont.BoldSystemFontOfSize (12);
            tt.TextAlignment = UITextAlignment.Center;
            tt.TextColor = UIColor.LightTextColor;
            tt.BackgroundColor = UIColor.ViewFlipsideBackgroundColor;
            tt.Editable = false;
            tt.ContentInset = new UIEdgeInsets (-9, 0, 0, 0);
            buildingTextView = tt;
        }

        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();


        }

        public override void ViewWillAppear (bool animated)
        {
            base.ViewWillAppear (animated);
        }

        public string BuildingText
        {
            get {
                return buildingTextView.Text;
            }
            set {
                container.Resolve<IUIThreadDispatcher> ().DispatchOnUIThread (delegate { // Run on UI thread
                    buildingTextView.Text = value;
                });
            }
        }

        public override void PushViewController (UIViewController viewController, bool animated)
        {
            if (!modifiedViewControllers.Contains (viewController))
            {
                viewController.View = new PaddedView (viewController.View, new InnsetF (0, viewOffset, 0, 0));
                modifiedViewControllers.Add (viewController);
            }

            viewController.NavigationItem.RightBarButtonItem = pickBuildingItem;
            base.PushViewController (viewController, animated);
        }

        private class PaddedView : UIView
        {
            private UIView view;
            private InnsetF innsets;

            public PaddedView (UIView view, InnsetF innsets)
                : base(view.Frame)
            {
                this.view = view;
                this.innsets = innsets;
                this.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
                this.AddSubview (view);
            }

            public override void LayoutSubviews ()
            {
                //apply the insets to the subview
                view.Frame = new RectangleF (innsets.Left, innsets.Top,
                    Frame.Size.Width - innsets.Left - innsets.Right,
                    Frame.Size.Height - innsets.Top - innsets.Bottom);
            }
        }

        private class InnsetF
        {
            private float top, bottom, left, right;
            public InnsetF (float left, float top, float right, float bottom)
            {
                this.top = top;
                this.left = left;
                this.bottom = bottom;
                this.right = right;
            }

            public float Top
            {
                get { return top; }
                set { top = value; }
            }

            public float Bottom
            {
                get { return bottom; }
                set { bottom = value; }
            }

            public float Right
            {
                get { return right; }
                set { right = value; }
            }

            public float Left
            {
                get { return left; }
                set { left = value; }
            }
        }
    }
}

【讨论】:

    【解决方案2】:

    因此,您希望 Spotify 在离线时执行相反的操作(您所指的字符串消息出现在 UINavigationController 上方)。

    我认为您采用的方法行不通 - 据我所知,NavigationBar 只能是 44 像素高。您能否对 Spotify 采取类似的方法并将其移至 NavigationBar 上方?这样,您可以保留 NavigationController 等,并简单地使其视图更小,然后将字符串添加到窗口对象 - 这样它会在您浏览应用程序时持续存在。

    【讨论】:

    • 嗯。这很可能是一个很好的解决方案。甚至可能比我目前正在尝试实现的更好(顺便说一句,我或多或少地做到了,目前只有一个小问题)。我会在我开始工作后研究一下。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多