Skip to content

Commit

Permalink
Keyboard (#3541)
Browse files Browse the repository at this point in the history
* Support Keyboard events
  • Loading branch information
ddalp authored Oct 29, 2019
1 parent ae3593f commit af904af
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 1 deletion.
9 changes: 9 additions & 0 deletions change/react-native-windows-2019-10-28-10-44-55-keyboard.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"type": "prerelease",
"comment": "Support Keyboard events",
"packageName": "react-native-windows",
"email": "[email protected]",
"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"
}
39 changes: 38 additions & 1 deletion packages/playground/Samples/textinput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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: '',
Expand Down Expand Up @@ -82,6 +110,15 @@ export default class Bootstrap extends React.Component<{}, any> {
}
onPress={this.onPressShowPassword}
/>
<KeyboardAvoidingView
style={styles.container}
behavior="padding"
enabled>
<TextInput
style={styles.input}
placeholder={'KeyboardAvoidingView padding'}
/>
</KeyboardAvoidingView>
</View>
);
}
Expand Down
2 changes: 2 additions & 0 deletions vnext/ReactUWP/ReactUWP.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@
<ClInclude Include="Views\RootViewManager.h" />
<ClInclude Include="Views\ScrollContentViewManager.h" />
<ClInclude Include="Views\ScrollViewManager.h" />
<ClInclude Include="Views\SIPEventHandler.h" />
<ClInclude Include="Views\SwitchViewManager.h" />
<ClInclude Include="Views\SliderViewManager.h" />
<ClInclude Include="Views\TextInputViewManager.h" />
Expand Down Expand Up @@ -353,6 +354,7 @@
<ClCompile Include="Views\RootViewManager.cpp" />
<ClCompile Include="Views\ScrollContentViewManager.cpp" />
<ClCompile Include="Views\ScrollViewManager.cpp" />
<ClCompile Include="Views\SIPEventHandler.cpp" />
<ClCompile Include="Views\SliderViewManager.cpp" />
<ClCompile Include="Views\ShadowNodeBase.cpp" />
<ClCompile Include="Views\SwitchViewManager.cpp" />
Expand Down
5 changes: 5 additions & 0 deletions vnext/ReactUWP/Views/ReactControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ void ReactControl::AttachRoot() noexcept {
if (!m_touchEventHandler)
m_touchEventHandler = std::make_shared<TouchEventHandler>(m_reactInstance);

if (!m_SIPEventHandler)
m_SIPEventHandler = std::make_shared<SIPEventHandler>(m_reactInstance);

m_previewKeyboardEventHandlerOnRoot = std::make_shared<PreviewKeyboardEventHandlerOnRoot>(m_reactInstance);

// Register callback from instance for errors
Expand Down Expand Up @@ -268,6 +271,8 @@ void ReactControl::DetachInstance() {

// Clear members with a dependency on the reactInstance
m_touchEventHandler.reset();

m_SIPEventHandler.reset();
}
}

Expand Down
2 changes: 2 additions & 0 deletions vnext/ReactUWP/Views/ReactControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <IReactInstance.h>
#include <winrt/Windows.UI.Xaml.Controls.h>
#include "IXamlRootView.h"
#include "SIPEventHandler.h"
#include "TouchEventHandler.h"
#include "Views/KeyboardEventHandler.h"

Expand Down Expand Up @@ -75,6 +76,7 @@ class ReactControl : public std::enable_shared_from_this<ReactControl>, public I
std::shared_ptr<facebook::react::NativeModuleProvider> m_moduleProvider;
folly::dynamic m_initialProps;
std::shared_ptr<TouchEventHandler> m_touchEventHandler;
std::shared_ptr<SIPEventHandler> m_SIPEventHandler;
std::shared_ptr<PreviewKeyboardEventHandlerOnRoot> m_previewKeyboardEventHandlerOnRoot;

int64_t m_rootTag = -1;
Expand Down
64 changes: 64 additions & 0 deletions vnext/ReactUWP/Views/SIPEventHandler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include <pch.h>

#include "SIPEventHandler.h"

#include <Modules/NativeUIManager.h>

#include <winrt/Windows.ApplicationModel.Core.h>
#include <winrt/Windows.Foundation.h>

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<IReactInstance> &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<winrt::CoreInputViewOcclusion> 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 &&parameters) {
if (auto instance = m_wkReactInstance.lock()) {
instance->CallJsFunction(
"RCTDeviceEventEmitter", "emit", folly::dynamic::array(std::move(eventName), std::move(parameters)));
}
}
} // namespace uwp
} // namespace react
30 changes: 30 additions & 0 deletions vnext/ReactUWP/Views/SIPEventHandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#pragma once
#include <folly/dynamic.h>

#include <IReactInstance.h>
#include <winrt/Windows.UI.ViewManagement.Core.h>

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<IReactInstance> &reactInstance);
virtual ~SIPEventHandler();

private:
void SendEvent(std::string &&eventName, folly::dynamic &&parameters);
std::weak_ptr<IReactInstance> m_wkReactInstance;
winrt::CoreInputView::OcclusionsChanged_revoker m_occlusionsChanged_revoker;
};

} // namespace uwp
} // namespace react

0 comments on commit af904af

Please sign in to comment.