Files
react-native/React/Fabric/Mounting/ComponentViews/InputAccessory/RCTInputAccessoryComponentView.mm
T
Samuel Susla 258387ddaa Use window size instead of screen size in InputAccessoryView
Summary:
Changelog: [internal]

Use window size instead of screen size to layout InputAccessoryView.

Reviewed By: PeteTheHeat

Differential Revision: D23297141

fbshipit-source-id: d6d7223342d17a2e1b9e5fca6f999b7ad365d056
2020-08-25 06:50:34 -07:00

154 lines
4.5 KiB
Plaintext

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "RCTInputAccessoryComponentView.h"
#import <React/RCTBackedTextInputViewProtocol.h>
#import <React/RCTConversions.h>
#import <React/RCTSurfaceTouchHandler.h>
#import <React/RCTUtils.h>
#import <React/UIView+React.h>
#import <react/renderer/components/inputaccessory/InputAccessoryComponentDescriptor.h>
#import <react/renderer/components/rncore/Props.h>
#import "RCTInputAccessoryContentView.h"
#import "RCTFabricComponentsPlugins.h"
using namespace facebook::react;
static UIView<RCTBackedTextInputViewProtocol> *_Nullable RCTFindTextInputWithNativeId(UIView *view, NSString *nativeId)
{
if ([view respondsToSelector:@selector(inputAccessoryViewID)] &&
[view respondsToSelector:@selector(setInputAccessoryView:)]) {
UIView<RCTBackedTextInputViewProtocol> *typed = (UIView<RCTBackedTextInputViewProtocol> *)view;
if (!nativeId || [typed.inputAccessoryViewID isEqualToString:nativeId]) {
return typed;
}
}
for (UIView *subview in view.subviews) {
UIView<RCTBackedTextInputViewProtocol> *result = RCTFindTextInputWithNativeId(subview, nativeId);
if (result) {
return result;
}
}
return nil;
}
@implementation RCTInputAccessoryComponentView {
InputAccessoryShadowNode::ConcreteStateTeller _stateTeller;
RCTInputAccessoryContentView *_contentView;
RCTSurfaceTouchHandler *_touchHandler;
UIView<RCTBackedTextInputViewProtocol> __weak *_textInput;
}
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const InputAccessoryProps>();
_props = defaultProps;
_contentView = [RCTInputAccessoryContentView new];
_touchHandler = [RCTSurfaceTouchHandler new];
[_touchHandler attachToView:_contentView];
}
return self;
}
- (void)didMoveToWindow
{
[super didMoveToWindow];
if (self.window && !_textInput) {
if (self.nativeId) {
_textInput = RCTFindTextInputWithNativeId(self.window, self.nativeId);
_textInput.inputAccessoryView = _contentView;
} else {
_textInput = RCTFindTextInputWithNativeId(_contentView, nil);
}
if (!self.nativeId) {
[self becomeFirstResponder];
}
}
}
- (BOOL)canBecomeFirstResponder
{
return true;
}
- (UIView *)inputAccessoryView
{
return _contentView;
}
#pragma mark - RCTComponentViewProtocol
+ (ComponentDescriptorProvider)componentDescriptorProvider
{
return concreteComponentDescriptorProvider<InputAccessoryComponentDescriptor>();
}
- (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
{
[_contentView insertSubview:childComponentView atIndex:index];
}
- (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
{
[childComponentView removeFromSuperview];
}
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
{
auto const &oldInputAccessoryProps = *std::static_pointer_cast<InputAccessoryProps const>(_props);
auto const &newInputAccessoryProps = *std::static_pointer_cast<InputAccessoryProps const>(props);
if (newInputAccessoryProps.backgroundColor != oldInputAccessoryProps.backgroundColor) {
_contentView.backgroundColor = RCTUIColorFromSharedColor(newInputAccessoryProps.backgroundColor);
}
[super updateProps:props oldProps:oldProps];
self.hidden = true;
}
- (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState
{
_stateTeller.setConcreteState(state);
CGSize oldViewportSize = RCTCGSizeFromSize(_stateTeller.getData().value().viewportSize);
CGSize viewportSize = RCTViewportSize();
viewportSize.height = std::nan("");
if (oldViewportSize.width != viewportSize.width) {
auto stateData = InputAccessoryState{RCTSizeFromCGSize(viewportSize)};
_stateTeller.updateState(std::move(stateData));
}
}
- (void)updateLayoutMetrics:(LayoutMetrics const &)layoutMetrics
oldLayoutMetrics:(LayoutMetrics const &)oldLayoutMetrics
{
[super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:oldLayoutMetrics];
[_contentView setFrame:RCTCGRectFromRect(layoutMetrics.getContentFrame())];
}
- (void)prepareForRecycle
{
[super prepareForRecycle];
_stateTeller.invalidate();
_textInput = nil;
}
@end
Class<RCTComponentViewProtocol> RCTInputAccessoryCls(void)
{
return RCTInputAccessoryComponentView.class;
}