mirror of
https://github.com/status-im/react-native.git
synced 2025-02-25 23:55:23 +00:00
Support Input Accessory View (iOS Only) [1/N]
Reviewed By: mmmulani Differential Revision: D6886573 fbshipit-source-id: 71e1f812b1cc1698e4380211a6cedd59011b5495
This commit is contained in:
parent
c87d03a8b2
commit
38197c8230
114
Libraries/Components/TextInput/InputAccessoryView.js
Normal file
114
Libraries/Components/TextInput/InputAccessoryView.js
Normal file
@ -0,0 +1,114 @@
|
||||
/**
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @providesModule InputAccessoryView
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const ColorPropType = require('ColorPropType');
|
||||
const React = require('React');
|
||||
const StyleSheet = require('StyleSheet');
|
||||
const ViewPropTypes = require('ViewPropTypes');
|
||||
|
||||
const requireNativeComponent = require('requireNativeComponent');
|
||||
|
||||
const RCTInputAccessoryView = requireNativeComponent('RCTInputAccessoryView');
|
||||
|
||||
/**
|
||||
* Note: iOS only
|
||||
*
|
||||
* A component which enables customization of the keyboard input accessory view.
|
||||
* The input accessory view is displayed above the keyboard whenever a TextInput
|
||||
* has focus. This component can be used to create custom toolbars.
|
||||
*
|
||||
* To use this component wrap your custom toolbar with the
|
||||
* InputAccessoryView component, and set a nativeID. Then, pass that nativeID
|
||||
* as the inputAccessoryViewID of whatever TextInput you desire. A simple
|
||||
* example:
|
||||
*
|
||||
* ```ReactNativeWebPlayer
|
||||
* import React, { Component } from 'react';
|
||||
* import { AppRegistry, TextInput, InputAccessoryView, Button } from 'react-native';
|
||||
*
|
||||
* export default class UselessTextInput extends Component {
|
||||
* constructor(props) {
|
||||
* super(props);
|
||||
* this.state = {text: 'Placeholder Text'};
|
||||
* }
|
||||
*
|
||||
* render() {
|
||||
* const inputAccessoryViewID = "uniqueID";
|
||||
* return (
|
||||
* <View>
|
||||
* <ScrollView keyboardDismissMode="interactive">
|
||||
* <TextInput
|
||||
* style={{
|
||||
* padding: 10,
|
||||
* paddingTop: 50,
|
||||
* }}
|
||||
* inputAccessoryViewID=inputAccessoryViewID
|
||||
* onChangeText={text => this.setState({text})}
|
||||
* value={this.state.text}
|
||||
* />
|
||||
* </ScrollView>
|
||||
* <InputAccessoryView nativeID=inputAccessoryViewID>
|
||||
* <Button
|
||||
* onPress={() => this.setState({text: 'Placeholder Text'})}
|
||||
* title="Reset Text"
|
||||
* />
|
||||
* </InputAccessoryView>
|
||||
* </View>
|
||||
* );
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // skip this line if using Create React Native App
|
||||
* AppRegistry.registerComponent('AwesomeProject', () => UselessTextInput);
|
||||
* ```
|
||||
*
|
||||
* This component can also be used to create sticky text inputs (text inputs
|
||||
* which are anchored to the top of the keyboard). To do this, wrap a
|
||||
* TextInput with the InputAccessoryView component, and don't set a nativeID.
|
||||
* For an example, look at InputAccessoryViewExample.js in RNTester.
|
||||
*/
|
||||
|
||||
type Props = {
|
||||
+children: React.Node,
|
||||
/**
|
||||
* An ID which is used to associate this `InputAccessoryView` to
|
||||
* specified TextInput(s).
|
||||
*/
|
||||
nativeID?: string,
|
||||
style?: ViewPropTypes.style,
|
||||
backgroundColor?: ColorPropType,
|
||||
};
|
||||
|
||||
class InputAccessoryView extends React.Component<Props> {
|
||||
render(): React.Node {
|
||||
if (React.Children.count(this.props.children) === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<RCTInputAccessoryView
|
||||
style={[this.props.style, styles.container]}
|
||||
nativeID={this.props.nativeID}
|
||||
backgroundColor={this.props.backgroundColor}>
|
||||
{this.props.children}
|
||||
</RCTInputAccessoryView>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
position: 'absolute',
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = InputAccessoryView;
|
@ -590,6 +590,13 @@ const TextInput = createReactClass({
|
||||
* This property is supported only for single-line TextInput component on iOS.
|
||||
*/
|
||||
caretHidden: PropTypes.bool,
|
||||
/**
|
||||
* An optional identifier which links a custom InputAccessoryView to
|
||||
* this text input. The InputAccessoryView is rendered above the
|
||||
* keyboard when this text input is focused.
|
||||
* @platform ios
|
||||
*/
|
||||
inputAccessoryViewID: PropTypes.string,
|
||||
},
|
||||
getDefaultProps(): Object {
|
||||
return {
|
||||
|
@ -103,6 +103,9 @@
|
||||
5956B1A6200FF35C008D9D16 /* RCTUITextField.m in Sources */ = {isa = PBXBuildFile; fileRef = 5956B103200FEBA9008D9D16 /* RCTUITextField.m */; };
|
||||
5956B1A7200FF35C008D9D16 /* RCTVirtualTextShadowView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5956B12E200FEBAA008D9D16 /* RCTVirtualTextShadowView.m */; };
|
||||
5956B1A8200FF35C008D9D16 /* RCTVirtualTextViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5956B12B200FEBAA008D9D16 /* RCTVirtualTextViewManager.m */; };
|
||||
8F2807C7202D2B6B005D65E6 /* RCTInputAccessoryViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F2807C1202D2B6A005D65E6 /* RCTInputAccessoryViewManager.m */; };
|
||||
8F2807C8202D2B6B005D65E6 /* RCTInputAccessoryView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F2807C3202D2B6A005D65E6 /* RCTInputAccessoryView.m */; };
|
||||
8F2807C9202D2B6B005D65E6 /* RCTInputAccessoryViewContent.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F2807C5202D2B6B005D65E6 /* RCTInputAccessoryViewContent.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
@ -229,6 +232,12 @@
|
||||
5956B12D200FEBAA008D9D16 /* RCTVirtualTextViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTVirtualTextViewManager.h; sourceTree = "<group>"; };
|
||||
5956B12E200FEBAA008D9D16 /* RCTVirtualTextShadowView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTVirtualTextShadowView.m; sourceTree = "<group>"; };
|
||||
5956B12F200FEBAA008D9D16 /* RCTConvert+Text.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+Text.m"; sourceTree = "<group>"; };
|
||||
8F2807C1202D2B6A005D65E6 /* RCTInputAccessoryViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTInputAccessoryViewManager.m; sourceTree = "<group>"; };
|
||||
8F2807C2202D2B6A005D65E6 /* RCTInputAccessoryViewContent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTInputAccessoryViewContent.h; sourceTree = "<group>"; };
|
||||
8F2807C3202D2B6A005D65E6 /* RCTInputAccessoryView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTInputAccessoryView.m; sourceTree = "<group>"; };
|
||||
8F2807C4202D2B6A005D65E6 /* RCTInputAccessoryView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTInputAccessoryView.h; sourceTree = "<group>"; };
|
||||
8F2807C5202D2B6B005D65E6 /* RCTInputAccessoryViewContent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTInputAccessoryViewContent.m; sourceTree = "<group>"; };
|
||||
8F2807C6202D2B6B005D65E6 /* RCTInputAccessoryViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTInputAccessoryViewManager.h; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
@ -274,6 +283,12 @@
|
||||
5956B0FF200FEBA9008D9D16 /* TextInput */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8F2807C4202D2B6A005D65E6 /* RCTInputAccessoryView.h */,
|
||||
8F2807C3202D2B6A005D65E6 /* RCTInputAccessoryView.m */,
|
||||
8F2807C2202D2B6A005D65E6 /* RCTInputAccessoryViewContent.h */,
|
||||
8F2807C5202D2B6B005D65E6 /* RCTInputAccessoryViewContent.m */,
|
||||
8F2807C6202D2B6B005D65E6 /* RCTInputAccessoryViewManager.h */,
|
||||
8F2807C1202D2B6A005D65E6 /* RCTInputAccessoryViewManager.m */,
|
||||
5956B113200FEBA9008D9D16 /* Multiline */,
|
||||
5956B10C200FEBA9008D9D16 /* RCTBackedTextInputDelegate.h */,
|
||||
5956B107200FEBA9008D9D16 /* RCTBackedTextInputDelegateAdapter.h */,
|
||||
@ -465,8 +480,11 @@
|
||||
5956B140200FEBAA008D9D16 /* RCTTextShadowView.m in Sources */,
|
||||
5956B131200FEBAA008D9D16 /* RCTRawTextViewManager.m in Sources */,
|
||||
5956B137200FEBAA008D9D16 /* RCTBaseTextInputShadowView.m in Sources */,
|
||||
8F2807C7202D2B6B005D65E6 /* RCTInputAccessoryViewManager.m in Sources */,
|
||||
5956B146200FEBAA008D9D16 /* RCTConvert+Text.m in Sources */,
|
||||
8F2807C9202D2B6B005D65E6 /* RCTInputAccessoryViewContent.m in Sources */,
|
||||
5956B13F200FEBAA008D9D16 /* RCTTextAttributes.m in Sources */,
|
||||
8F2807C8202D2B6B005D65E6 /* RCTInputAccessoryView.m in Sources */,
|
||||
5956B143200FEBAA008D9D16 /* RCTTextView.m in Sources */,
|
||||
5956B13C200FEBAA008D9D16 /* RCTUITextView.m in Sources */,
|
||||
5956B136200FEBAA008D9D16 /* RCTBackedTextInputDelegateAdapter.m in Sources */,
|
||||
|
@ -46,6 +46,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property (nonatomic, copy) RCTTextSelection *selection;
|
||||
@property (nonatomic, strong, nullable) NSNumber *maxLength;
|
||||
@property (nonatomic, copy) NSAttributedString *attributedText;
|
||||
@property (nonatomic, copy) NSString *inputAccessoryViewID;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -15,6 +15,8 @@
|
||||
#import <React/RCTUtils.h>
|
||||
#import <React/UIView+React.h>
|
||||
|
||||
#import "RCTInputAccessoryView.h"
|
||||
#import "RCTInputAccessoryViewContent.h"
|
||||
#import "RCTTextAttributes.h"
|
||||
#import "RCTTextSelection.h"
|
||||
|
||||
@ -400,12 +402,33 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
|
||||
|
||||
- (void)didSetProps:(NSArray<NSString *> *)changedProps
|
||||
{
|
||||
[self invalidateInputAccessoryView];
|
||||
#if !TARGET_OS_TV
|
||||
if ([changedProps containsObject:@"inputAccessoryViewID"] && self.inputAccessoryViewID) {
|
||||
[self setCustomInputAccessoryViewWithNativeID:self.inputAccessoryViewID];
|
||||
} else if (!self.inputAccessoryViewID) {
|
||||
[self setDefaultInputAccessoryView];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)invalidateInputAccessoryView
|
||||
- (void)setCustomInputAccessoryViewWithNativeID:(NSString *)nativeID
|
||||
{
|
||||
__weak RCTBaseTextInputView *weakSelf = self;
|
||||
[_bridge.uiManager rootViewForReactTag:self.reactTag withCompletion:^(UIView *rootView) {
|
||||
RCTBaseTextInputView *strongSelf = weakSelf;
|
||||
if (rootView) {
|
||||
UIView *accessoryView = [strongSelf->_bridge.uiManager viewForNativeID:nativeID
|
||||
withRootTag:rootView.reactTag];
|
||||
if (accessoryView && [accessoryView isKindOfClass:[RCTInputAccessoryView class]]) {
|
||||
strongSelf.backedTextInputView.inputAccessoryView = ((RCTInputAccessoryView *)accessoryView).content.inputAccessoryView;
|
||||
[strongSelf reloadInputViewsIfNecessary];
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)setDefaultInputAccessoryView
|
||||
{
|
||||
#if !TARGET_OS_TV
|
||||
UIView<RCTBackedTextInputViewProtocol> *textInputView = self.backedTextInputView;
|
||||
UIKeyboardType keyboardType = textInputView.keyboardType;
|
||||
|
||||
@ -443,12 +466,15 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame)
|
||||
else {
|
||||
textInputView.inputAccessoryView = nil;
|
||||
}
|
||||
[self reloadInputViewsIfNecessary];
|
||||
}
|
||||
|
||||
- (void)reloadInputViewsIfNecessary
|
||||
{
|
||||
// We have to call `reloadInputViews` for focused text inputs to update an accessory view.
|
||||
if (textInputView.isFirstResponder) {
|
||||
[textInputView reloadInputViews];
|
||||
if (self.backedTextInputView.isFirstResponder) {
|
||||
[self.backedTextInputView reloadInputViews];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)handleInputAccessoryDoneButton
|
||||
|
@ -53,6 +53,7 @@ RCT_EXPORT_VIEW_PROPERTY(clearTextOnFocus, BOOL)
|
||||
RCT_EXPORT_VIEW_PROPERTY(maxLength, NSNumber)
|
||||
RCT_EXPORT_VIEW_PROPERTY(selectTextOnFocus, BOOL)
|
||||
RCT_EXPORT_VIEW_PROPERTY(selection, RCTTextSelection)
|
||||
RCT_EXPORT_VIEW_PROPERTY(inputAccessoryViewID, NSString)
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock)
|
||||
RCT_EXPORT_VIEW_PROPERTY(onSelectionChange, RCTDirectEventBlock)
|
||||
|
19
Libraries/Text/TextInput/RCTInputAccessoryView.h
Normal file
19
Libraries/Text/TextInput/RCTInputAccessoryView.h
Normal file
@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@class RCTBridge;
|
||||
@class RCTInputAccessoryViewContent;
|
||||
|
||||
@interface RCTInputAccessoryView : UIView
|
||||
|
||||
- (instancetype)initWithBridge:(RCTBridge *)bridge;
|
||||
|
||||
@property (nonatomic, readonly, strong) RCTInputAccessoryViewContent *content;
|
||||
|
||||
@end
|
69
Libraries/Text/TextInput/RCTInputAccessoryView.m
Normal file
69
Libraries/Text/TextInput/RCTInputAccessoryView.m
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTInputAccessoryView.h"
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTTouchHandler.h>
|
||||
#import <React/UIView+React.h>
|
||||
|
||||
#import "RCTInputAccessoryViewContent.h"
|
||||
|
||||
@implementation RCTInputAccessoryView
|
||||
{
|
||||
BOOL _contentShouldBeFirstResponder;
|
||||
}
|
||||
|
||||
- (instancetype)initWithBridge:(RCTBridge *)bridge
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_content = [RCTInputAccessoryViewContent new];
|
||||
RCTTouchHandler *const touchHandler = [[RCTTouchHandler alloc] initWithBridge:bridge];
|
||||
[touchHandler attachToView:_content.inputAccessoryView];
|
||||
[self addSubview:_content];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)reactSetFrame:(CGRect)frame
|
||||
{
|
||||
[_content.inputAccessoryView setFrame:frame];
|
||||
[_content.contentView setFrame:frame];
|
||||
|
||||
if (_contentShouldBeFirstResponder) {
|
||||
_contentShouldBeFirstResponder = NO;
|
||||
[_content becomeFirstResponder];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)index
|
||||
{
|
||||
[super insertReactSubview:subview atIndex:index];
|
||||
[_content insertReactSubview:subview atIndex:index];
|
||||
}
|
||||
|
||||
- (void)removeReactSubview:(UIView *)subview
|
||||
{
|
||||
[super removeReactSubview:subview];
|
||||
[_content removeReactSubview:subview];
|
||||
}
|
||||
|
||||
- (void)didUpdateReactSubviews
|
||||
{
|
||||
// Do nothing, as subviews are managed by `insertReactSubview:atIndex:`
|
||||
}
|
||||
|
||||
- (void)didSetProps:(NSArray<NSString *> *)changedProps
|
||||
{
|
||||
// If the accessory view is not linked to a text input via nativeID, assume it is
|
||||
// a standalone component that should get focus whenever it is rendered
|
||||
if (![changedProps containsObject:@"nativeID"] && !self.nativeID) {
|
||||
_contentShouldBeFirstResponder = YES;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
14
Libraries/Text/TextInput/RCTInputAccessoryViewContent.h
Normal file
14
Libraries/Text/TextInput/RCTInputAccessoryViewContent.h
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface RCTInputAccessoryViewContent : UIView
|
||||
|
||||
@property (nonatomic, readwrite, retain) UIView *contentView;
|
||||
|
||||
@end
|
75
Libraries/Text/TextInput/RCTInputAccessoryViewContent.m
Normal file
75
Libraries/Text/TextInput/RCTInputAccessoryViewContent.m
Normal file
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTInputAccessoryViewContent.h"
|
||||
|
||||
#import <React/UIView+React.h>
|
||||
|
||||
@interface RCTInputAccessoryViewContent()
|
||||
|
||||
// Overriding `inputAccessoryView` to `readwrite`.
|
||||
@property (nonatomic, readwrite, retain) UIView *inputAccessoryView;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTInputAccessoryViewContent
|
||||
|
||||
- (BOOL)canBecomeFirstResponder
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
- (BOOL)becomeFirstResponder
|
||||
{
|
||||
const BOOL becameFirstResponder = [super becomeFirstResponder];
|
||||
|
||||
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
|
||||
// Avoiding the home pill and notch (landscape mode) on iphoneX.
|
||||
if (becameFirstResponder) {
|
||||
if (@available(iOS 11.0, *)) {
|
||||
[_contentView.bottomAnchor
|
||||
constraintLessThanOrEqualToSystemSpacingBelowAnchor:_contentView.window.safeAreaLayoutGuide.bottomAnchor
|
||||
multiplier:1.0f].active = YES;
|
||||
[_contentView.leftAnchor
|
||||
constraintLessThanOrEqualToSystemSpacingAfterAnchor:_contentView.window.safeAreaLayoutGuide.leftAnchor
|
||||
multiplier:1.0f].active = YES;
|
||||
[_contentView.rightAnchor
|
||||
constraintLessThanOrEqualToSystemSpacingAfterAnchor:_contentView.window.safeAreaLayoutGuide.rightAnchor
|
||||
multiplier:1.0f].active = YES;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return becameFirstResponder;
|
||||
}
|
||||
|
||||
- (UIView *)inputAccessoryView
|
||||
{
|
||||
if (!_inputAccessoryView) {
|
||||
_inputAccessoryView = [UIView new];
|
||||
_contentView = [UIView new];
|
||||
[_inputAccessoryView addSubview:_contentView];
|
||||
}
|
||||
return _inputAccessoryView;
|
||||
}
|
||||
|
||||
- (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)index
|
||||
{
|
||||
[super insertReactSubview:subview atIndex:index];
|
||||
[_contentView insertSubview:subview atIndex:index];
|
||||
}
|
||||
|
||||
- (void)removeReactSubview:(UIView *)subview
|
||||
{
|
||||
[super removeReactSubview:subview];
|
||||
[subview removeFromSuperview];
|
||||
if ([[_inputAccessoryView subviews] count] == 0 && [self isFirstResponder]) {
|
||||
[self resignFirstResponder];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
12
Libraries/Text/TextInput/RCTInputAccessoryViewManager.h
Normal file
12
Libraries/Text/TextInput/RCTInputAccessoryViewManager.h
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTViewManager.h>
|
||||
|
||||
@interface RCTInputAccessoryViewManager : RCTViewManager
|
||||
|
||||
@end
|
28
Libraries/Text/TextInput/RCTInputAccessoryViewManager.m
Normal file
28
Libraries/Text/TextInput/RCTInputAccessoryViewManager.m
Normal file
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTInputAccessoryViewManager.h"
|
||||
|
||||
#import "RCTInputAccessoryView.h"
|
||||
|
||||
@implementation RCTInputAccessoryViewManager
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (UIView *)view
|
||||
{
|
||||
return [[RCTInputAccessoryView alloc] initWithBridge:self.bridge];
|
||||
}
|
||||
|
||||
RCT_REMAP_VIEW_PROPERTY(backgroundColor, content.inputAccessoryView.backgroundColor, UIColor)
|
||||
|
||||
@end
|
@ -9,6 +9,8 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const Button = require('Button');
|
||||
const InputAccessoryView = require('InputAccessoryView');
|
||||
var React = require('react');
|
||||
var ReactNative = require('react-native');
|
||||
var {
|
||||
@ -91,6 +93,35 @@ class TextEventsExample extends React.Component<{}, $FlowFixMeState> {
|
||||
}
|
||||
}
|
||||
|
||||
class TextInputAccessoryViewExample extends React.Component<{}, *> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {text: 'Placeholder Text'};
|
||||
}
|
||||
|
||||
render() {
|
||||
const inputAccessoryViewID = 'inputAccessoryView1';
|
||||
return (
|
||||
<View>
|
||||
<TextInput
|
||||
style={styles.default}
|
||||
inputAccessoryViewID={inputAccessoryViewID}
|
||||
onChangeText={text => this.setState({text})}
|
||||
value={this.state.text}
|
||||
/>
|
||||
<InputAccessoryView nativeID={inputAccessoryViewID}>
|
||||
<View style={{backgroundColor: 'white'}}>
|
||||
<Button
|
||||
onPress={() => this.setState({text: 'Placeholder Text'})}
|
||||
title="Reset Text"
|
||||
/>
|
||||
</View>
|
||||
</InputAccessoryView>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RewriteExample extends React.Component<$FlowFixMeProps, any> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -485,6 +516,12 @@ exports.examples = [
|
||||
return <RewriteExampleInvalidCharacters />;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Keyboard Accessory View',
|
||||
render: function() {
|
||||
return <TextInputAccessoryViewExample />;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Auto-capitalize',
|
||||
render: function() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user