Bladeren bron

Hide keyboard before screen pop animation

Guy Carmeli 8 jaren geleden
bovenliggende
commit
221d02167c

+ 12
- 4
android/app/src/main/java/com/reactnativenavigation/layouts/BottomTabsLayout.java Bestand weergeven

@@ -134,8 +134,12 @@ public class BottomTabsLayout extends RelativeLayout implements Layout, AHBottom
134 134
 
135 135
     @Override
136 136
     public void pop(ScreenParams screenParams) {
137
-        getCurrentScreenStack().pop(screenParams.animateScreenTransitions);
138
-        setBottomTabsStyleFromCurrentScreen();
137
+        getCurrentScreenStack().pop(screenParams.animateScreenTransitions, new ScreenStack.OnScreenPop() {
138
+            @Override
139
+            public void onScreenPopAnimationEnd() {
140
+                setBottomTabsStyleFromCurrentScreen();
141
+            }
142
+        });
139 143
     }
140 144
 
141 145
     @Override
@@ -197,8 +201,12 @@ public class BottomTabsLayout extends RelativeLayout implements Layout, AHBottom
197 201
     @Override
198 202
     public boolean onTitleBarBackPress() {
199 203
         if (getCurrentScreenStack().canPop()) {
200
-            getCurrentScreenStack().pop(true);
201
-            setBottomTabsStyleFromCurrentScreen();
204
+            getCurrentScreenStack().pop(true, new ScreenStack.OnScreenPop() {
205
+                @Override
206
+                public void onScreenPopAnimationEnd() {
207
+                    setBottomTabsStyleFromCurrentScreen();
208
+                }
209
+            });
202 210
             return true;
203 211
         }
204 212
 

+ 30
- 1
android/app/src/main/java/com/reactnativenavigation/screens/ScreenStack.java Bestand weergeven

@@ -1,5 +1,6 @@
1 1
 package com.reactnativenavigation.screens;
2 2
 
3
+import android.support.annotation.Nullable;
3 4
 import android.support.v7.app.AppCompatActivity;
4 5
 import android.view.View;
5 6
 import android.widget.RelativeLayout;
@@ -8,6 +9,7 @@ import com.reactnativenavigation.params.ScreenParams;
8 9
 import com.reactnativenavigation.params.StyleParams;
9 10
 import com.reactnativenavigation.params.TitleBarButtonParams;
10 11
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
12
+import com.reactnativenavigation.utils.KeyboardVisibilityDetector;
11 13
 import com.reactnativenavigation.utils.Task;
12 14
 import com.reactnativenavigation.views.TitleBarBackButtonListener;
13 15
 
@@ -16,10 +18,15 @@ import java.util.Stack;
16 18
 
17 19
 public class ScreenStack {
18 20
 
21
+    public interface OnScreenPop {
22
+        void onScreenPopAnimationEnd();
23
+    }
24
+
19 25
     private final AppCompatActivity activity;
20 26
     private RelativeLayout parent;
21 27
     private TitleBarBackButtonListener titleBarBackButtonListener;
22 28
     private Stack<Screen> stack = new Stack<>();
29
+    private final KeyboardVisibilityDetector keyboardVisibilityDetector;
23 30
 
24 31
     public ScreenStack(AppCompatActivity activity,
25 32
                        RelativeLayout parent,
@@ -27,6 +34,7 @@ public class ScreenStack {
27 34
         this.activity = activity;
28 35
         this.parent = parent;
29 36
         this.titleBarBackButtonListener = titleBarBackButtonListener;
37
+        keyboardVisibilityDetector = new KeyboardVisibilityDetector(parent);
30 38
     }
31 39
 
32 40
     public void pushInitialScreen(ScreenParams initialScreenParams, RelativeLayout.LayoutParams params) {
@@ -58,13 +66,30 @@ public class ScreenStack {
58 66
     }
59 67
 
60 68
     public void pop(boolean animated) {
69
+        pop(animated, null);
70
+    }
71
+
72
+    public void pop(final boolean animated, @Nullable final OnScreenPop onScreenPop) {
61 73
         if (!canPop()) {
62 74
             return;
63 75
         }
64 76
 
65 77
         final Screen toRemove = stack.pop();
66
-        Screen previous = stack.peek();
78
+        final Screen previous = stack.peek();
79
+
80
+        if (keyboardVisibilityDetector.isKeyboardVisible()) {
81
+            keyboardVisibilityDetector.closeKeyboard(new Runnable() {
82
+                @Override
83
+                public void run() {
84
+                    swapScreens(animated, toRemove, previous, onScreenPop);
85
+                }
86
+            });
87
+        } else {
88
+            swapScreens(animated, toRemove, previous, onScreenPop);
89
+        }
90
+    }
67 91
 
92
+    private void swapScreens(boolean animated, final Screen toRemove, Screen previous, OnScreenPop onScreenPop) {
68 93
         readdPrevious(previous);
69 94
         toRemove.hide(animated, new Runnable() {
70 95
             @Override
@@ -73,6 +98,10 @@ public class ScreenStack {
73 98
                 parent.removeView(toRemove);
74 99
             }
75 100
         });
101
+
102
+        if (onScreenPop != null) {
103
+            onScreenPop.onScreenPopAnimationEnd();
104
+        }
76 105
     }
77 106
 
78 107
     public Screen peek() {

+ 82
- 0
android/app/src/main/java/com/reactnativenavigation/utils/KeyboardVisibilityDetector.java Bestand weergeven

@@ -0,0 +1,82 @@
1
+package com.reactnativenavigation.utils;
2
+
3
+import android.app.Activity;
4
+import android.content.Context;
5
+import android.graphics.Rect;
6
+import android.view.View;
7
+import android.view.ViewTreeObserver;
8
+import android.view.inputmethod.InputMethodManager;
9
+
10
+import com.reactnativenavigation.NavigationApplication;
11
+
12
+public class KeyboardVisibilityDetector {
13
+    // 0.15 ratio is perhaps enough to determine keypad height.
14
+    public static final double KEYBOARD_VISIBLE_RATIO = 0.15;
15
+
16
+    private final KeyboardVisibilityLayoutListener keyboardVisibilityListener;
17
+    private final View screen;
18
+    private Runnable keyboardCloseListener;
19
+
20
+    public KeyboardVisibilityDetector(final View screen) {
21
+        this.screen = screen;
22
+        keyboardVisibilityListener = new KeyboardVisibilityLayoutListener(this);
23
+        screen.getViewTreeObserver().addOnGlobalLayoutListener(keyboardVisibilityListener);
24
+    }
25
+
26
+    public boolean isKeyboardVisible() {
27
+        return keyboardVisibilityListener.isKeyboardVisible();
28
+    }
29
+
30
+    public void closeKeyboard(Runnable keyboardClosedListener) {
31
+        Activity context = (Activity) screen.getContext();
32
+        View view = context.getCurrentFocus();
33
+        if (view != null) {
34
+            this.keyboardCloseListener = keyboardClosedListener;
35
+
36
+            InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
37
+            imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
38
+        }
39
+    }
40
+
41
+    private static class KeyboardVisibilityLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener {
42
+        public static final int KEYBOARD_CLOSE_DURATION = 100;
43
+        private View screen;
44
+        private boolean isVisible = false;
45
+        private KeyboardVisibilityDetector detector;
46
+
47
+        public KeyboardVisibilityLayoutListener(KeyboardVisibilityDetector detector) {
48
+            this.detector = detector;
49
+            this.screen = detector.screen;
50
+        }
51
+
52
+        public boolean isKeyboardVisible() {
53
+            return isVisible;
54
+        }
55
+
56
+        @Override
57
+        public void onGlobalLayout() {
58
+            int screenHeight = screen.getRootView().getHeight();
59
+            int screenBottomY = getScreenBottomY(screen);
60
+
61
+            int keyboardHeight = screenHeight - screenBottomY;
62
+            if (isKeyboardVisible(screenHeight, keyboardHeight)) {
63
+                isVisible = true;
64
+            } else {
65
+                if (isVisible && detector.keyboardCloseListener != null) {
66
+                    NavigationApplication.instance.runOnMainThread(detector.keyboardCloseListener, KEYBOARD_CLOSE_DURATION);
67
+                }
68
+                isVisible = false;
69
+            }
70
+        }
71
+
72
+        private boolean isKeyboardVisible(int screenHeight, int keypadHeight) {
73
+            return keypadHeight > screenHeight * KEYBOARD_VISIBLE_RATIO;
74
+        }
75
+
76
+        private int getScreenBottomY(View screen) {
77
+            Rect r = new Rect();
78
+            screen.getWindowVisibleDisplayFrame(r);
79
+            return r.bottom;
80
+        }
81
+    }
82
+}