自定义标签栏,中央按钮将被按下的索引隐藏
Custom Tab Bar, with central button which will be hide by pressed index
我如何创建带有 4 个项目和一个位于中心的 FAB 的自定义选项卡栏,但 Fab 按钮仅在我按下索引 3 时显示,对于索引 0 .. 3 fab.isHidden = true。如果移动,我不需要那个按钮的动画,但填充是加号),只显示/隐藏。为了创建自定义标签蝙蝠,我使用本指南https://medium.com/better-programming/draw-a-custom-ios-tabbar-shape-27d298a7f4fa, I am need create tab bar like this , I am try maenter 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), y: 0),
// controlPoint1: CGPoint(x: centerWidth + 25, y: height), controlPoint2: CGPoint(x: (centerWidth + 30), y: 0))
// cirle inside tab bar
path.addArc(withCenter: CGPoint(x: centerWidth, y: 0), 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, y: 0), 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
}
}
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”创建两个 class 这个 class 包含形状和你想要的“UITabBar”,第二个 class对于“UITabBarController”在 ViewControllers 之间切换,我们可以添加动画....这是需要的,因为我的 TabBar 有 4 个选项卡,只有在最后一个选项卡上我有带动画的中央 FAB 按钮,我应该制作动画出现按钮时我的 2 和 3 ui 标签栏元素的位置。
Class 对于“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, y: (r/2.0)), 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, y: 0), 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 }
}
和 class 用于 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
}
}
}
我如何创建带有 4 个项目和一个位于中心的 FAB 的自定义选项卡栏,但 Fab 按钮仅在我按下索引 3 时显示,对于索引 0 .. 3 fab.isHidden = true。如果移动,我不需要那个按钮的动画,但填充是加号),只显示/隐藏。为了创建自定义标签蝙蝠,我使用本指南https://medium.com/better-programming/draw-a-custom-ios-tabbar-shape-27d298a7f4fa, I am need create tab bar like this , I am try maenter 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), y: 0),
// controlPoint1: CGPoint(x: centerWidth + 25, y: height), controlPoint2: CGPoint(x: (centerWidth + 30), y: 0))
// cirle inside tab bar
path.addArc(withCenter: CGPoint(x: centerWidth, y: 0), 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, y: 0), 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
}
}
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”创建两个 class 这个 class 包含形状和你想要的“UITabBar”,第二个 class对于“UITabBarController”在 ViewControllers 之间切换,我们可以添加动画....这是需要的,因为我的 TabBar 有 4 个选项卡,只有在最后一个选项卡上我有带动画的中央 FAB 按钮,我应该制作动画出现按钮时我的 2 和 3 ui 标签栏元素的位置。
Class 对于“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, y: (r/2.0)), 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, y: 0), 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 }
}
和 class 用于 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
}
}
}