如何创建一个更大的中心UITabBar项目

60
我想知道如何创建一个像下面截图中那样更大的中心 UITabBar?它真的很漂亮!!!
8个回答

64

在特定选项卡栏项目的视图控制器中点击选项卡栏按钮,使其突出显示,

移除文本,将图像插入设置为选项卡栏按钮的顶部-25。

如下图所示

enter image description here

然后

进入资产,
选择您在选项卡栏按钮中设置的图像,
渲染属性设置为原始图像(如果您有一个彩色按钮,否则它将呈现为一种颜色)
如下所示, enter image description here

现在,您将获得所需的效果, enter image description here

编辑:要使上半部分可点击,请继承UITabBar

class ProminentTabBar: UITabBar {
    var prominentButtonCallback: (()->())?
    
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        guard let items = items, items.count>0 else {
            return super.hitTest(point, with: event)
        }
        
        let middleItem = items[items.count/2]
        let middleExtra = middleItem.imageInsets.top
        let middleWidth = bounds.width/CGFloat(items.count)
        let middleRect = CGRect(x: (bounds.width-middleWidth)/2, y: middleExtra, width: middleWidth, height: abs(middleExtra))
        if middleRect.contains(point) {
            prominentButtonCallback?()
            return nil
        }
        return super.hitTest(point, with: event)
    }
}

在TabBarController中添加以下内容

override func viewDidLoad() {
    super.viewDidLoad()
    
    let prominentTabBar = self.tabBar as! ProminentTabBar
    prominentTabBar.prominentButtonCallback = prominentTabTaped
}

func prominentTabTaped() {
    selectedIndex = (tabBar.items?.count ?? 0)/2
}

记住,涉及UITabBar时没有简单的解决方案 :-)


1
你还需要底部25个边距,否则图像会呈现为椭圆形。 - Codetard
你已经对那个按钮进行了子类化吗? - ZameerMoh
5
这看起来视觉效果不错,但它只接受在选项卡栏范围内的轻点。有没有办法注册来自圆形顶部1/3的轻点? - Grambo
@van 尝试在点击时为按钮设置相同的大小。 - ZameerMoh
@IOSDealBreaker 是的,我尝试使用“did select”方法,但没有成功。 - Van
显示剩余11条评论

29

我建议你看一下以下文章。它解释了如何自定义选项卡栏以提高主按钮。

代码:

UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
[button setBackgroundImage:buttonImage forState:UIControlStateNormal];
[button setBackgroundImage:highlightImage forState:UIControlStateHighlighted];

CGFloat heightDifference = buttonImage.size.height - self.tabBar.frame.size.height;
if (heightDifference < 0)
   button.center = self.tabBar.center;
else
{
 CGPoint center = self.tabBar.center;
 center.y = center.y - heightDifference/2.0;
 button.center = center;
}

[self.view addSubview:button];

Guide: https://github.com/boctor/idev-recipes/tree/master/RaisedCenterTabBar


该链接的域名已过期。在您的代码中,“self”是一个UITabBarController吗? - cohenadair
2
@cohenadair 中的 self 指的是 UIViewController。我添加了一个链接到 Github 存储库,其中包含一个示例 - Manuel Escrig

9

Swift 3, 4:

我在我的UITabBarController子类的viewDidLoad方法中使用以下代码:

let button = UIButton()
button.setImage(UIImage(named: "home"), for: .normal)
button.sizeToFit()
button.translatesAutoresizingMaskIntoConstraints = false

tabBar.addSubview(button)
tabBar.centerXAnchor.constraint(equalTo: button.centerXAnchor).isActive = true
tabBar.topAnchor.constraint(equalTo: button.centerYAnchor).isActive = true

有时候,我会将 button.adjustsImageWhenHighlighted = false 设为 false 以模仿其他项目的行为,或更改约束条件的 constant 属性来将按钮向上或向下移动。

你不明白这对选项卡栏有什么用吗?现在我需要写一堆额外的代码来让按钮打开我想要的选项卡? - dub

7
这是@Kakashi的答案的Swift 3版本(向他们表示+1),我将其放在了我的自定义UITabBarController子类中:
override func viewDidLoad() {
        if let newButtonImage = UIImage(named: "new__button") {
            self.addCenterButton(withImage: newButtonImage, highlightImage: newButtonImage)
        }
 }

 func handleTouchTabbarCenter(sender : UIButton)
 {
    if let count = self.tabBar.items?.count
    {
        let i = floor(Double(count / 2))
        self.selectedViewController = self.viewControllers?[Int(i)]
    }
 }

func addCenterButton(withImage buttonImage : UIImage, highlightImage: UIImage) {

        let paddingBottom : CGFloat = 10.0

        let button = UIButton(type: .custom)
        button.autoresizingMask = [.flexibleRightMargin, .flexibleTopMargin, .flexibleLeftMargin, .flexibleBottomMargin]
        button.frame = CGRect(x: 0.0, y: 0.0, width: buttonImage.size.width / 2.0, height: buttonImage.size.height / 2.0)
        button.setBackgroundImage(buttonImage, for: .normal)
        button.setBackgroundImage(highlightImage, for: .highlighted)

        let rectBoundTabbar = self.tabBar.bounds
        let xx = rectBoundTabbar.midX
        let yy = rectBoundTabbar.midY - paddingBottom
        button.center = CGPoint(x: xx, y: yy)

        self.tabBar.addSubview(button)
        self.tabBar.bringSubview(toFront: button)

        button.addTarget(self, action: #selector(handleTouchTabbarCenter), for: .touchUpInside)

        if let count = self.tabBar.items?.count
        {
            let i = floor(Double(count / 2))
            let item = self.tabBar.items![Int(i)]
            item.title = ""
        }
    }

在按钮点击时,handleTouchTabbarCenter函数未被调用。 - Ramis
是的,一样。有没有新的解决方案? - Yaroslav Dukal
问题:设备旋转时,按钮位置不跟随。此外,还有许多其他情况下,按钮被重新绘制,而旧按钮仍然存在。例如,在通话状态栏中。 - Jerland2
嗨,谢谢,我看到我的按钮了,但是handleTouchTabbarCenter没有被调用,我们可能缺少什么(我看到有更多的人有同样的错误)。 - Mago Nicolas Palacios

4

我按照 @Michael Dautermann 的答案进行操作,但是按钮从未响应点击,因此我对其进行了修改以使其起作用:

  func handleTouchTabbarCenter()
{
    if let count = self.tabBar.items?.count
    {
        let i = floor(Double(count / 2))
        self.selectedViewController = self.viewControllers?[Int(i)]
    }
}

func addCenterButton(withImage buttonImage : UIImage, highlightImage: UIImage) {

    self.centerButton = UIButton(type: .custom)
    self.centerButton?.autoresizingMask = [.flexibleRightMargin, .flexibleTopMargin, .flexibleLeftMargin, .flexibleBottomMargin]
    self.centerButton?.frame = CGRect(x: 0.0, y: 0.0, width: buttonImage.size.width, height: buttonImage.size.height)
    self.centerButton?.setBackgroundImage(buttonImage, for: .normal)
    self.centerButton?.setBackgroundImage(highlightImage, for: .highlighted)
    self.centerButton?.isUserInteractionEnabled = true

    let heightdif: CGFloat = buttonImage.size.height - (self.tabBar.frame.size.height);

    if (heightdif < 0){
        self.centerButton?.center = (self.tabBar.center)
    }
    else{
        var center: CGPoint = (self.tabBar.center)
        center.y = center.y - 24
        self.centerButton?.center = center
    }

    self.view.addSubview(self.centerButton!)
    self.tabBar.bringSubview(toFront: self.centerButton!)

    self.centerButton?.addTarget(self, action: #selector(handleTouchTabbarCenter), for: .touchUpInside)

    if let count = self.tabBar.items?.count
    {
        let i = floor(Double(count / 2))
        let item = self.tabBar.items![Int(i)]
        item.title = ""
    }
}

3
我参考了Manuel的示例(被接受的答案),并对由于iPhone X问题导致的底部安全区域插图进行了调整。
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
[button setBackgroundImage:buttonImage forState:UIControlStateNormal];
[button setBackgroundImage:highlightImage forState:UIControlStateHighlighted];

CGFloat heightDifference = buttonImage.size.height - self.tabBar.frame.size.height;
CGPoint center = self.tabBar.center;
if (heightDifference >= 0) {
    center.y = center.y - heightDifference/2.0;
}

if (@available(iOS 11.0, *)) {
    UIWindow *window = UIApplication.sharedApplication.keyWindow;
    CGFloat bottomPadding = window.safeAreaInsets.bottom;
    center.y = center.y - bottomPadding;
}

[self.view addSubview:button];

1
谢谢您,接受的答案是2010年的,因此很高兴看到更新的解决方案适用于新型号 :) - Eman

3

为了隐藏UITabbar,我创建了自定义的UITabbarController并插入了以下方法。

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self addCenterButtonWithImage:[UIImage imageNamed:@"logo"] highlightImage:[UIImage imageNamed:@"logo"]];
}

- (void)addCenterButtonWithImage:(UIImage*)buttonImage highlightImage:(UIImage*)highlightImage
{
    float paddingBottom = 10;

    UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin;
    button.frame = CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
    [button setBackgroundImage:buttonImage forState:UIControlStateNormal];
    [button setBackgroundImage:highlightImage forState:UIControlStateHighlighted];

    CGRect rectBoundTabbar = [self.tabBar bounds];
    float xx = CGRectGetMidX(rectBoundTabbar);
    float yy = CGRectGetMidY(rectBoundTabbar) - paddingBottom;
    button.center = CGPointMake(xx, yy);

    [self.tabBar addSubview:button];
    [self.tabBar bringSubviewToFront:button];

    // add handle
    [button addTarget:self action:@selector(handleTouchTabbarCenter:) forControlEvents:UIControlEventTouchUpInside];

    // hide title item menu
    NSInteger count = [self.tabBar.items count];
    NSInteger i = floor(count / 2.0);
    UITabBarItem *item = [self.tabBar.items objectAtIndex:i];
    [item setTitle:nil];

}

- (void)handleTouchTabbarCenter:(id)sender
{
    // go to some view
}

1
对于Swift
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (Int64)(2.0)), dispatch_get_main_queue(), {
            let button: UIButton = UIButton(type: .Custom)
            let win:UIWindow = UIApplication.sharedApplication().delegate!.window!!

            button.frame = CGRectMake(0.0, win.frame.size.height - 65, 55, 55)
            button.center = CGPoint(x:win.center.x , y: button.center.y)

            button.setBackgroundImage(UIImage(named: "Camera") , forState: .Normal)
            button.setBackgroundImage(UIImage(named: "Camera"), forState: .Highlighted)
            win.addSubview(button)
        });

你为什么要将按钮添加到应用程序的窗口中?将其添加到视图控制器的视图或者更好的是添加到选项卡栏本身不是更有意义吗? - Brian Sachetta
我有其他要求需要添加到上述代码中。这是我项目需求的经过测试的代码。 - Hardik Thakkar
没错,这是可以实现的,只是与其将按钮与整个应用程序的窗口关联起来,将其与所属视图关联起来似乎更有意义。 - Brian Sachetta
谁给了负评,请说明原因。 - Hardik Thakkar
问题是要求自定义UITabbar而不是在窗口中添加按钮。 - Naveen Shan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接