diff --git a/change/react-native-windows-2019-10-28-10-44-55-keyboard.json b/change/react-native-windows-2019-10-28-10-44-55-keyboard.json
new file mode 100644
index 00000000000..1e22476be3b
--- /dev/null
+++ b/change/react-native-windows-2019-10-28-10-44-55-keyboard.json
@@ -0,0 +1,9 @@
+{
+ "type": "prerelease",
+ "comment": "Support Keyboard events",
+ "packageName": "react-native-windows",
+ "email": "dida@ntdev.microsoft.com",
+ "commit": "45a2fb84e8cbe53ad7ea190efab3919124ffb90b",
+ "date": "2019-10-28T17:44:55.590Z",
+ "file": "D:\\react2\\react-native-windows\\change\\react-native-windows-2019-10-28-10-44-55-keyboard.json"
+}
\ No newline at end of file
diff --git a/packages/playground/Samples/textinput.tsx b/packages/playground/Samples/textinput.tsx
index 595cd757a39..53ac5cb107a 100644
--- a/packages/playground/Samples/textinput.tsx
+++ b/packages/playground/Samples/textinput.tsx
@@ -5,9 +5,37 @@
*/
import * as React from 'react';
-import {AppRegistry, Button, StyleSheet, TextInput, View} from 'react-native';
+import {
+ AppRegistry,
+ Button,
+ StyleSheet,
+ TextInput,
+ Keyboard,
+ View,
+ KeyboardAvoidingView,
+} from 'react-native';
export default class Bootstrap extends React.Component<{}, any> {
+ componentDidMount() {
+ Keyboard.addListener('keyboardDidShow', this.keyboardDidShow);
+
+ Keyboard.addListener('keyboardDidHide', this.keyboardDidHide);
+ }
+
+ keyboardDidShow = () => {
+ console.log('keyboardDidShow');
+ };
+
+ keyboardDidHide = () => {
+ console.log('keyboardDidHide');
+ };
+
+ componentWillUnmount() {
+ Keyboard.removeListener('keyboardDidShow', this.keyboardDidShow);
+
+ Keyboard.removeListener('keyboardDidHide', this.keyboardDidHide);
+ }
+
state = {
passwordHidden: true,
text: '',
@@ -82,6 +110,15 @@ export default class Bootstrap extends React.Component<{}, any> {
}
onPress={this.onPressShowPassword}
/>
+
+
+
);
}
diff --git a/vnext/ReactUWP/ReactUWP.vcxproj b/vnext/ReactUWP/ReactUWP.vcxproj
index 5bfbd4d2a76..43b2c9bba20 100644
--- a/vnext/ReactUWP/ReactUWP.vcxproj
+++ b/vnext/ReactUWP/ReactUWP.vcxproj
@@ -252,6 +252,7 @@
+
@@ -353,6 +354,7 @@
+
diff --git a/vnext/ReactUWP/Views/ReactControl.cpp b/vnext/ReactUWP/Views/ReactControl.cpp
index fd979a9c61d..74ef6ce672d 100644
--- a/vnext/ReactUWP/Views/ReactControl.cpp
+++ b/vnext/ReactUWP/Views/ReactControl.cpp
@@ -172,6 +172,9 @@ void ReactControl::AttachRoot() noexcept {
if (!m_touchEventHandler)
m_touchEventHandler = std::make_shared(m_reactInstance);
+ if (!m_SIPEventHandler)
+ m_SIPEventHandler = std::make_shared(m_reactInstance);
+
m_previewKeyboardEventHandlerOnRoot = std::make_shared(m_reactInstance);
// Register callback from instance for errors
@@ -268,6 +271,8 @@ void ReactControl::DetachInstance() {
// Clear members with a dependency on the reactInstance
m_touchEventHandler.reset();
+
+ m_SIPEventHandler.reset();
}
}
diff --git a/vnext/ReactUWP/Views/ReactControl.h b/vnext/ReactUWP/Views/ReactControl.h
index 03db192607e..e6bd45f17e9 100644
--- a/vnext/ReactUWP/Views/ReactControl.h
+++ b/vnext/ReactUWP/Views/ReactControl.h
@@ -9,6 +9,7 @@
#include
#include
#include "IXamlRootView.h"
+#include "SIPEventHandler.h"
#include "TouchEventHandler.h"
#include "Views/KeyboardEventHandler.h"
@@ -75,6 +76,7 @@ class ReactControl : public std::enable_shared_from_this, public I
std::shared_ptr m_moduleProvider;
folly::dynamic m_initialProps;
std::shared_ptr m_touchEventHandler;
+ std::shared_ptr m_SIPEventHandler;
std::shared_ptr m_previewKeyboardEventHandlerOnRoot;
int64_t m_rootTag = -1;
diff --git a/vnext/ReactUWP/Views/SIPEventHandler.cpp b/vnext/ReactUWP/Views/SIPEventHandler.cpp
new file mode 100644
index 00000000000..f3c7ec7c4b3
--- /dev/null
+++ b/vnext/ReactUWP/Views/SIPEventHandler.cpp
@@ -0,0 +1,64 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#include
+
+#include "SIPEventHandler.h"
+
+#include
+
+#include
+#include
+
+namespace winrt {
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Collections;
+using namespace Windows::UI::ViewManagement::Core;
+using namespace Windows::UI::Xaml;
+} // namespace winrt
+namespace react {
+namespace uwp {
+
+SIPEventHandler::SIPEventHandler(const std::weak_ptr &reactInstance)
+ : m_wkReactInstance(reactInstance) {
+ auto coreInputView = winrt::CoreInputView::GetForCurrentView();
+ if (coreInputView) {
+ m_occlusionsChanged_revoker = coreInputView.OcclusionsChanged(
+ winrt::auto_revoke, [=](auto &&, const winrt::CoreInputViewOcclusionsChangedEventArgs &e) {
+ if (!e.Handled()) {
+ winrt::Rect finalRect = winrt::RectHelper::Empty();
+ winrt::IVectorView occlusions = e.Occlusions();
+ for (uint32_t i = 0; i < occlusions.Size(); i++) {
+ winrt::CoreInputViewOcclusion occlusion = occlusions.GetAt(i);
+ if (occlusion.OcclusionKind() == winrt::CoreInputViewOcclusionKind::Docked) {
+ finalRect = winrt::RectHelper::Union(finalRect, occlusion.OccludingRect());
+ }
+ }
+
+ if (winrt::RectHelper::GetIsEmpty(finalRect)) {
+ folly::dynamic params = folly::dynamic::object("screenY", 0)("screenX", 0)("width", 0)("height", 0);
+ SendEvent("keyboardDidHide", std::move(params));
+ } else {
+ folly::dynamic params = folly::dynamic::object(
+ "endCoordinates",
+ folly::dynamic::object("screenY", finalRect.Y)("screenX", finalRect.X)("width", finalRect.Width)(
+ "height", finalRect.Height));
+ SendEvent("keyboardDidShow", std::move(params));
+ }
+ }
+ });
+ }
+}
+
+SIPEventHandler::~SIPEventHandler() {
+ m_occlusionsChanged_revoker = {};
+}
+
+void SIPEventHandler::SendEvent(std::string &&eventName, folly::dynamic &¶meters) {
+ if (auto instance = m_wkReactInstance.lock()) {
+ instance->CallJsFunction(
+ "RCTDeviceEventEmitter", "emit", folly::dynamic::array(std::move(eventName), std::move(parameters)));
+ }
+}
+} // namespace uwp
+} // namespace react
diff --git a/vnext/ReactUWP/Views/SIPEventHandler.h b/vnext/ReactUWP/Views/SIPEventHandler.h
new file mode 100644
index 00000000000..142bd258f55
--- /dev/null
+++ b/vnext/ReactUWP/Views/SIPEventHandler.h
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#pragma once
+#include
+
+#include
+#include
+
+namespace winrt {
+using namespace Windows::Foundation;
+using namespace Windows::UI::ViewManagement::Core;
+} // namespace winrt
+
+namespace react {
+namespace uwp {
+
+class SIPEventHandler {
+ public:
+ SIPEventHandler(const std::weak_ptr &reactInstance);
+ virtual ~SIPEventHandler();
+
+ private:
+ void SendEvent(std::string &&eventName, folly::dynamic &¶meters);
+ std::weak_ptr m_wkReactInstance;
+ winrt::CoreInputView::OcclusionsChanged_revoker m_occlusionsChanged_revoker;
+};
+
+} // namespace uwp
+} // namespace react