-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feat: System Bars Plugin #8180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
feat: System Bars Plugin #8180
Changes from 26 commits
Commits
Show all changes
52 commits
Select commit
Hold shift + click to select a range
2b49827
Setting on core definitions and docs for SystemBars plugin
theproducer b78f69f
Renaming, adding basic docs
theproducer edb5288
Adding Android SystemBars basic functionality
theproducer 3bb5784
Adding Android safe area injection
theproducer 6ddb7b9
fmt
theproducer 9e6b41a
Adding insets support to setting style and hiding
theproducer 2c93ccd
Starting on overlay webview support
theproducer c4be18d
Cleanup, adding support for configuration
theproducer 11c5590
Fixes to type declarations
theproducer 07d6b3f
Updating meaning of LIGHT vs DARK
theproducer 0698ca7
Updating style to match documentation on iOS
theproducer 8bcd46d
Rename `enable` to `enableInsets`
theproducer 15fab3a
Merge branch 'main' into RDMR-902
theproducer bf2fe33
fmt
theproducer bbfb49b
Removing overlay support
theproducer c6664d1
Adding webview version check, optimizing insets injection
theproducer 55717fd
fmt
theproducer 0f7d843
Merge branch 'main' into RDMR-902
theproducer ba72a20
Adding config option for hiding system bars
theproducer e6bd10b
Adding support for configurations in iOS system bars
theproducer 929aa33
Adding support for setting iOS status bar animations
theproducer 114367d
Making showing / hiding status bars more friendly
theproducer e8df7ae
naming and consistency
theproducer 7eb6aed
documentation
theproducer 6fb8d70
docs, fmt
theproducer a104cea
fmt
theproducer 7ca256c
Removing enableInsets setting in exchange for meta viewport checking
theproducer 21f473b
Removing Cap 7 edgeToEdgeHandler
theproducer be27917
Merge branch 'main' into RDMR-902
theproducer cd2fb6c
Adding ability to control iOS home indicator visibility
theproducer cf0b1f9
fmt
theproducer ec05a18
Readding `adjustMarginsForEdgeToEdge`, defaulted to “auto”
theproducer 984a254
webview and viewport check fix
theproducer 0978ba3
Adding more checks for edge to edge mode inside `setupSafeAreaInsets`
theproducer d5504fa
Using bridge webview parent view to apply insets
theproducer 39872aa
docs
theproducer b90b657
Removing unneeded dispatchEvent
theproducer 0a51081
ios tweaks
theproducer 188e5ba
ios tweaks
theproducer 6a43397
fmt
theproducer 8be67e9
Merge branch 'main' into RDMR-902
markemer dd019b9
Merge branch 'main' into RDMR-902
theproducer 0334463
Merge branch 'RDMR-902' of github.com:ionic-team/capacitor into RDMR-902
theproducer ca6607c
lint
theproducer b69f466
Adding document table explaining difference between SystemBars and St…
theproducer 5dda6ae
Adding `disableInsets` options
theproducer 4136185
Fixing lint errors
theproducer 44d4ab5
More docs improvements
theproducer 06ec8b3
Renaming insets to SystemBarType
theproducer 79e319e
Updating docs
theproducer 28018be
Merge branch 'main' into RDMR-902
theproducer dc1ef57
more doc tweaks
theproducer File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
200 changes: 200 additions & 0 deletions
200
android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,200 @@ | ||
| package com.getcapacitor.plugin; | ||
|
|
||
| import android.content.pm.PackageInfo; | ||
| import android.content.res.Configuration; | ||
| import android.view.View; | ||
| import android.view.Window; | ||
| import androidx.core.graphics.Insets; | ||
| import androidx.core.view.ViewCompat; | ||
| import androidx.core.view.WindowCompat; | ||
| import androidx.core.view.WindowInsetsCompat; | ||
| import androidx.core.view.WindowInsetsControllerCompat; | ||
| import androidx.webkit.WebViewCompat; | ||
| import com.getcapacitor.Plugin; | ||
| import com.getcapacitor.PluginCall; | ||
| import com.getcapacitor.PluginMethod; | ||
| import com.getcapacitor.annotation.CapacitorPlugin; | ||
| import java.util.Locale; | ||
| import java.util.regex.Matcher; | ||
| import java.util.regex.Pattern; | ||
|
|
||
| @CapacitorPlugin | ||
| public class SystemBars extends Plugin { | ||
|
|
||
| static final String STYLE_LIGHT = "LIGHT"; | ||
| static final String STYLE_DARK = "DARK"; | ||
| static final String STYLE_DEFAULT = "DEFAULT"; | ||
| static final String INSET_TOP = "TOP"; | ||
| static final String INSET_BOTTOM = "BOTTOM"; | ||
|
|
||
| @Override | ||
| public void load() { | ||
| super.load(); | ||
| initSystemBars(); | ||
| } | ||
|
|
||
| private boolean hasFixedWebView() { | ||
| PackageInfo packageInfo = WebViewCompat.getCurrentWebViewPackage(bridge.getContext()); | ||
| Pattern pattern = Pattern.compile("(\\d+)"); | ||
| Matcher matcher = pattern.matcher(packageInfo.versionName); | ||
|
|
||
| if (!matcher.find()) { | ||
| return false; | ||
| } | ||
|
|
||
| String majorVersionStr = matcher.group(0); | ||
| int majorVersion = Integer.parseInt(majorVersionStr); | ||
|
|
||
| return majorVersion >= 140; | ||
| } | ||
|
|
||
| private void initSystemBars() { | ||
| boolean enableInsets = getConfig().getBoolean("enableInsets", true); | ||
| String style = getConfig().getString("style", STYLE_DEFAULT).toUpperCase(); | ||
| boolean hidden = getConfig().getBoolean("hidden", false); | ||
|
|
||
| if (enableInsets) { | ||
| setupSafeAreaInsets(); | ||
| } | ||
|
|
||
| getBridge() | ||
| .executeOnMainThread(() -> { | ||
| setStyle(style, ""); | ||
| setHidden(hidden, ""); | ||
| }); | ||
| } | ||
|
|
||
| @PluginMethod | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The swift equivalents of the plugin methods here are annotated with a |
||
| public void setStyle(final PluginCall call) { | ||
| String inset = call.getString("inset", "").toUpperCase(Locale.US); | ||
| String style = call.getString("style", STYLE_DEFAULT); | ||
|
|
||
| getBridge() | ||
| .executeOnMainThread(() -> { | ||
| setStyle(style, inset); | ||
| call.resolve(); | ||
| }); | ||
| } | ||
|
|
||
| @PluginMethod | ||
| public void show(final PluginCall call) { | ||
| String inset = call.getString("inset", "").toUpperCase(Locale.US); | ||
|
|
||
| getBridge() | ||
| .executeOnMainThread(() -> { | ||
| setHidden(false, inset); | ||
| call.resolve(); | ||
| }); | ||
| } | ||
|
|
||
| @PluginMethod | ||
| public void hide(final PluginCall call) { | ||
| String inset = call.getString("inset", "").toUpperCase(Locale.US); | ||
|
|
||
| getBridge() | ||
| .executeOnMainThread(() -> { | ||
| setHidden(true, inset); | ||
| call.resolve(); | ||
| }); | ||
| } | ||
|
|
||
| @PluginMethod | ||
| public void setAnimation(final PluginCall call) { | ||
| call.resolve(); | ||
| } | ||
|
|
||
| private void setupSafeAreaInsets() { | ||
| View decorView = getActivity().getWindow().getDecorView(); | ||
|
|
||
| ViewCompat.setOnApplyWindowInsetsListener(decorView, (v, insets) -> { | ||
theproducer marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| if (!this.hasFixedWebView()) { | ||
| Insets safeArea = insets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout()); | ||
| injectSafeAreaCSS(safeArea.top, safeArea.right, safeArea.bottom, safeArea.left); | ||
|
|
||
| return WindowInsetsCompat.CONSUMED; | ||
| } | ||
|
|
||
| return insets; | ||
| }); | ||
| } | ||
|
|
||
| private void injectSafeAreaCSS(int top, int right, int bottom, int left) { | ||
| // Convert pixels to density-independent pixels | ||
| float density = getActivity().getResources().getDisplayMetrics().density; | ||
| float topPx = top / density; | ||
| float rightPx = right / density; | ||
| float bottomPx = bottom / density; | ||
| float leftPx = left / density; | ||
|
|
||
| // Execute JavaScript to inject the CSS | ||
| getBridge() | ||
| .executeOnMainThread(() -> { | ||
| if (bridge != null && bridge.getWebView() != null) { | ||
| String script = String.format( | ||
| Locale.US, | ||
| """ | ||
| try { | ||
| document.documentElement.style.setProperty("--safe-area-inset-top", "%dpx"); | ||
| document.documentElement.style.setProperty("--safe-area-inset-right", "%dpx"); | ||
| document.documentElement.style.setProperty("--safe-area-inset-bottom", "%dpx"); | ||
| document.documentElement.style.setProperty("--safe-area-inset-left", "%dpx"); | ||
| window.dispatchEvent(new CustomEvent('safeAreaChanged')); | ||
theproducer marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } catch(e) { console.error('Error injecting safe area CSS:', e); } | ||
| """, | ||
| (int) topPx, | ||
| (int) rightPx, | ||
| (int) bottomPx, | ||
| (int) leftPx | ||
| ); | ||
|
|
||
| bridge.getWebView().evaluateJavascript(script, null); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| private void setStyle(String style, String inset) { | ||
| if (style.equals(STYLE_DEFAULT)) { | ||
| style = getStyleForTheme(); | ||
| } | ||
|
|
||
| Window window = getActivity().getWindow(); | ||
| WindowInsetsControllerCompat windowInsetsControllerCompat = WindowCompat.getInsetsController(window, window.getDecorView()); | ||
| if (inset.isEmpty() || inset.equals(INSET_TOP)) { | ||
| windowInsetsControllerCompat.setAppearanceLightStatusBars(!style.equals(STYLE_DARK)); | ||
| } | ||
|
|
||
| if (inset.isEmpty() || inset.equals(INSET_BOTTOM)) { | ||
| windowInsetsControllerCompat.setAppearanceLightNavigationBars(!style.equals(STYLE_DARK)); | ||
| } | ||
| } | ||
|
|
||
| private void setHidden(boolean hide, String inset) { | ||
| Window window = getActivity().getWindow(); | ||
| WindowInsetsControllerCompat windowInsetsControllerCompat = WindowCompat.getInsetsController(window, window.getDecorView()); | ||
|
|
||
| if (hide) { | ||
| if (inset.isEmpty() || inset.equals(INSET_TOP)) { | ||
| windowInsetsControllerCompat.hide(WindowInsetsCompat.Type.statusBars()); | ||
| } | ||
| if (inset.isEmpty() || inset.equals(INSET_BOTTOM)) { | ||
| windowInsetsControllerCompat.hide(WindowInsetsCompat.Type.navigationBars()); | ||
| } | ||
| return; | ||
| } | ||
|
|
||
| if (inset.isEmpty() || inset.equals(INSET_TOP)) { | ||
| windowInsetsControllerCompat.show(WindowInsetsCompat.Type.systemBars()); | ||
| } | ||
| if (inset.isEmpty() || inset.equals(INSET_BOTTOM)) { | ||
OS-pedrogustavobilro marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| windowInsetsControllerCompat.show(WindowInsetsCompat.Type.navigationBars()); | ||
| } | ||
| } | ||
|
|
||
| private String getStyleForTheme() { | ||
| int currentNightMode = getActivity().getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; | ||
| if (currentNightMode != Configuration.UI_MODE_NIGHT_YES) { | ||
| return STYLE_LIGHT; | ||
| } | ||
| return STYLE_DARK; | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.