在选项卡栏上制作自定义圆角按钮

21

这是我想要做的事情: 在此输入图片描述

注意:屏幕截图来自较早版本的iOS

我已经实现的内容: 在此输入图片描述

代码:

 override func viewWillAppear(animated: Bool) {
    // Creates image of the Button
    let imageCameraButton: UIImage! = UIImage(named: "cameraIcon")

    // Creates a Button
    let cameraButton = UIButton(type: .Custom)
    // Sets width and height to the Button
    cameraButton.frame = CGRectMake(0.0, 0.0, imageCameraButton.size.width, imageCameraButton.size.height);
    // Sets image to the Button
    cameraButton.setBackgroundImage(imageCameraButton, forState: .Normal)
    // Sets the center of the Button to the center of the TabBar
    cameraButton.center = self.tabBar.center
    // Sets an action to the Button
    cameraButton.addTarget(self, action: "doSomething", forControlEvents: .TouchUpInside)

    // Adds the Button to the view
    self.view.addSubview(cameraButton)
}

我尝试按照正常方式创建一个圆角按钮,但结果是这样的:

图片描述

圆角按钮的代码片段:

//Creation of Ronded Button
    cameraButton.layer.cornerRadius = cameraButton.frame.size.width/2
    cameraButton.clipsToBounds = true

1
这可以通过在TabBar上添加一个按钮来完成。 - E-Riddie
这是不可能的,因为您无法将按钮添加到选项卡栏控制器视图中。此外,添加到任一选项卡视图的任何按钮始终在选项卡栏后面。除此之外,如果我在单个视图中添加了一个按钮,则该按钮将不会在所有视图中都可用,就像我上面描述的情况一样。 - Supratik Majumdar
不可能:D?我一开始就告诉你这个想法,因为你在错误的控制器中添加了视图。为此,您需要子类化UITabBarController并在那里进行计算。您已经更新了答案。 - E-Riddie
是的,我误解了。谢谢 @EridB - Supratik Majumdar
4个回答

53

解决方案

您需要创建 UITabBarController 的子类,然后将按钮添加到 TabBar 视图上方。按钮的操作应该通过设置 selectedIndex 来触发 UITabBarController 的标签切换。

代码

以下代码只是一个简单实现,但如果需要 完全支持 iPhone(包括 X 系列)/iPad 版本,可以在此处检查完整存储库:EBRoundedTabBarController

class CustomTabBarController: UITabBarController {

    // MARK: - View lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()

        let controller1 = UIViewController()
        controller1.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 1)
        let nav1 = UINavigationController(rootViewController: controller1)

        let controller2 = UIViewController()
        controller2.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 2)
        let nav2 = UINavigationController(rootViewController: controller2)

        let controller3 = UIViewController()
        let nav3 = UINavigationController(rootViewController: controller3)
        nav3.title = ""

        let controller4 = UIViewController()
        controller4.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 4)
        let nav4 = UINavigationController(rootViewController: controller4)

        let controller5 = UIViewController()
        controller5.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 5)
        let nav5 = UINavigationController(rootViewController: controller5)


        viewControllers = [nav1, nav2, nav3, nav4, nav5]
        setupMiddleButton()
    }

    // MARK: - Setups

    func setupMiddleButton() {
        let menuButton = UIButton(frame: CGRect(x: 0, y: 0, width: 64, height: 64))

        var menuButtonFrame = menuButton.frame
        menuButtonFrame.origin.y = view.bounds.height - menuButtonFrame.height
        menuButtonFrame.origin.x = view.bounds.width/2 - menuButtonFrame.size.width/2
        menuButton.frame = menuButtonFrame

        menuButton.backgroundColor = UIColor.red
        menuButton.layer.cornerRadius = menuButtonFrame.height/2
        view.addSubview(menuButton)

        menuButton.setImage(UIImage(named: "example"), for: .normal)
        menuButton.addTarget(self, action: #selector(menuButtonAction(sender:)), for: .touchUpInside)

        view.layoutIfNeeded()
    }


    // MARK: - Actions

    @objc private func menuButtonAction(sender: UIButton) {
        selectedIndex = 2
    }
}

输出

在这里输入图像描述


1
如果我们移动或显示另一个屏幕,我通过委托完成了这项工作,但我认为这并不正确。 - Alexander Khitev
1
@Alexsander 你可以使用viewWillDisappear隐藏按钮,viewWillAppear显示它。声明一个实例变量来存储按钮实例,这样当你浏览应用程序时就可以隐藏和显示它。 - E-Riddie
1
@Loebre 这段代码就是整个项目。没有什么花里胡哨的东西,只需要将这个控制器设置为AppDelegate下的rootController,你就完成了。 - E-Riddie
1
跟我一样。有人解决了这个问题吗? - Yaroslav Dukal
5
@Raymond26 @alizain-prasla 我写了一篇关于这个问题的博客,以及如何使用hidesBottomBarWhenPushed解决它:https://equaleyes.com/blog/2017/09/04/the-common-raised-center-button-problems-in-tabbar/ - Dejan Skledar
显示剩余9条评论

13

Swift 3解决方案

对于EricB的解决方案,只需要稍作调整即可使其在Swift 3中生效。menuButton.addTarget()方法需要将其选择器语法进行一些更改。

这里是新的menuButton.addTarget()函数:

menuButton.addTarget(self, action: #selector(MyTabBarController.menuButtonAction), for: UIControlEvents.touchUpInside)

在定义TabBarController类时,我还添加了UITabBarControllerDelegate并将所有内容放置在

override func viewDidAppear(_ animated: Bool) { ... }

为了更清晰明了,以下是完整代码:

完整代码解决方案

import UIKit

class MyTabBarController: UITabBarController, UITabBarControllerDelegate {

// View Did Load
override func viewDidLoad() {
    super.viewDidLoad()

}

// Tab Bar Specific Code
override func viewDidAppear(_ animated: Bool) {
    let controller1 = UIViewController(self.view.backgroundColor = UIColor.white)
    controller1.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.contacts, tag: 1)
    let nav1 = UINavigationController(rootViewController: controller1)

    let controller2 = UIViewController()
    controller2.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.contacts, tag: 2)
    let nav2 = UINavigationController(rootViewController: controller2)

    let controller3 = UIViewController()
    let nav3 = UINavigationController(rootViewController: controller3)
    nav3.title = ""

    let controller4 = UIViewController()
    controller4.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.contacts, tag: 4)
    let nav4 = UINavigationController(rootViewController: controller4)

    let controller5 = UIViewController()
    controller5.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.contacts, tag: 5)
    let nav5 = UINavigationController(rootViewController: controller5)

    self.viewControllers = [nav1, nav2, nav3, nav4, nav5]
    self.setupMiddleButton()
}

// TabBarButton – Setup Middle Button
func setupMiddleButton() {
    let menuButton = UIButton(frame: CGRect(x: 0, y: 0, width: 64, height: 64))
    var menuButtonFrame = menuButton.frame
    menuButtonFrame.origin.y = self.view.bounds.height - menuButtonFrame.height
    menuButtonFrame.origin.x = self.view.bounds.width / 2 - menuButtonFrame.size.width / 2
    menuButton.frame = menuButtonFrame

    menuButton.backgroundColor = UIColor.red
    menuButton.layer.cornerRadius = menuButtonFrame.height/2
    self.view.addSubview(menuButton)

    menuButton.setImage(UIImage(named: "example"), for: UIControlState.normal)
    menuButton.addTarget(self, action: #selector(MyTabBarController.menuButtonAction), for: UIControlEvents.touchUpInside)

    self.view.layoutIfNeeded()
}

// Menu Button Touch Action
func menuButtonAction(sender: UIButton) {
    self.selectedIndex = 2
    // console print to verify the button works
    print("Middle Button was just pressed!")
   }
 }

1
你似乎忘记添加super.viewDidAppear(animated)了,感谢你的解决方案 :) - Vivienne Fosh

7

这是customTabbarcontroller类,它是UITabbarcontroller的子类。这个想法与@EridB提供的相同。但是在他的代码中,@Raymond26的问题没有解决。因此,发布一个完整的解决方案,使用Swift 3.0编写。

protocol CustomTabBarControllerDelegate
{
    func customTabBarControllerDelegate_CenterButtonTapped(tabBarController:CustomTabBarController, button:UIButton, buttonState:Bool);
}

class CustomTabBarController: UITabBarController, UITabBarControllerDelegate
{
    var customTabBarControllerDelegate:CustomTabBarControllerDelegate?;
    var centerButton:UIButton!;
    private var centerButtonTappedOnce:Bool = false;

    override func viewDidLayoutSubviews()
    {
        super.viewDidLayoutSubviews();

        self.bringcenterButtonToFront();
    }

    override func viewDidLoad()
    {
        super.viewDidLoad()

        self.delegate = self;

        self.tabBar.barTintColor = UIColor.red;

        let dashboardVC = DashboardViewController()        
        dashboardVC.tabBarItem = UITabBarItem(tabBarSystemItem: .topRated, tag: 1)
        let nav1 = UINavigationController(rootViewController: dashboardVC)

        let myFriendsVC = MyFriendsViewController()
        myFriendsVC.tabBarItem = UITabBarItem(tabBarSystemItem: .featured, tag: 2)
        let nav2 = UINavigationController(rootViewController: myFriendsVC)

        let controller3 = UIViewController()
        let nav3 = UINavigationController(rootViewController: controller3)
        nav3.title = ""

        let locatorsVC = LocatorsViewController()
        locatorsVC.tabBarItem = UITabBarItem(tabBarSystemItem: .downloads, tag: 4)
        let nav4 = UINavigationController(rootViewController: locatorsVC)

        let getDirectionsVC = GetDirectionsViewController()
        getDirectionsVC.tabBarItem = UITabBarItem(tabBarSystemItem: .history, tag: 5)
        let nav5 = UINavigationController(rootViewController: getDirectionsVC)

        viewControllers = [nav1, nav2, nav3, nav4, nav5]

        self.setupMiddleButton()
    }

    // MARK: - TabbarDelegate Methods

    func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController)
    {
        switch viewController
        {
        case is DashboardViewController:
            self.showCenterButton()
        case is MyFriendsViewController:
            self.showCenterButton()
        case is GetDirectionsViewController:
            self.showCenterButton()
        case is LocatorsViewController:
            self.showCenterButton()
        default:
            self.showCenterButton()
        }
    }

    // MARK: - Internal Methods

    @objc private func centerButtonAction(sender: UIButton)
    {
        //        selectedIndex = 2
        if(!centerButtonTappedOnce)
        {
            centerButtonTappedOnce=true;
            centerButton.setImage(UIImage(named: "ic_bullseye_white"), for: .normal)
        }
        else
        {
            centerButtonTappedOnce=false;
            centerButton.setImage(UIImage(named: "ic_bullseye_red"), for: .normal)
        }

        customTabBarControllerDelegate?.customTabBarControllerDelegate_CenterButtonTapped(tabBarController: self,
                                                                                          button: centerButton,
                                                                                          buttonState: centerButtonTappedOnce);
    }

    func hideCenterButton()
    {
        centerButton.isHidden = true;
    }

    func showCenterButton()
    {
        centerButton.isHidden = false;
        self.bringcenterButtonToFront();
    }

    // MARK: - Private methods

    private func setupMiddleButton()
    {
        centerButton = UIButton(frame: CGRect(x: 0, y: 0, width: 64, height: 64))

        var centerButtonFrame = centerButton.frame
        centerButtonFrame.origin.y = view.bounds.height - centerButtonFrame.height
        centerButtonFrame.origin.x = view.bounds.width/2 - centerButtonFrame.size.width/2
        centerButton.frame = centerButtonFrame

        centerButton.backgroundColor = UIColor.red
        centerButton.layer.cornerRadius = centerButtonFrame.height/2
        view.addSubview(centerButton)

        centerButton.setImage(UIImage(named: "ic_bullseye_red"), for: .normal)
        centerButton.setImage(UIImage(named: "ic_bullseye_white"), for: .highlighted)
        centerButton.addTarget(self, action: #selector(centerButtonAction(sender:)), for: .touchUpInside)

        view.layoutIfNeeded()
    }

    private func bringcenterButtonToFront()
    {
        print("bringcenterButtonToFront called...")
        self.view.bringSubview(toFront: self.centerButton);
    }

}

这是完整参考的 DashboardViewController
class DashboardViewController: BaseViewController, CustomTabBarControllerDelegate
{
    override func viewDidLoad()
    {
        super.viewDidLoad()
        (self.tabBarController as! CustomTabBarController).customTabBarControllerDelegate = self;
    }

    override func viewWillAppear(_ animated: Bool)
    {
        super.viewWillAppear(animated);
        (self.tabBarController as! CustomTabBarController).showCenterButton();
    }

    override func viewWillDisappear(_ animated: Bool)
    {
        super.viewWillDisappear(animated);

        self.hidesBottomBarWhenPushed = false;
        (self.tabBarController as! CustomTabBarController).hideCenterButton();
    }

    override func viewWillLayoutSubviews()
    {
        super.viewWillLayoutSubviews();

        if(!isUISetUpDone)
        {
            self.view.backgroundColor = UIColor.lightGray
            self.title = "DASHBOARD"
            self.prepareAndAddViews();
            self.isUISetUpDone = true;
        }
    }

    override func didReceiveMemoryWarning()
    {
        super.didReceiveMemoryWarning()
    }

    //MARK: CustomTabBarControllerDelegate Methods

    func customTabBarControllerDelegate_CenterButtonTapped(tabBarController: CustomTabBarController, button: UIButton, buttonState: Bool)
    {
        print("isDrive ON : \(buttonState)");
    }

    //MARK: Internal Methods

    func menuButtonTapped()
    {
        let myFriendsVC = MyFriendsViewController()
        myFriendsVC.hidesBottomBarWhenPushed = true;
        self.navigationController!.pushViewController(myFriendsVC, animated: true);
    }

    //MARK: Private Methods

    private func prepareAndAddViews()
    {
        let menuButton = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 50))
        menuButton.titleLabel?.text = "Push"
        menuButton.titleLabel?.textColor = UIColor.white
        menuButton.backgroundColor = UIColor.red;
        menuButton.addTarget(self, action: #selector(DashboardViewController.menuButtonTapped), for: .touchUpInside)
        self.view.addSubview(menuButton);
    }
}

1
非常感谢,它节省了我的时间。我有一个问题,当我点击自定义中心按钮时,我希望背景变模糊,并且控制应该在同一个控制器上(我不想要黑屏,请查看Asana应用程序以获取更多信息)。你能建议我如何实现相同的效果吗? - Satish

0

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

删除文本,只需将图像插图顶部设置为选项卡栏按钮的-25。 查看以下图片 输入图像描述


你好,图片无法显示,请检查以下链接: https://dev59.com/-WMl5IYBdhLWcg3w3aA- - Muhammad Ali
上方的视图无法点击。 - Aman Gupta

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