React-Native에서 키보드 폐쇄 문제를 해결하는 방법은 무엇입니까?

零下一度
풀어 주다: 2017-07-16 15:26:30
원래의
1548명이 탐색했습니다.

개발 중에 입력이 필요한 부분을 자주 접하게 되는데, RN이 언급한 TextInput은 사용하기 쉽지만, 아쉽게도 폐색 문제를 다루지 않습니다.

자판이 튀어나와서 편집창을 가리는 경우가 많아 머리가 아프네요.

저는 원래 js.coach 라이브러리에서 타사 플러그인을 찾고 싶었는데, 제가 본 것 중 가장 좋은 것은 React-native-keyboard-spacer였습니다. 하지만 아직 한 가지가 빠졌습니다. 키보드의 높이.

이것도 오랫동안 확인했는데 제공되지 않았습니다. 그래서 키보드 높이를 구하려면 네이티브 모듈을 직접 작성해야 했습니다.

네이티브 iOS에서 키보드 높이를 구하는 것에 대해서는 많이 말하지 않겠습니다. 인터넷에 많은 것들이 있습니다. 저는 RN을 기반으로 작성한 코드와 네이티브 모듈을 직접 붙여넣습니다.

// 
// KeyboardHeight.h 
// Jicheng6 
// 
// Created by guojicheng on 16/11/7. 
// Copyright © 2016年 Facebook. All rights reserved. 
// 
 
#import <UIKit/UIKit.h> 
#import "RCTEventEmitter.h" 
#import "RCTBridgeModule.h" 
 
@interface KeyboardHeight : RCTEventEmitter<RCTBridgeModule> 
 
-(void)heightChanged:(int)height; 
 
@property (nonatomic, assign)int kbHeight; 
 
@end
로그인 후 복사
// 
// KeyboardHeight.m 
// Jicheng6 
// 
// Created by guojicheng on 16/11/7. 
// Copyright © 2016年 Facebook. All rights reserved. 
// 
 
#import "KeyboardHeight.h" 
 
@implementation KeyboardHeight 
 
RCT_EXPORT_MODULE(); 
 
- (instancetype)init 
{ 
 self = [super init]; 
 if (self) { 
  self.kbHeight = 0; 
  [[NSNotificationCenter defaultCenter] addObserver:self 
                       selector:@selector(keyboardDidShow:) 
                         name:UIKeyboardDidShowNotification 
                        object:nil]; 
 } 
 return self; 
} 
 
-(void)keyboardDidShow:(NSNotification*) aNotification 
{ 
 //获取键盘的高度 
 NSDictionary *userInfo = [aNotification userInfo]; 
 NSValue *aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey]; 
 CGRect keyboardRect = [aValue CGRectValue]; 
 if (_kbHeight != keyboardRect.size.height){ 
  _kbHeight = keyboardRect.size.height; 
  [self heightChanged:_kbHeight]; 
 } 
} 
 
RCT_REMAP_METHOD(getKBHeight, 
         resolver:(RCTPromiseResolveBlock)resolve 
         rejecter:(RCTPromiseRejectBlock)reject) 
{ 
 resolve([[NSNumber alloc]initWithInt:_kbHeight]); 
} 
 
- (NSArray<NSString *> *)supportedEvents 
{ 
 return @[@"heightChanged"]; 
} 
 
-(void)heightChanged:(int)height 
{ 
 [self sendEventWithName:@"heightChanged" body:[NSNumber numberWithUnsignedInt:height]]; 
} 
 
@end
로그인 후 복사

사실 내 이전 블로그에도 하나 있는데 처음에는 RCT_REMAP_METHOD를 통해서 높이를 구할까 생각했는데, 아쉽게도 키보드가 처음 뜰 때, 뜬 후에도 높이가 0이 안 나와서 a를 추가했습니다. 리스닝 함수 heightChanged. 기록된 값과 변경된 값이 일치하지 않는 경우 리스닝 함수를 호출하여 해당 값을 JS 측에 전달합니다. 이러한 방식으로 JS 측은 변경 사항을 감지한 후 해당 변경을 수행할 수 있습니다.

네, 네이티브 모듈이 캡슐화되었습니다. 다음으로 js 측면을 살펴보겠습니다. 이것은 이전 블로그에서 언급한 내용이기도 합니다.


import React, { Component } from &#39;react&#39;; 
import { 
  AppRegistry, 
  StyleSheet, 
  Text, 
  View, 
  TouchableOpacity, 
  Alert, 
  TextInput, 
  PixelRatio, 
  Linking, 
  Keyboard, 
  NativeEventEmitter, 
} from &#39;react-native&#39;; 
 
var Dimensions = require(&#39;Dimensions&#39;); 
var ScreenWidth = Dimensions.get(&#39;window&#39;).width; 
var ScreenHeight = Dimensions.get(&#39;window&#39;).height; 
 
var kbHeight = require(&#39;NativeModules&#39;).KeyboardHeight; 
const kbHeightEvt = new NativeEventEmitter(kbHeight);
로그인 후 복사


componentWillMount() { 
    this.heightChanged = kbHeightEvt.addListener(&#39;heightChanged&#39;, this._heightChanged.bind(this)); 
  } 
  componentDidMount() { 
 
  } 
  componentWillUnmount() { 
    this.heightChanged.remove(); 
  } 
  _heightChanged(data){ 
    // console.log(data); 
    this.keyboardHeight = data; 
    this.changeMarginTop();//这里我是处理高度的 
  }
로그인 후 복사

높이에 도달했습니다. 다음 단계는 더 쉽습니다. 즉 덧셈과 뺄셈의 문제입니다.

화면에서 입력 상자의 위치를 ​​가져온 다음 이를 키보드 높이와 비교해야 합니다. onLayout을 통해 입력 상자의 위치를 ​​가져옵니다.


onLayoutParent(event){ 
    if (this.orgLayoutParent == null){//获取的父组件的位置,因为要用到计算 
      this.orgLayoutParent = event.nativeEvent.layout; 
    } 
    console.log(&#39;parent layout: &#39;, event.nativeEvent.layout); 
  } 
  onLayoutMail(event){//获取输入框的位置,这个位置是相对父组件的位置,所以上面需要获得父组件的 
    this.layoutMail = event.nativeEvent.layout; 
  } 
  onFocusMail(event){ 
    this.focusName = &#39;mail&#39;;//定义一个标识,可以区分不同输入框 
    this.changeMarginTop();//统一处理高度的函数 
  } 
  onSubmitMail(){ 
    drawLayout.setKBMoveY(0);//当输入完毕时,重置回原来的状态 
  } 
  changeMarginTop(){//计算移动的距离 
    var layout = null; 
    if (this.focusName == &#39;mail&#39;){ 
      layout = this.layoutMail; 
    } 
    if (layout && this.orgLayoutParent.y + layout.y + layout.height > ScreenHeight - this.keyboardHeight){ 
      drawLayout.setKBMoveY(-(this.orgLayoutParent.y + layout.y + layout.height - ScreenHeight + this.keyboardHeight)); 
    }else{//不对的置零处理 
      drawLayout.setKBMoveY(0); 
    } 
  } 
  render() { 
    return ( 
      <View style={[styles.container, this.props.style ? this.props.style : {}]} onLayout={this.onLayoutParent.bind(this)}> 
        <View style={[styles.viewStyle, {marginTop: 10}]} onLayout={this.onLayoutMail.bind(this)}>//这里获取的是相对位置哦 
          <TextInput style={styles.textInputStyle} 
            onChangeText={this.onTextChange.bind(this)} 
            value={this.state.emailPath} 
            placeholder={&#39;请输入邮箱&#39;} 
            onFocus={this.onFocusMail.bind(this)}//当获取到焦点时触发 
            onSubmitEditing={this.onSubmitMail.bind(this)}/>//点击回车时的调用,这里可以根据需求去做 
          <TouchableOpacity onPress={this.onSubmitSend.bind(this)}> 
            <View style={[styles.sendButtonView, {}]}> 
              <Text style={styles.sendButtonText}> 
                发送 
              </Text> 
            </View> 
          </TouchableOpacity> 
        </View> 
      </View> 
    ); 
  }
로그인 후 복사

현재 구성 요소와 페이지가 필요하지 않습니다. 제가 그랬듯이 할아버지 구성 요소를 기록하기 위해 전역을 추가했습니다(주로 전체 페이지를 위로 이동하기 위해). 다음 단계는
animation

을 추가하는 것입니다. drawLayout을 선택한 다음 너무 갑작스럽게 이동하지 마세요.

import React, { Component } from &#39;react&#39;; 
import { 
 StyleSheet, 
 Text, 
 View, 
 TouchableOpacity, 
 Animated, 
} from &#39;react-native&#39;; 
 
import SendEmail from &#39;./SendEmail&#39;; 
 
export default class DrawLayout extends Component { 
 constructor(props){ 
  super(props); 
  this.state={ 
   kbShowY: new Animated.Value(0),//设置动画的初始值 
  }; 
  global.drawLayout = this;//这里将自己保存到global里面,方便它的子组件调用 
 } 
 setKBMoveY(y){ 
  Animated.timing(//这里用的是timing均匀变化,具体的参数,可以参考RN的文档,写的很详细了,这里就不啰嗦了。 
   this.state.kbShowY,{ 
    toValue: y,//变化到目的位置 
    delay: 250,//延时250毫秒 
   }, 
  ).start();//开始 
 } 
 componentWillUnmount() { 
  global.drawLayout = null;//降这个值赋值为空 
 } 
  
 render() { 
  return ( 
   <Animated.View style={[styles.container, {marginTop: this.state.kbShowY}]} >//使用Animated.View 
    <SendEmail style={{marginTop: 10}}/> 
   </Animated.View> 
  ); 
 } 
}
로그인 후 복사

그렇습니다. 그런 다음 스크린샷을 찍어서 애니메이션이 있지만 역동적인 사진을 만들 수 없습니다

위 내용은 React-Native에서 키보드 폐쇄 문제를 해결하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿