Browse Source

Auto blur on unmount option (#4191)

This adds an Android-only flag blurOnUnmount, that if true when calling push, pop, showModal, dismisModal, as well as when true on the component's static options(passProps) { ... } return value, will cause RNN to check for any focused views when the component the flag was passed for is being unmounted, and blur said view if it exists, causing not just the view to lose focus, but also the soft keyboard to be dismissed.

We added this to our fork of RNN to tackle issues stemming from an inability to dismiss the soft keyboard on unmounting components, due to the disappear/unmount lifecycle events of the component coming too late for our keyboard dismissal calls to make it across the native<->js bridge before the component was unmounted.

As this functionality is hidden behind a flag and does not alter base functionality, and the issue it seeks to solve might have been encountered by other users of RNN, I figured I might as well submit a PR to see if there is interest in merging this back into the base.
Evan Ricketts 6 years ago
parent
commit
34a4675edc

+ 17
- 6
lib/android/app/src/main/java/com/reactnativenavigation/parse/ModalOptions.java View File

@@ -1,29 +1,40 @@
1 1
 package com.reactnativenavigation.parse;
2 2
 
3
+import android.support.annotation.NonNull;
4
+
5
+import com.reactnativenavigation.parse.params.Bool;
6
+import com.reactnativenavigation.parse.params.NullBool;
7
+import com.reactnativenavigation.parse.parsers.BoolParser;
8
+
3 9
 import org.json.JSONObject;
4 10
 
5 11
 public class ModalOptions {
6 12
 
7
-    public static ModalOptions parse(JSONObject json) {
13
+    public static ModalOptions parse(final JSONObject json) {
8 14
         ModalOptions options = new ModalOptions();
9 15
         if (json == null) return options;
10 16
 
11 17
         options.presentationStyle = ModalPresentationStyle.fromString(json.optString("modalPresentationStyle"));
18
+        options.blurOnUnmount = BoolParser.parse(json, "blurOnUnmount");
12 19
 
13 20
         return options;
14 21
     }
15 22
 
16 23
     public ModalPresentationStyle presentationStyle = ModalPresentationStyle.Unspecified;
24
+    public @NonNull Bool blurOnUnmount = new NullBool();
17 25
 
18
-    public void mergeWith(ModalOptions other) {
19
-        if (other.hasValue()) presentationStyle = other.presentationStyle;
26
+    public void mergeWith(final ModalOptions other) {
27
+        if (other.presentationStyleHasValue()) presentationStyle = other.presentationStyle;
28
+        if (other.blurOnUnmount.hasValue()) blurOnUnmount = other.blurOnUnmount;
20 29
     }
21 30
 
22
-    private boolean hasValue() {
31
+    private boolean presentationStyleHasValue() {
23 32
         return presentationStyle != ModalPresentationStyle.Unspecified;
24 33
     }
25 34
 
26
-    public void mergeWithDefault(ModalOptions defaultOptions) {
27
-        if (!hasValue()) presentationStyle = defaultOptions.presentationStyle;
35
+    public void mergeWithDefault(final ModalOptions defaultOptions) {
36
+        if (!presentationStyleHasValue()) presentationStyle = defaultOptions.presentationStyle;
37
+        if (!blurOnUnmount.hasValue()) blurOnUnmount = defaultOptions.blurOnUnmount;
28 38
     }
39
+
29 40
 }

+ 18
- 0
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ComponentViewController.java View File

@@ -2,6 +2,7 @@ package com.reactnativenavigation.viewcontrollers;
2 2
 
3 3
 import android.app.Activity;
4 4
 import android.support.annotation.NonNull;
5
+import android.view.View;
5 6
 
6 7
 import com.reactnativenavigation.parse.Options;
7 8
 import com.reactnativenavigation.presentation.Presenter;
@@ -71,4 +72,21 @@ public class ComponentViewController extends ChildController<ComponentLayout> {
71 72
     ReactComponent getComponent() {
72 73
         return view;
73 74
     }
75
+
76
+    @Override
77
+    public void destroy() {
78
+        final boolean blurOnUnmount = options != null && options.modal.blurOnUnmount.isTrue();
79
+        if (blurOnUnmount) {
80
+            blurActivityFocus();
81
+        }
82
+        super.destroy();
83
+    }
84
+
85
+    private void blurActivityFocus() {
86
+        final Activity activity = getActivity();
87
+        final View focusView = activity != null ? activity.getCurrentFocus() : null;
88
+        if (focusView != null) {
89
+            focusView.clearFocus();
90
+        }
91
+    }
74 92
 }

+ 6
- 0
lib/src/interfaces/Options.ts View File

@@ -753,4 +753,10 @@ setRoot: {
753 753
    * #### (iOS specific)
754 754
    */
755 755
   rootBackgroundImage?: ImageRequireSource;
756
+  /**
757
+   * Enable or disable automatically blurring focused input, dismissing keyboard on unmount
758
+   * #### (Android specific)
759
+   * @default false
760
+   */
761
+  blurOnUnmount?: boolean;
756 762
 }