For various reasons, people create their own tab bar from scratch. Previously, it was fairly simple by adding a horizontal stack with the buttons for each tab and a UIVisualEffectView with UIBlurEffect in the back.
The iOS 26 tab bar is fairly similar to recreate from scratch too by using a UIGlassEffect instead of the UIBlurEffect . However, I am unable to recreate that “liquidy” droplet background effect behind the selected tab which animates and interacts as you move the selected tab:
I believe this “liquid” is also what’s used by Apple in other controls such as the knob of a UISwitch, knob of the UISlider, the droplet when placing the cursor when typing etc.
How would you recreate that animation in your own custom views or custom tab bar created from scratch?
EDIT 2: This tweet mentions using segmented pickers for this. I am currently investigating this way. I am not sure how to use images in a segment picker.
EDIT:
Currently, I have the tab bar recreated as such:
import UIKit
import SnapKit
class ViewController: UIViewController {
private let blur = UIVisualEffectView()
override func viewDidLoad() {
super.viewDidLoad()
let stackView = UIStackView()
stackView.spacing = 0
stackView.axis = .horizontal
["person.2.fill","person.fill","bell.fill"].forEach { name in
let button = UIButton()
let config = UIImage.SymbolConfiguration(pointSize: 18, weight: .medium, scale: .large)
let img = UIImage(systemName: name, withConfiguration: config)?.withTintColor(.label, renderingMode: .alwaysOriginal)
button.setImage(img, for: .normal)
button.snp.makeConstraints { make in
make.size.equalTo(CGSize(width: 94, height: 54))
}
stackView.addArrangedSubview(button)
}
blur.layer.cornerCurve = .continuous
if #available(iOS 26.0, *) {
let effect = UIGlassEffect(style: .regular)
effect.isInteractive = true
blur.effect = effect
} else {
blur.effect = UIBlurEffect(style: .regular)
}
blur.contentView.addSubview(stackView)
stackView.snp.makeConstraints { make in
make.edges.equalToSuperview().inset(4)
}
view.addSubview(blur)
blur.snp.makeConstraints { (make) in
make.center.equalToSuperview()
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
blur.layer.cornerRadius = blur.frame.height / 2
}
}
