@ajuarezso/capacitor-liquid-glass 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -47,6 +47,11 @@ final class LiquidGlassTabBarOverlay: NSObject {
|
|
|
47
47
|
private weak var window: UIWindow?
|
|
48
48
|
private var tabBar: UITabBar?
|
|
49
49
|
private var items: [LiquidGlassTabItem] = []
|
|
50
|
+
/// Overlay `UIVisualEffectView` que provee el material cuando el style es
|
|
51
|
+
/// `.liquidGlass`. Solo se monta cuando el estilo lo requiere, y se
|
|
52
|
+
/// destruye al cambiar a otro estilo. Vive como subview del window justo
|
|
53
|
+
/// DEBAJO del `tabBar` (que en este modo queda 100% transparente).
|
|
54
|
+
private var glassOverlayView: UIVisualEffectView?
|
|
50
55
|
|
|
51
56
|
func attach(to window: UIWindow) {
|
|
52
57
|
if self.window === window, tabBar != nil { return }
|
|
@@ -76,37 +81,36 @@ final class LiquidGlassTabBarOverlay: NSObject {
|
|
|
76
81
|
/// - `default`: Liquid Glass (iOS 26+) o blur translúcido como fallback.
|
|
77
82
|
/// - `ultraThin`: blur mínimo `systemUltraThinMaterial` — más ver-through.
|
|
78
83
|
/// - `transparent`: sin background ni blur — content behind se ve completo.
|
|
84
|
+
/// - `liquidGlass`: tab bar 100% transparente + overlay `UIVisualEffectView`
|
|
85
|
+
/// con `UIGlassEffect` (iOS 26+) o `systemThinMaterial` fallback.
|
|
79
86
|
private func applyAppearance(_ tabBar: UITabBar, style: LiquidGlassTabBarStyle) {
|
|
80
87
|
let appearance = UITabBarAppearance()
|
|
81
88
|
switch style {
|
|
82
89
|
case .default:
|
|
83
90
|
appearance.configureWithDefaultBackground()
|
|
91
|
+
removeGlassOverlay()
|
|
84
92
|
case .ultraThin:
|
|
85
93
|
appearance.configureWithDefaultBackground()
|
|
86
94
|
appearance.backgroundEffect = UIBlurEffect(style: .systemUltraThinMaterial)
|
|
87
95
|
appearance.backgroundColor = UIColor.clear
|
|
96
|
+
removeGlassOverlay()
|
|
88
97
|
case .transparent:
|
|
89
98
|
appearance.configureWithTransparentBackground()
|
|
90
99
|
appearance.backgroundEffect = nil
|
|
91
100
|
appearance.backgroundColor = UIColor.clear
|
|
92
101
|
appearance.shadowColor = UIColor.clear
|
|
102
|
+
removeGlassOverlay()
|
|
93
103
|
case .liquidGlass:
|
|
94
|
-
//
|
|
95
|
-
//
|
|
96
|
-
// el
|
|
97
|
-
//
|
|
98
|
-
//
|
|
99
|
-
appearance.
|
|
100
|
-
|
|
101
|
-
if #available(iOS 26.0, *) {
|
|
102
|
-
appearance.backgroundEffect = UIGlassEffect()
|
|
103
|
-
} else {
|
|
104
|
-
appearance.backgroundEffect = UIBlurEffect(style: .systemThinMaterial)
|
|
105
|
-
}
|
|
106
|
-
#else
|
|
107
|
-
appearance.backgroundEffect = UIBlurEffect(style: .systemThinMaterial)
|
|
108
|
-
#endif
|
|
104
|
+
// Tab bar 100% transparente — el material lo aporta el overlay
|
|
105
|
+
// `UIVisualEffectView` con `UIGlassEffect` montado debajo del bar.
|
|
106
|
+
// Es el patrón canon de iOS 26 para aplicar Liquid Glass real a
|
|
107
|
+
// controles que no exponen API directa para asignarlo (UITabBar
|
|
108
|
+
// solo acepta `UIBlurEffect` en `backgroundEffect`).
|
|
109
|
+
appearance.configureWithTransparentBackground()
|
|
110
|
+
appearance.backgroundEffect = nil
|
|
109
111
|
appearance.backgroundColor = UIColor.clear
|
|
112
|
+
appearance.shadowColor = UIColor.clear
|
|
113
|
+
installGlassOverlay(behind: tabBar)
|
|
110
114
|
}
|
|
111
115
|
tabBar.standardAppearance = appearance
|
|
112
116
|
if #available(iOS 15.0, *) {
|
|
@@ -114,6 +118,50 @@ final class LiquidGlassTabBarOverlay: NSObject {
|
|
|
114
118
|
}
|
|
115
119
|
}
|
|
116
120
|
|
|
121
|
+
/// Monta un `UIVisualEffectView` con `UIGlassEffect` (iOS 26+) o
|
|
122
|
+
/// `systemThinMaterial` como fallback, justo DEBAJO del `tabBar` en el
|
|
123
|
+
/// z-order del window. `tabBar` está en modo transparente, así que todo
|
|
124
|
+
/// el material visible viene del overlay.
|
|
125
|
+
///
|
|
126
|
+
/// El overlay queda con `isUserInteractionEnabled = false` para no
|
|
127
|
+
/// interferir con los taps que el `tabBar` consume por encima.
|
|
128
|
+
private func installGlassOverlay(behind tabBar: UITabBar) {
|
|
129
|
+
guard let parent = tabBar.superview else { return }
|
|
130
|
+
// Idempotente: si ya existe overlay no recrearlo (evita flicker en
|
|
131
|
+
// re-configs por badge updates u otros cambios sin style change).
|
|
132
|
+
if glassOverlayView != nil { return }
|
|
133
|
+
|
|
134
|
+
let effect: UIVisualEffect
|
|
135
|
+
#if compiler(>=6.1)
|
|
136
|
+
if #available(iOS 26.0, *) {
|
|
137
|
+
effect = UIGlassEffect()
|
|
138
|
+
} else {
|
|
139
|
+
effect = UIBlurEffect(style: .systemThinMaterial)
|
|
140
|
+
}
|
|
141
|
+
#else
|
|
142
|
+
effect = UIBlurEffect(style: .systemThinMaterial)
|
|
143
|
+
#endif
|
|
144
|
+
|
|
145
|
+
let overlay = UIVisualEffectView(effect: effect)
|
|
146
|
+
overlay.translatesAutoresizingMaskIntoConstraints = false
|
|
147
|
+
overlay.isUserInteractionEnabled = false
|
|
148
|
+
parent.insertSubview(overlay, belowSubview: tabBar)
|
|
149
|
+
|
|
150
|
+
NSLayoutConstraint.activate([
|
|
151
|
+
overlay.leadingAnchor.constraint(equalTo: tabBar.leadingAnchor),
|
|
152
|
+
overlay.trailingAnchor.constraint(equalTo: tabBar.trailingAnchor),
|
|
153
|
+
overlay.topAnchor.constraint(equalTo: tabBar.topAnchor),
|
|
154
|
+
overlay.bottomAnchor.constraint(equalTo: tabBar.bottomAnchor),
|
|
155
|
+
])
|
|
156
|
+
|
|
157
|
+
self.glassOverlayView = overlay
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private func removeGlassOverlay() {
|
|
161
|
+
glassOverlayView?.removeFromSuperview()
|
|
162
|
+
glassOverlayView = nil
|
|
163
|
+
}
|
|
164
|
+
|
|
117
165
|
func configure(items: [LiquidGlassTabItem], selectedIndex: Int, tintHex: String?, style: LiquidGlassTabBarStyle) {
|
|
118
166
|
guard let tabBar else { return }
|
|
119
167
|
|
|
@@ -173,6 +221,12 @@ final class LiquidGlassTabBarOverlay: NSObject {
|
|
|
173
221
|
tabBar.isHidden = false
|
|
174
222
|
tabBar.alpha = 0
|
|
175
223
|
tabBar.transform = CGAffineTransform(translationX: 0, y: 20)
|
|
224
|
+
// Sincronizar el overlay glass (si está montado) con la misma curva,
|
|
225
|
+
// sino el material queda visible mientras el bar fade-out/in.
|
|
226
|
+
let overlay = glassOverlayView
|
|
227
|
+
overlay?.isHidden = false
|
|
228
|
+
overlay?.alpha = 0
|
|
229
|
+
overlay?.transform = CGAffineTransform(translationX: 0, y: 20)
|
|
176
230
|
// Fade-in + slide-up (curva native iOS para apariciones)
|
|
177
231
|
UIView.animate(
|
|
178
232
|
withDuration: 0.28,
|
|
@@ -183,6 +237,8 @@ final class LiquidGlassTabBarOverlay: NSObject {
|
|
|
183
237
|
animations: {
|
|
184
238
|
tabBar.alpha = 1
|
|
185
239
|
tabBar.transform = .identity
|
|
240
|
+
overlay?.alpha = 1
|
|
241
|
+
overlay?.transform = .identity
|
|
186
242
|
},
|
|
187
243
|
completion: nil
|
|
188
244
|
)
|
|
@@ -193,6 +249,7 @@ final class LiquidGlassTabBarOverlay: NSObject {
|
|
|
193
249
|
guard let tabBar = tabBar else { return }
|
|
194
250
|
if tabBar.isHidden { return }
|
|
195
251
|
// Fade-out + slide-down (más rápido que el show — el exit es snappy)
|
|
252
|
+
let overlay = glassOverlayView
|
|
196
253
|
UIView.animate(
|
|
197
254
|
withDuration: 0.18,
|
|
198
255
|
delay: 0,
|
|
@@ -200,10 +257,14 @@ final class LiquidGlassTabBarOverlay: NSObject {
|
|
|
200
257
|
animations: {
|
|
201
258
|
tabBar.alpha = 0
|
|
202
259
|
tabBar.transform = CGAffineTransform(translationX: 0, y: 20)
|
|
260
|
+
overlay?.alpha = 0
|
|
261
|
+
overlay?.transform = CGAffineTransform(translationX: 0, y: 20)
|
|
203
262
|
},
|
|
204
263
|
completion: { _ in
|
|
205
264
|
tabBar.isHidden = true
|
|
206
265
|
tabBar.transform = .identity
|
|
266
|
+
overlay?.isHidden = true
|
|
267
|
+
overlay?.transform = .identity
|
|
207
268
|
}
|
|
208
269
|
)
|
|
209
270
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ajuarezso/capacitor-liquid-glass",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "iOS 26 Liquid Glass native chrome (TabBar, NavigationBar, Alerts, Sheets) for Capacitor apps. Falls back gracefully on iOS < 26 and Android.",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|