【问题标题】:How can I get a full-sized UINavigationBar titleView如何获得全尺寸的 UINavigationBar titleView
【发布时间】:2011-04-14 23:00:22
【问题描述】:

我正在尝试将自定义控件添加为 UINavigationBar 中的 titleView。当我这样做时,尽管设置了通常假定全宽的框架和属性,但我得到了这个:

可以忽略亮蓝色,因为它是我隐藏自定义控件的地方。问题是导航栏末端的窄条。我怎样才能摆脱这些,以便我的自定义视图将拉伸 100%?

CGRect frame = CGRectMake(self.view.bounds.origin.x, self.view.bounds.origin.y, self.view.width, kDefaultBarHeight);
UANavBarControlView *control = [[[UANavBarControlView alloc] initWithFrame:frame] autorelease];
control.autoresizingMask = UIViewAutoresizingFlexibleWidth; 
self.navigationItem.titleView = control;

PS - 我知道我可以自己添加视图而不是附加到导航栏,而且我自己定位它会很容易。我有理由需要它“打开”导航栏,这些原因是here

【问题讨论】:

  • 你很幸运能得到那个宽度;我有一个非全角标题视图,但它仍然被水平压缩...

标签: iphone uiview uinavigationbar uinavigationitem


【解决方案1】:

设置视图的navigationItem 的titleView 永远不会成功。相反,您可以将 subView 添加到导航控制器的 navigationBar :

UIView* ctrl = [[UIView alloc] initWithFrame:navController.navigationBar.bounds];
ctrl.backgroundColor = [UIColor yellowColor];
ctrl.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[navController.navigationBar addSubview:ctrl];

【讨论】:

  • 这种方法不适用于导航。将视图控制器推送到堆栈上会将其置于此处。我可以在推拉之前将其删除,但这似乎很hacky
  • 我最终破解了它,通过添加动画在 viewwillappear 和 viewwilldissapear 上添加/删除它。我猜一个hacky问题的hacky解决方案。我会暂缓给你赏金,看看是否有更好的解决方案出现。
  • 我也是这样做的。正如你所说:hacky 解决方案!
  • 您是否尝试过继承 UINavigationController 以在内部更改 titleview 的框架?我不知道该怎么做!
  • + 1,这行得通,但我很惊讶没有更直接的方法可以做到这一点......
【解决方案2】:

CGRect 框架 = CGRectMake(0, 0, 320, 44);

UILabel *titlelabel = [[UILabel alloc]initWithFrame:frame];

titlelabel.textAlignment = UITextAlignmentCenter;

titlelabel.backgroundColor = [UIColor clearColor];

titlelabel.textColor = [UIColor whiteColor];

titlelabel.font = [UIFont systemFontOfSize:20];

titlelabel.text =@"Available Reports";

self.navigationItem.titleView = titlelabel;

如果您想设置图像,然后在 uilable 上使用 uiimage 视图,您可以创建完整导航栏的任何视图,只需告诉我您的导航看起来如何,如果您愿意,我将向您发送代码,我可以在导航上放置 6 个按钮还有

【讨论】:

  • 我猜你在发帖之前都没有尝试过吧?
  • 这似乎只对你有用,因为你有清晰的背景。
【解决方案3】:

刚遇到同样的问题,经过一番思考解决了。 titleView 的框架在每次出现时由 navigationBar 设置。

您所要做的就是继承 UIView 并覆盖 setFrame

像这样:

    - (void)setFrame:(CGRect)frame {
        [super setFrame:CGRectMake(0.0, 0.0, 320.0, 50.0)];
    }

现在将你偷偷摸摸的新 UIView 设置为 navigationItem.titleView 并享受它新发现的对超级视图调整大小的抵抗力。

您不必在每次设置框架时都设置 super 的框架。您只需设置一次即可完成。如果您想支持方向更改,您也可以将其组合在一起。

【讨论】:

  • 这在 ios5.0 中设置标题视图时帮助了我。非常感谢! :-)
  • 对于遇到同样问题的任何人...如果您的 titleview 没有显示,您需要覆盖 layoutSubviews,并将视图置于最前面(或插入到更高的索引处)。跨度>
  • +1 这只是一个很好的解决方案,与所有其他解决布局或类别的解决方案相比。
  • 我认为硬编码值是一种不好的方法,我在-setFrame中找到了这段代码:[super setFrame:CGRectMake(0.f, frame.origin.y, self.superview .frame.size.width, frame.size.height)];
  • 在 Swift 中这是什么?
【解决方案4】:

ksm 答案的 Swift 版本

let leftOffset: CGFloat = 60
let rightOffset: CGFloat = 60

@objc override var frame: CGRect {
     didSet {
                let width: CGFloat = UIScreen.main.bounds.width - leftOffset - rightOffset
                let height: CGFloat = 44

                super.frame = CGRect(
                    x: leftOffset,
                    y: 20,
                    width: width,
                    height: height
                )
       }
}

【讨论】:

    【解决方案5】:

    感谢@VdesmedT的答案,我一直在使用这个答案在导航栏中实现全屏大小的titleView。

    但是,我最近刚升级到iOS11,发现这个解决方案不起作用。所以我用另一种方式想通了(可能看起来很奇怪)。核心思想不是改变titleView的大小,而是改变bar的subViews来达到全屏bar的效果

    1. 制作一个barView(确保barView的宽度是screenSize - 12*2, 12 是系统填充设置为titleView,你可以使用手动布局 或自动布局的约束来实现这一点)。然后将其设置为 导航栏的titleView
    2. 将您的组件添加到此 barView 中。你可以对齐组件 从 -12 到 barView 的宽度 + 12
    3. 重载 barView 的 pointInside ,使其甚至可以响应 当点击发生在 barView 之外时。

      - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
       {
        BOOL ret = [super pointInside:point withEvent:event];
        if (ret == NO)
        {
          CGRect expandRect = UIEdgeInsetsInsetRect(self.bounds, UIEdgeInsetsMake(0, -12, 0, -12));
          ret = CGRectContainsPoint(expandRect, point);
      }
      return ret;
      }
      

    【讨论】:

      【解决方案6】:

      以下代码写在iOS8/iOS9/iOS10/iOS11上。

      swift 3 中的代码

      class TitleView: UIView {
      
          override var frame: CGRect {
              get {
                  return super.frame
              }
              set {
                  super.frame = newValue.insetBy(dx: -newValue.minX, dy: 0)
              }
          }
      
          override func didMoveToSuperview() {
              if let superview = superview {
                  frame = superview.bounds
                  translatesAutoresizingMaskIntoConstraints = true
                  autoresizingMask = [.flexibleWidth, .flexibleHeight]
              }
          }
      
          override func updateConstraints() {
              super.updateConstraints()
              /// remove autolayout warning in iOS11
              superview?.constraints.forEach { constraint in
                  if fabs(constraint.constant) == 8 {
                      constraint.isActive = false
                  }
              }
          }
      }
      

      【讨论】:

      • 完美运行!谢谢
      • 这非常脆弱,所以一定要按原样使用它。我想我会喜欢并将约束移除移动到 didMoveToSubview。这在 iOS 10 上崩溃了!
      猜你喜欢
      • 1970-01-01
      • 2017-10-23
      • 2021-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-20
      相关资源
      最近更新 更多