@capgo/capacitor-native-navigation 8.4.2 → 8.4.3
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.
package/README.md
CHANGED
|
@@ -1,21 +1,12 @@
|
|
|
1
1
|
# @capgo/capacitor-native-navigation
|
|
2
2
|
|
|
3
|
-
<a href="https://capgo.app/">
|
|
4
|
-
<img
|
|
5
|
-
src="https://capgo.app/readme-banner.svg?repo=Cap-go/capacitor-native-navigation"
|
|
6
|
-
alt="Capgo - Instant updates for Capacitor"
|
|
7
|
-
/>
|
|
8
|
-
</a>
|
|
3
|
+
<a href="https://capgo.app/?ref=plugin_native_navigation"><img src="https://capgo.app/readme-banner.svg?repo=Cap-go/capacitor-native-navigation" alt="Capgo - Instant updates for Capacitor" /></a>
|
|
9
4
|
|
|
10
5
|
<div align="center">
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
</
|
|
14
|
-
<
|
|
15
|
-
<a href="https://capgo.app/consulting/?ref=plugin_native_navigation">
|
|
16
|
-
Missing a feature? We can build the plugin for you
|
|
17
|
-
</a>
|
|
18
|
-
</h2>
|
|
6
|
+
<p><b>Capgo</b>: open-source live updates for Ionic and Capacitor apps. Ship OTA fixes and features instantly, without waiting for app store review.</p>
|
|
7
|
+
<h2><a href="https://capgo.app/register/?ref=plugin_native_navigation">➡️ Get started for free</a></h2>
|
|
8
|
+
<p>14-day unlimited free trial. No credit card required</p>
|
|
9
|
+
<p><a href="https://capgo.app/consulting/?ref=plugin_native_navigation">Missing a feature? We'll build the plugin for you 💪</a></p>
|
|
19
10
|
</div>
|
|
20
11
|
|
|
21
12
|
Native navbar, tabbar, safe-area handling, and WebView snapshot transitions for Capacitor apps. Your web framework keeps routing and page rendering while this plugin owns the platform surfaces users expect to feel native.
|
|
@@ -105,6 +105,8 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
105
105
|
private final Map<Integer, String> menuActionPlacements = new HashMap<>();
|
|
106
106
|
private final List<NativeTabItem> tabItems = new ArrayList<>();
|
|
107
107
|
private int selectedTabIndex = 0;
|
|
108
|
+
private boolean tabbarDisableIndicator = false;
|
|
109
|
+
private Integer tabbarIndicatorColor = null;
|
|
108
110
|
|
|
109
111
|
@Override
|
|
110
112
|
public void load() {
|
|
@@ -244,6 +246,8 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
244
246
|
tabbarGlassOptions = GlassOptions.from(tabbarGlassConfig, defaultGlassOptions);
|
|
245
247
|
badgeBackgroundColor = colorOption(call, colors, "badgeBackgroundColor", "badgeBackground", Color.rgb(255, 59, 48));
|
|
246
248
|
badgeTextColor = colorOption(call, colors, "badgeTextColor", "badgeText", Color.WHITE);
|
|
249
|
+
tabbarDisableIndicator = call.getBoolean("disableIndicator", false);
|
|
250
|
+
tabbarIndicatorColor = colorOption(call, colors, "indicatorColor", "indicator", null);
|
|
247
251
|
|
|
248
252
|
for (int sourceIndex = 0; sourceIndex < tabs.length(); sourceIndex++) {
|
|
249
253
|
JSONObject tab = tabs.optJSONObject(sourceIndex);
|
|
@@ -644,6 +648,68 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
644
648
|
};
|
|
645
649
|
}
|
|
646
650
|
|
|
651
|
+
private void applyTabbarContainerOutline() {
|
|
652
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP || tabbarContainer == null) {
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
if (tabbarStyle.isCurve()) {
|
|
657
|
+
tabbarContainer.setClipToOutline(false);
|
|
658
|
+
tabbarContainer.setOutlineProvider(ViewOutlineProvider.BACKGROUND);
|
|
659
|
+
if (tabbarGlassBackdrop != null) {
|
|
660
|
+
tabbarGlassBackdrop.setClipToOutline(false);
|
|
661
|
+
tabbarGlassBackdrop.setOutlineProvider(ViewOutlineProvider.BACKGROUND);
|
|
662
|
+
}
|
|
663
|
+
if (tabbarGlassSurface != null) {
|
|
664
|
+
tabbarGlassSurface.setClipToOutline(false);
|
|
665
|
+
tabbarGlassSurface.setOutlineProvider(ViewOutlineProvider.BACKGROUND);
|
|
666
|
+
}
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
ViewOutlineProvider floatingOutlineProvider = floatingTabbarOutlineProvider();
|
|
671
|
+
tabbarContainer.setClipToOutline(false);
|
|
672
|
+
tabbarContainer.setOutlineProvider(floatingOutlineProvider);
|
|
673
|
+
if (tabbarGlassBackdrop != null) {
|
|
674
|
+
tabbarGlassBackdrop.setClipToOutline(true);
|
|
675
|
+
tabbarGlassBackdrop.setOutlineProvider(floatingOutlineProvider);
|
|
676
|
+
}
|
|
677
|
+
if (tabbarGlassSurface != null) {
|
|
678
|
+
tabbarGlassSurface.setClipToOutline(true);
|
|
679
|
+
tabbarGlassSurface.setOutlineProvider(floatingOutlineProvider);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
private ViewOutlineProvider floatingTabbarOutlineProvider() {
|
|
684
|
+
return new ViewOutlineProvider() {
|
|
685
|
+
@Override
|
|
686
|
+
public void getOutline(View view, Outline outline) {
|
|
687
|
+
int width = view.getWidth();
|
|
688
|
+
int height = view.getHeight();
|
|
689
|
+
if (width <= 0 || height <= 0 || tabbar == null) {
|
|
690
|
+
outline.setEmpty();
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
Path path = tabbar.chromeBackgroundPath(width, height);
|
|
695
|
+
if (TabbarChromeSupport.canApplyPathOutline()) {
|
|
696
|
+
outline.setPath(path);
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
boolean hasDetachedTrailing = tabItems.stream().anyMatch((item) -> item.detachedTrailing);
|
|
701
|
+
int capsuleWidth = TabbarChromeSupport.floatingCapsuleWidth(
|
|
702
|
+
width,
|
|
703
|
+
dp(tabbarStyle.height),
|
|
704
|
+
dp(10),
|
|
705
|
+
hasDetachedTrailing
|
|
706
|
+
);
|
|
707
|
+
float radius = Math.min(dp(tabbarStyle.cornerRadius), height / 2f);
|
|
708
|
+
outline.setRoundRect(0, 0, capsuleWidth, height, radius);
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
|
|
647
713
|
private Toolbar ensureToolbar() {
|
|
648
714
|
if (toolbar != null) {
|
|
649
715
|
return toolbar;
|
|
@@ -698,7 +764,6 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
698
764
|
tabbarGlassSurface = new View(getContext());
|
|
699
765
|
tabbarGlassBackdrop.setVisibility(View.GONE);
|
|
700
766
|
tabbarGlassSurface.setVisibility(View.GONE);
|
|
701
|
-
|
|
702
767
|
tabbar = new NativeTabbarLayout(getContext());
|
|
703
768
|
tabbar.setClipChildren(false);
|
|
704
769
|
tabbar.setClipToPadding(false);
|
|
@@ -722,6 +787,7 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
722
787
|
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dp(DEFAULT_TABBAR_DP))
|
|
723
788
|
);
|
|
724
789
|
}
|
|
790
|
+
applyTabbarContainerOutline();
|
|
725
791
|
return tabbar;
|
|
726
792
|
}
|
|
727
793
|
|
|
@@ -788,10 +854,10 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
788
854
|
button.addView(centerFill, new FrameLayout.LayoutParams(centerFillDiameter, centerFillDiameter, Gravity.CENTER));
|
|
789
855
|
}
|
|
790
856
|
|
|
791
|
-
if (!center && selected) {
|
|
857
|
+
if (!center && selected && !tabbarDisableIndicator) {
|
|
792
858
|
GradientDrawable selectedBackground = new GradientDrawable();
|
|
793
859
|
selectedBackground.setShape(GradientDrawable.OVAL);
|
|
794
|
-
selectedBackground.setColor(
|
|
860
|
+
selectedBackground.setColor(TabbarChromeSupport.resolveSelectedIndicatorColor(tabbarIndicatorColor, tintColor));
|
|
795
861
|
View selectedCircle = new View(getContext());
|
|
796
862
|
selectedCircle.setBackground(selectedBackground);
|
|
797
863
|
button.addView(selectedCircle, new FrameLayout.LayoutParams(dp(58), dp(58), Gravity.CENTER));
|
|
@@ -1245,25 +1311,21 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
1245
1311
|
);
|
|
1246
1312
|
}
|
|
1247
1313
|
|
|
1314
|
+
Path chromeBackgroundPath(int width, int height) {
|
|
1315
|
+
return backgroundPath(width, height);
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1248
1318
|
private Path backgroundPath(int width, int height) {
|
|
1249
1319
|
Path path = new Path();
|
|
1250
1320
|
if (!style.isCurve()) {
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
path.addRoundRect(
|
|
1260
|
-
new RectF(left, top, left + diameter, top + diameter),
|
|
1261
|
-
diameter / 2f,
|
|
1262
|
-
diameter / 2f,
|
|
1263
|
-
Path.Direction.CW
|
|
1264
|
-
);
|
|
1265
|
-
}
|
|
1266
|
-
return path;
|
|
1321
|
+
return TabbarChromeSupport.buildFloatingTabbarPath(
|
|
1322
|
+
width,
|
|
1323
|
+
height,
|
|
1324
|
+
dp(style.cornerRadius),
|
|
1325
|
+
dp(style.height),
|
|
1326
|
+
dp(10),
|
|
1327
|
+
detachedTrailingIndex() >= 0
|
|
1328
|
+
);
|
|
1267
1329
|
}
|
|
1268
1330
|
float barTop = dp(style.barTop());
|
|
1269
1331
|
float barHeight = dp(style.height);
|
|
@@ -1607,6 +1669,7 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
1607
1669
|
}
|
|
1608
1670
|
|
|
1609
1671
|
tabbar.setTabbarStyle(tabbarStyle, drawColor, centerIndex);
|
|
1672
|
+
applyTabbarContainerOutline();
|
|
1610
1673
|
}
|
|
1611
1674
|
|
|
1612
1675
|
private int resolvedTabbarSurfaceColor() {
|
|
@@ -1815,6 +1878,15 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
1815
1878
|
tabbarContainer.setLayoutParams(tabbarContainerParams);
|
|
1816
1879
|
fillContainer(tabbarGlassBackdrop);
|
|
1817
1880
|
fillContainer(tabbarGlassSurface);
|
|
1881
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
1882
|
+
tabbarContainer.invalidateOutline();
|
|
1883
|
+
if (tabbarGlassBackdrop != null) {
|
|
1884
|
+
tabbarGlassBackdrop.invalidateOutline();
|
|
1885
|
+
}
|
|
1886
|
+
if (tabbarGlassSurface != null) {
|
|
1887
|
+
tabbarGlassSurface.invalidateOutline();
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1818
1890
|
}
|
|
1819
1891
|
|
|
1820
1892
|
if (tabbar != null) {
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
package app.capgo.nativenavigation;
|
|
2
|
+
|
|
3
|
+
import android.graphics.Path;
|
|
4
|
+
import android.graphics.RectF;
|
|
5
|
+
import android.os.Build;
|
|
6
|
+
|
|
7
|
+
public final class TabbarChromeSupport {
|
|
8
|
+
|
|
9
|
+
public enum TabbarOutlineMode {
|
|
10
|
+
FLOATING_SHAPE,
|
|
11
|
+
CURVE_DEFAULT
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
private TabbarChromeSupport() {}
|
|
15
|
+
|
|
16
|
+
public static int resolveSelectedIndicatorColor(Integer explicitColor, int tintColor) {
|
|
17
|
+
if (explicitColor != null) {
|
|
18
|
+
return explicitColor;
|
|
19
|
+
}
|
|
20
|
+
return (34 << 24) | (tintColor & 0x00FFFFFF);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public static TabbarOutlineMode outlineModeForShape(String shape) {
|
|
24
|
+
return "curve".equals(shape) ? TabbarOutlineMode.CURVE_DEFAULT : TabbarOutlineMode.FLOATING_SHAPE;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public static boolean shouldClipGlassToOutline(TabbarOutlineMode mode) {
|
|
28
|
+
return mode == TabbarOutlineMode.FLOATING_SHAPE;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public static int floatingCapsuleWidth(int totalWidth, int barHeightPx, int trailingGapPx, boolean hasDetachedTrailing) {
|
|
32
|
+
if (!hasDetachedTrailing) {
|
|
33
|
+
return totalWidth;
|
|
34
|
+
}
|
|
35
|
+
return Math.max(0, totalWidth - barHeightPx - trailingGapPx);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public static Path buildFloatingTabbarPath(
|
|
39
|
+
int width,
|
|
40
|
+
int height,
|
|
41
|
+
float cornerRadiusPx,
|
|
42
|
+
float barHeightPx,
|
|
43
|
+
float trailingGapPx,
|
|
44
|
+
boolean hasDetachedTrailing
|
|
45
|
+
) {
|
|
46
|
+
Path path = new Path();
|
|
47
|
+
int capsuleWidth = floatingCapsuleWidth(width, (int) barHeightPx, (int) trailingGapPx, hasDetachedTrailing);
|
|
48
|
+
path.addRoundRect(new RectF(0, 0, capsuleWidth, height), cornerRadiusPx, cornerRadiusPx, Path.Direction.CW);
|
|
49
|
+
if (hasDetachedTrailing) {
|
|
50
|
+
float diameter = barHeightPx;
|
|
51
|
+
float left = width - diameter;
|
|
52
|
+
float top = (height - diameter) / 2f;
|
|
53
|
+
path.addRoundRect(
|
|
54
|
+
new RectF(left, top, left + diameter, top + diameter),
|
|
55
|
+
diameter / 2f,
|
|
56
|
+
diameter / 2f,
|
|
57
|
+
Path.Direction.CW
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
return path;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public static boolean canApplyPathOutline() {
|
|
64
|
+
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.R;
|
|
65
|
+
}
|
|
66
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capgo/capacitor-native-navigation",
|
|
3
|
-
"version": "8.4.
|
|
3
|
+
"version": "8.4.3",
|
|
4
4
|
"description": "Capacitor plugin for native navbar, tabbar, safe-area handling, and WebView snapshot transitions.",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|