Просмотр исходного кода

Hide keyboard before screen pop animation

Guy Carmeli 8 лет назад
Родитель
Сommit
221d02167c

+ 12
- 4
android/app/src/main/java/com/reactnativenavigation/layouts/BottomTabsLayout.java Просмотреть файл

134
 
134
 
135
     @Override
135
     @Override
136
     public void pop(ScreenParams screenParams) {
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
     @Override
145
     @Override
197
     @Override
201
     @Override
198
     public boolean onTitleBarBackPress() {
202
     public boolean onTitleBarBackPress() {
199
         if (getCurrentScreenStack().canPop()) {
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
             return true;
210
             return true;
203
         }
211
         }
204
 
212
 

+ 30
- 1
android/app/src/main/java/com/reactnativenavigation/screens/ScreenStack.java Просмотреть файл

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

+ 82
- 0
android/app/src/main/java/com/reactnativenavigation/utils/KeyboardVisibilityDetector.java Просмотреть файл

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
+}