[英]How to set rounded corners and shadow for UITabBar?
我想為UITabBar
設置圓角半徑和陰影,但我遇到了問題。 這是我的代碼
tabBar.barTintColor = .white
tabBar.isTranslucent = false
tabBar.layer.shadowOffset = CGSize(width: 0, height: 5)
tabBar.layer.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1).cgColor
tabBar.layer.shadowOpacity = 1;
tabBar.layer.shadowRadius = 25;
tabBar.layer.masksToBounds = false
tabBar.isTranslucent = true
tabBar.barStyle = .blackOpaque
tabBar.layer.cornerRadius = 13
tabBar.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
如果我將tabBar.layer.masksToBounds = false
更改為= true
-> 將顯示角半徑,但不會顯示陰影。
斯威夫特 5
嘗試這個。 我通過在標簽欄后面放置一個自定義視圖來實現它。 這適用於Swift 5
import UIKit
class MainTabBarController:
UITabBarController,
UITabBarControllerDelegate {
let customTabBarView: UIView = {
let view = UIView(frame: .zero)
view.backgroundColor = .white
view.layer.cornerRadius = 20
view.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
view.clipsToBounds = true
view.layer.masksToBounds = false
view.layer.shadowColor = UIColor.black.cgColor
view.layer.shadowOffset = CGSize(width: 0, height: -8.0)
view.layer.shadowOpacity = 0.12
view.layer.shadowRadius = 10.0
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
addCustomTabBarView()
hideTabBarBorder()
setupTabBar()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
customTabBarView.frame = tabBar.frame
}
override func viewDidAppear(_ animated: Bool) {
var newSafeArea = UIEdgeInsets()
newSafeArea.bottom += customTabBarView.bounds.size.height
self.children.forEach({$0.additionalSafeAreaInsets = newSafeArea})
}
private func addCustomTabBarView() {
customTabBarView.frame = tabBar.frame
view.addSubview(customTabBarView)
view.bringSubviewToFront(self.tabBar)
}
func hideTabBarBorder() {
let tabBar = self.tabBar
tabBar.backgroundImage = UIImage.from(color: .clear)
tabBar.shadowImage = UIImage()
tabBar.clipsToBounds = true
}
func setupTabBar() {
self.setViewControllers([tab1, tab2, tab3], animated: false)
self.viewDidLayoutSubviews()
}
}
extension UIImage {
static func from(color: UIColor) -> UIImage {
let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
context!.setFillColor(color.cgColor)
context!.fill(rect)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img!
}
}
我想出了一種方法來做到這一點,通過為標簽欄添加一個單獨的陰影層:
tabBar.clipsToBounds = true
tabBar.layer.cornerRadius = Siz_TabBar_CornerRadius
// For some reason you have to use the vertically opposite corners for this to show up on iPad
tabBar.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
shadowLayer = CALayer()
shadowLayer.frame = tabBar.frame
shadowLayer.backgroundColor = UIColor.clear.cgColor
shadowLayer.cornerRadius = yourTabBarCornerRadius
shadowLayer.shadowColor = yourShadowColor.cgColor
shadowLayer.shadowRadius = yourShadowRadius
shadowLayer.shadowOpacity = 1.0
shadowLayer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
// This is important so the shadow doesn't lag content
// which is scrolling underneath it. You should tell the tab
// bar layer to rasterize as well, the rounded corners can cause
// performance issues with animated content underneath them.
shadowLayer.shouldRasterize = true
shadowLayer.rasterizationScale = UIScreen.main.scale
// The shadow path is needed because a shadow won't
// display for a layer with a clear backgroundColor
let shadowPath = UIBezierPath(roundedRect: shadowLayer.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: yourTabBarCornerRadius, height: yourTabBarCornerRadius))
// The mask makes it so that the shadow doesn't draw on
// top of the tab bar, filling in the whole layer
let maskLayer = CAShapeLayer()
let maskPath = CGMutablePath()
// This path goes around the outside of the possible shadow radius, so that the
// shadow is between this path and the tap bar
maskPath.addRect(CGRect(x: -yourShadowRadius, y: -yourShadowRadius, width: shadowLayer.frame.width + yourShadowRadius, height: shadowLayer.frame.height + yourShadowRadius))
// The shadow path (shape of the tab bar) is drawn on the inside
maskPath.addPath(shadowPath.cgPath)
maskLayer.path = maskPath
// This makes it so that the only shadow layer content that will
// be drawn is located in between the two above paths
maskLayer.fillRule = .evenOdd
shadowLayer.mask = maskLayer
// View here is the tab bar controller's view
view.layer.addSublayer(shadowLayer)
您是對的,設置 maskToBounds=true 是允許應用 tabBar.layer.cornerRadius 值的唯一方法,但將其設置為 true 將移除任何陰影!
許多解決方案涉及在選項卡欄后面添加一個虛擬視圖,並對其應用陰影。 它可以工作,但是一旦我通過在標簽欄后面添加虛擬視圖作為父視圖的子視圖來使其工作,當我嘗試通過使用 hidesBottomBarWhenPushed=true 推送視圖控制器導航到另一個屏幕時,標簽欄被隱藏但虛擬視圖仍保留在屏幕上:(
經過 2 天的反復試驗,我找到了一個不需要添加虛擬視圖的解決方案,而是添加了一個子圖層來圓角並設置陰影。 這很簡單,不涉及子視圖,也不需要將 maskToBounds 設置為 true。
受此答案啟發: https : //stackoverflow.com/a/63793084/1241783
我沒有繼承 UITabBar 的子類,而是創建了一個 UITabBarController 的子類,並添加了這個函數:
private func addShape() {
let shapeLayer = CAShapeLayer()
shapeLayer.path = UIBezierPath(
roundedRect: tabBar.bounds,
byRoundingCorners: [.topLeft, .topRight],
cornerRadii: CGSize(width: tabBarCornerRadius, height: 0.0)).cgPath
shapeLayer.fillColor = UIColor.white.cgColor
shapeLayer.shadowPath = UIBezierPath(roundedRect: tabBar.bounds, cornerRadius: tabBarCornerRadius).cgPath
shapeLayer.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.2).cgColor
shapeLayer.shadowOpacity = 1
shapeLayer.shadowRadius = 16
shapeLayer.shadowOffset = CGSize(width: 0, height: -6)
// To improve rounded corner and shadow performance tremendously
shapeLayer.shouldRasterize = true
shapeLayer.rasterizationScale = UIScreen.main.scale
if let oldShapeLayer = self.shapeLayer {
tabBar.layer.replaceSublayer(oldShapeLayer, with: shapeLayer)
} else {
tabBar.layer.insertSublayer(shapeLayer, at: 0)
}
self.shapeLayer = shapeLayer
}
在 viewDidLayoutSubviews 的覆蓋中調用此函數:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
addShape()
}
最后,拼圖的最后一塊,Tab bar 會自動創建一個沒有圓角的背景視圖,所以我們需要通過在 viewDidLoad 中添加以下兩行來使背景視圖透明:
override func viewDidLoad() {
super.viewDidLoad()
tabBar.shadowImage = UIImage() // this removes the top line of the tabBar
tabBar.backgroundImage = UIImage() // this changes the UI backdrop view of tabBar to transparent
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.