22
33import android .content .Context ;
44import android .graphics .Rect ;
5+ import android .os .Build ;
56import android .util .DisplayMetrics ;
7+ import android .util .TypedValue ;
68import android .view .View ;
79import android .view .Window ;
810import android .view .inputmethod .InputMethodManager ;
1315import androidx .core .view .ViewCompat ;
1416import androidx .core .view .WindowInsetsAnimationCompat ;
1517import androidx .core .view .WindowInsetsCompat ;
18+ import com .getcapacitor .Bridge ;
1619import java .util .List ;
1720
1821public class Keyboard {
@@ -21,6 +24,7 @@ interface KeyboardEventListener {
2124 void onKeyboardEvent (String event , int size );
2225 }
2326
27+ private Bridge bridge ;
2428 private AppCompatActivity activity ;
2529 private View rootView ;
2630 private int usableHeightPrevious ;
@@ -39,8 +43,9 @@ public void setKeyboardEventListener(@Nullable KeyboardEventListener keyboardEve
3943 static final String EVENT_KB_WILL_HIDE = "keyboardWillHide" ;
4044 static final String EVENT_KB_DID_HIDE = "keyboardDidHide" ;
4145
42- public Keyboard (AppCompatActivity activity , boolean resizeOnFullScreen ) {
43- this .activity = activity ;
46+ public Keyboard (Bridge bridge , boolean resizeOnFullScreen ) {
47+ this .bridge = bridge ;
48+ this .activity = this .bridge .getActivity ();
4449
4550 //http://stackoverflow.com/a/4737265/1091751 detect if keyboard is showing
4651 FrameLayout content = activity .getWindow ().getDecorView ().findViewById (android .R .id .content );
@@ -131,9 +136,38 @@ private void possiblyResizeChildOfContent(boolean keyboardShown) {
131136 private int computeUsableHeight () {
132137 Rect r = new Rect ();
133138 mChildOfContent .getWindowVisibleDisplayFrame (r );
139+ if (shouldApplyEdgeToEdgeAdjustments ()) {
140+ WindowInsetsCompat insets = ViewCompat .getRootWindowInsets (rootView );
141+ if (insets != null ) {
142+ int systemBars = insets .getInsets (WindowInsetsCompat .Type .systemBars ()).bottom ;
143+ if (systemBars > 0 ) {
144+ return r .bottom + systemBars ;
145+ }
146+ }
147+ }
148+
134149 return isOverlays () ? r .bottom : r .height ();
135150 }
136151
152+ private boolean shouldApplyEdgeToEdgeAdjustments () {
153+ var adjustMarginsForEdgeToEdge = this .bridge .getConfig ().adjustMarginsForEdgeToEdge ();
154+ if (adjustMarginsForEdgeToEdge .equals ("force" )) { // Force edge-to-edge adjustments regardless of app settings
155+ return true ;
156+ } else if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .VANILLA_ICE_CREAM && adjustMarginsForEdgeToEdge .equals ("auto" )) { // Auto means that we need to check the app's edge-to-edge preference
157+ TypedValue value = new TypedValue ();
158+ boolean optOutAttributeExists = activity
159+ .getTheme ()
160+ .resolveAttribute (android .R .attr .windowOptOutEdgeToEdgeEnforcement , value , true );
161+
162+ if (!optOutAttributeExists ) { // Default is to apply edge to edge
163+ return true ;
164+ } else {
165+ return value .data == 0 ;
166+ }
167+ }
168+ return false ;
169+ }
170+
137171 @ SuppressWarnings ("deprecation" )
138172 private boolean isOverlays () {
139173 final Window window = activity .getWindow ();
0 commit comments