在阅读了有关自定义UITabBarControllers的几篇文章之后,我比开始研究之前更加困惑。
我的目标是创建具有3个重要属性的自定义TabBar:
这是我要实现的目标:
我已经能够通过遵循另一个StackOverflow答案(Remove tab bar item text, show only image)来删除文本并使图标居中,尽管该解决方案对我来说似乎是很简单的事情。
我该如何在项目后面创建一个圆圈并更改活动项目的颜色?
还有,有人介意解释XCode检查器部分“ Tab Bar Item”和“ Bar Item”之间的区别,它们之间直接相邻吗?
答案 0 :(得分:1)
最简单且实际上最干净的方法是设计图标并将其作为图像导入到.xcassets文件夹中。然后,您可以使用以下命令为每个viewController的不同状态设置不同的图标:
ViewController.tabBarItem = UITabBarItem(title: "", image: yourImage.withRenderingMode(.alwaysOriginal), selectedImage: yourImage)
您选择的图像将是带有圆圈的图像,而图像将没有。它比用xcode操纵图像要容易得多,并且也便宜得多,因为编译器只需要渲染图像而不必操纵它们。
关于另一个问题UIBarItem是
可以添加到显示在屏幕底部的栏中的项目的抽象超类。
UITabBarItem是UIBarItem的子类,以提供额外的功能。
答案 1 :(得分:1)
第一步很简单:将UITabbarItem的title属性保留为空会隐藏标签。
您的第二步实际上可以分为两步:更改图标的颜色并在其后面添加一个圆圈。
这里的第一步又很简单:您可以为当前选择的ViewController设置一个不同的图标(我使用Storyboard,这个过程非常简单)。您要做的就是添加一个白色版本的图标,当该菜单选项被选中时将显示。
最后一步是显示圆圈。为此,我们需要以下信息:
这两个中的第一个很容易找到,但是第二个带来了一个问题:UITabBar中的图标在屏幕上的间距不相等,因此我们不能仅将选项卡的宽度除以数量,然后取其中一半找到图标的中心。相反,我们将把UITabBarController子类化。
注意:UITabBarController的tabBar属性确实具有
.selectionIndicatorImage
属性。您可以为此分配一个图像,该图像将显示在图标后面。但是,您无法轻松控制此图像的位置,因此这就是为什么我们仍然要继承UITabBarController的原因。
class CircledTabBarController: UITabBarController {
var circle: UIView?
override func viewDidLoad() {
super.viewDidLoad()
let numberOfItems = CGFloat(tabBar.items!.count)
let tabBarItemSize = CGSize(width: (tabBar.frame.width / numberOfItems) - 20, height: tabBar.frame.height)
circle = UIView(frame: CGRect(x: 0, y: 0, width: tabBarItemSize.height, height: tabBarItemSize.height))
circle?.backgroundColor = .darkGray
circle?.layer.cornerRadius = circle!.frame.width/2
circle?.alpha = 0
tabBar.addSubview(circle!)
tabBar.sendSubview(toBack: circle!)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let index = -(tabBar.items?.index(of: tabBar.selectedItem!)?.distance(to: 0))!
let frame = frameForTabAtIndex(index: index)
circle?.center.x = frame.origin.x + frame.width/2
circle?.alpha = 1
}
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
let index = -(tabBar.items?.index(of: item)?.distance(to: 0))!
let frame = frameForTabAtIndex(index: index)
self.circle?.center.x = frame.origin.x + frame.width/2
}
func frameForTabAtIndex(index: Int) -> CGRect {
var frames = tabBar.subviews.compactMap { (view:UIView) -> CGRect? in
if let view = view as? UIControl {
for item in view.subviews {
if let image = item as? UIImageView {
return image.superview!.convert(image.frame, to: tabBar)
}
}
return view.frame
}
return nil
}
frames.sort { $0.origin.x < $1.origin.x }
if frames.count > index {
return frames[index]
}
return frames.last ?? CGRect.zero
}
}
现在使用UITabBarController的这个子类代替基类。
那么,为什么只将图标更改为带圆圈的图标呢?因为您可以用这做很多不同的事情。 I wrote an article about animating the UITabBarController in a similar manner,并且,如果您愿意,也可以轻松使用上述实现向自己的动画添加动画。