自定义标签栏,带有中央按钮,该按钮将被按下的索引隐藏

问题描述

仅当我按索引3时(对于索引0 .. 3 fab.isHidden = true),才会显示如何在中央BUT Fab按钮中创建包含4个项目和一个FAB的“自定义”选项卡栏。如果平移我不需要该按钮的动画,而是填充为加号),仅显示/隐藏。要创建自定义标签栏,请使用本指南https://medium.com/better-programming/draw-a-custom-ios-tabbar-shape-27d298a7f4fa,我需要像这样创建标签栏,我可以尝试enter image description here其他方法,但无法解决问题。

Custom tab bar which needed

我正尝试这种方式

import UIKit

@IBDesignable
class CustomizedTabBar: UITabBar {

   
    private var shapeLayer: CALayer?

    private func addShape() {
        let shapeLayer = CAShapeLayer()
        shapeLayer.path = createPath()
        shapeLayer.strokeColor = UIColor.red.cgColor
        shapeLayer.fillColor = UIColor.white.cgColor
        shapeLayer.linewidth = 1.0

        if let oldShapeLayer = self.shapeLayer {
            self.layer.replaceSublayer(oldShapeLayer,with: shapeLayer)
        } else {
            self.layer.insertSublayer(shapeLayer,at: 0)
        }

        self.shapeLayer = shapeLayer
    }

    override func draw(_ rect: CGRect) {
        self.addShape()
    }

    func createPath() -> CGPath {

        let height: CGFloat = 37.0
        let path = UIBezierPath()
        let centerWidth = self.frame.width / 2

        path.move(to: CGPoint(x: 0,y: 0)) // start top left
        path.addLine(to: CGPoint(x: (centerWidth - height * 2),y: 0)) // the beginning of the trough

////        // first curve down
//      path.addCurve(to: CGPoint(x: centerWidth,y: height),controlPoint1: CGPoint(x: (centerWidth - 25),y: 0),controlPoint2: CGPoint(x: centerWidth - 35,y: height))
//
////        // second curve up
//        path.addCurve(to: CGPoint(x: (centerWidth + height * 1.0),//                    controlPoint1: CGPoint(x: centerWidth + 25,controlPoint2: CGPoint(x: (centerWidth + 30),y: 0))
        
        // cirle inside tab bar
        path.addArc(withCenter: CGPoint(x: centerWidth,radius: height,startAngle: CGFloat(180).degreesToradians,endAngle: CGFloat(0).degreesToradians,clockwise: false)
        

        // complete the rect

        path.addLine(to: CGPoint(x: self.frame.width,y: 0))
        path.addLine(to: CGPoint(x: self.frame.width,y: self.frame.height))
        path.addLine(to: CGPoint(x: 0,y: self.frame.height))
        path.close()

        return path.cgPath
    }

    override func point(inside point: CGPoint,with event: UIEvent?) -> Bool {
        let buttonRadius: CGFloat = 35
        return abs(self.center.x - point.x) > buttonRadius || abs(point.y) > buttonRadius
    }

    func createPathCircle() -> CGPath {

        let radius: CGFloat = 37.0
        let path = UIBezierPath()
        let centerWidth = self.frame.width / 2

        path.move(to: CGPoint(x: 0,y: 0))
        path.addLine(to: CGPoint(x: (centerWidth - radius * 2),y: 0))
        path.addArc(withCenter: CGPoint(x: centerWidth,radius: radius,clockwise: false)
        path.addLine(to: CGPoint(x: self.frame.width,y: self.frame.height))
        path.close()
        return path.cgPath
    }
}

extension CGFloat {
    var degreesToradians: CGFloat { return self * .pi / 180 }
    var radiansTodegrees: CGFloat { return self * 180 / .pi }
}

第二种方式

import UIKit

class MainTabBar: UITabBar {

    var checkState: Bool = true
    
   public var middleButton = UIButton()

    override func awakeFromNib() {
        super.awakeFromNib()
        
        guard let tabItems = items else { return }
        tabItems[1].titlePositionAdjustment = UIOffset(horizontal: -10,vertical: 0)
        tabItems[2].titlePositionAdjustment = UIOffset(horizontal: 10,vertical: 0)

 setupMiddleButton()
        
   
  
    }
    
    override func hitTest(_ point: CGPoint,with event: UIEvent?) -> UIView? {
        if self.isHidden {
            return super.hitTest(point,with: event)
        }
        
        let from = point
        let to = middleButton.center
        

        return sqrt((from.x - to.x) * (from.x - to.x) + (from.y - to.y) * (from.y - to.y)) <= 39 ? middleButton : super.hitTest(point,with: event)
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        middleButton.center = CGPoint(x: UIScreen.main.bounds.width / 2,y: 5)
    }

    func setupMiddleButton() {

        middleButton.frame.size = CGSize(width: 70,height: 70)
        middleButton.layer.cornerRadius = 35
        middleButton.layer.masksToBounds = true
        middleButton.layer.borderWidth = 8
        middleButton.layer.borderColor = #colorLiteral(red: 1.0,green: 1.0,blue: 1.0,alpha: 1.0)
        middleButton.backgroundColor = #colorLiteral(red: 0.2447069331,green: 0.850134835,blue: 0.1531122658,alpha: 1)
        middleButton.setimage(UIImage(named: "plus.png"),for: .normal)
        middleButton.center = CGPoint(x: UIScreen.main.bounds.width / 2,y: 0)
        middleButton.addTarget(self,action: #selector(test),for: .touchUpInside)
       
        addSubview(middleButton)
        
    }

    @objc func test() {
        print("my name is jeff")
    }
    
      

}

我从文章中尝试这种方式 https://equaleyes.com/blog/2017/09/04/the-common-raised-center-button-problems-in-tabbar/
但这对我不起作用,而且我从WWW上读取了太多信息,但没有得到答案(

解决方法

我是创建此标签栏的,我们只需几个步骤。 创建ViewController并嵌入到“ TabBarController”中,然后需要首先为“ UITabBar”创建两个类,该类包含形状和您想要的“ UITabBar”,第二个类为“ UITabBarController”,以便在其中可以添加动画的ViewController之间进行切换... 。这是因为我的TabBar有4个选项卡,并且仅在LAST选项卡上具有带有动画的Central FAB按钮,并且当出现按钮时,我应该为2和3 ui选项卡栏元素设置位置动画。

“ UITabBar”的类

import UIKit

@IBDesignable
class CustomizedTabBar: UITabBar {
    
    // MARK:- Variables -
    @objc public var centerButtonActionHandler: ()-> () = {}

    @IBInspectable public var centerButton: UIButton?
    @IBInspectable public var centerButtonColor: UIColor?
    @IBInspectable public var centerButtonHeight: CGFloat = 50.0
    @IBInspectable public var padding: CGFloat = 5.0
    @IBInspectable public var buttonImage: UIImage?
    @IBInspectable public var buttonTitle: String?
    
    @IBInspectable public var tabbarColor: UIColor = UIColor.lightGray
    @IBInspectable public var unselectedItemColor: UIColor = .init(red: 0.58,green: 0.61,blue: 0.66,alpha: 1.0)
    @IBInspectable public var selectedItemColor: UIColor = UIColor.black
    
    public var arc: Bool = true {
        didSet {
            self.setNeedsDisplay()
        }
    }
    
    private var shapeLayer: CALayer?

    private func addShape() {
        
        let shapeLayer = CAShapeLayer()
        shapeLayer.path = createPath()
        
        
        shapeLayer.strokeColor = UIColor.white.cgColor
        shapeLayer.fillColor = #colorLiteral(red: 0.96,green: 0.96,blue: 0.96,alpha: 1)
        shapeLayer.lineWidth = 1.0

        if let oldShapeLayer = self.shapeLayer {
            self.layer.replaceSublayer(oldShapeLayer,with: shapeLayer)
        } else {
            self.layer.insertSublayer(shapeLayer,at: 0)
        }
        
        
        self.shapeLayer = shapeLayer
        self.tintColor = centerButtonColor
        self.unselectedItemTintColor = unselectedItemColor
        self.tintColor = selectedItemColor
        self.setupMiddleButton()
        
    }

    override func draw(_ rect: CGRect) {
        self.addShape()
    }
    
    override public func hitTest(_ point: CGPoint,with event: UIEvent?) -> UIView? {
        guard !clipsToBounds && !isHidden && alpha > 0 else { return nil }
        for member in subviews.reversed() {
            let subPoint = member.convert(point,from: self)
            guard let result = member.hitTest(subPoint,with: event) else { continue }
            return result
        }
        return nil
    }

    func createPath() -> CGPath {

        let padding: CGFloat = 5.0
        let centerButtonHeight: CGFloat = 53.0
        
        let f = CGFloat(centerButtonHeight / 2.0) + padding
        let h = frame.height
        let w = frame.width
        let halfW = frame.width/2.0
        let r = CGFloat(18)
        let path = UIBezierPath()
        path.move(to: .zero)
        
        if (!arc) {
            
            path.addLine(to: CGPoint(x: halfW-f-(r/2.0),y: 0))

            path.addQuadCurve(to: CGPoint(x: halfW-f,y: (r/2.0)),controlPoint: CGPoint(x: halfW-f,y: 0))

            path.addArc(withCenter: CGPoint(x: halfW,radius: f,startAngle: .pi,endAngle: 0,clockwise: false)

            path.addQuadCurve(to: CGPoint(x: halfW+f+(r/2.0),y: 0),controlPoint: CGPoint(x: halfW+f,y: 0))
        }
        path.addLine(to: CGPoint(x: w,y: 0))
        path.addLine(to: CGPoint(x: w,y: h))
        path.addLine(to: CGPoint(x: 0.0,y: h))
        path.close()

        return path.cgPath
    }
    
    private func setupMiddleButton() {
        
        centerButton = UIButton(frame: CGRect(x: (self.bounds.width / 2)-(centerButtonHeight/2),y: -16,width: centerButtonHeight,height: centerButtonHeight))
        centerButton!.setNeedsDisplay()
        centerButton!.layer.cornerRadius = centerButton!.frame.size.width / 2.0
        centerButton!.setTitle(buttonTitle,for: .normal)
        centerButton!.setImage(UIImage(named: "plus"),for: .normal)
        centerButton!.backgroundColor = .init(red: 0.07,green: 0.83,blue: 0.05,alpha: 1.0)
        centerButton!.tintColor = UIColor.white

        self.centerButton!.isHidden = true

        if (!self.arc) {

            DispatchQueue.main.async {
                
                UIView.transition(with: self.centerButton!,duration: 1,options: .transitionCrossDissolve,animations: {

                        self.centerButton!.isHidden = false

                })
            }
        }
        
        
        //add to the tabbar and add click event
        self.addSubview(centerButton!)
        centerButton!.addTarget(self,action: #selector(self.centerButtonAction),for: .touchUpInside)
    }


    override func point(inside point: CGPoint,with event: UIEvent?) -> Bool {
        let buttonRadius: CGFloat = 35
        return abs(self.center.x - point.x) > buttonRadius || abs(point.y) > buttonRadius
    }

    func createPathCircle() -> CGPath {

        let radius: CGFloat = 37.0
        let path = UIBezierPath()
        let centerWidth = self.frame.width / 2

        path.move(to: CGPoint(x: 0,y: 0))
        path.addLine(to: CGPoint(x: (centerWidth - radius * 2),y: 0))
        path.addArc(withCenter: CGPoint(x: centerWidth,radius: radius,startAngle: CGFloat(180).degreesToRadians,endAngle: CGFloat(0).degreesToRadians,clockwise: false)
        path.addLine(to: CGPoint(x: self.frame.width,y: 0))
        path.addLine(to: CGPoint(x: self.frame.width,y: self.frame.height))
        path.addLine(to: CGPoint(x: 0,y: self.frame.height))
        path.close()
        return path.cgPath
    }
    
    // Menu Button Touch Action
    @objc func centerButtonAction(sender: UIButton) {
       self.centerButtonActionHandler()
    }
    
}

extension CGFloat {
    var degreesToRadians: CGFloat { return self * .pi / 180 }
    var radiansToDegrees: CGFloat { return self * 180 / .pi }
}

以及UITabBarController的类

导入UIKit

class MyTabBarController: UITabBarController {
    override func tabBar(_ tabBar: UITabBar,didSelect item: UITabBarItem) {
        let myTabBar = tabBar as! CustomizedTabBar
        if (myTabBar.items?[3] == item) {
            myTabBar.arc = false
        } else {
            myTabBar.arc = true
        }
    }
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...