Programing

네이티브 반응 :“다음”키보드 버튼을 누른 후 다음 TextInput을 선택하는 방법?

lottogame 2020. 6. 14. 10:25
반응형

네이티브 반응 :“다음”키보드 버튼을 누른 후 다음 TextInput을 선택하는 방법?


두 개의 TextInput 필드를 다음과 같이 정의했습니다.

<TextInput 
   style = {styles.titleInput}
   returnKeyType = {"next"}
   autoFocus = {true}
   placeholder = "Title" />
<TextInput
   style = {styles.descriptionInput}          
   multiline = {true}
   maxLength = {200}
   placeholder = "Description" />

그러나 키보드에서 "다음"버튼을 누른 후 반응 네이티브 앱이 두 번째 TextInput 필드로 이동하지 않습니다. 어떻게하면 되나요?

감사!


두 번째 설정 TextInput이전이 초점 TextInputonSubmitEditing트리거됩니다.

이 시도

  1. 두 번째 TextInput에 Ref 추가
    ref={(input) => { this.secondTextInput = input; }}

  2. 첫 번째 TextInput 의 onSubmitEditing 이벤트에 포커스 기능을 바인딩 합니다.
    onSubmitEditing={() => { this.secondTextInput.focus(); }}

  3. 키보드 깜박임을 방지하려면 blurOnSubmit을 false로 설정해야합니다.
    blurOnSubmit={false}

모든 것이 끝나면 다음과 같이 보일 것입니다.

<TextInput
    placeholder = "FirstTextInput"
    returnKeyType = { "next" }
    onSubmitEditing={() => { this.secondTextInput.focus(); }}
    blurOnSubmit={false}
/>

<TextInput
    ref={(input) => { this.secondTextInput = input; }}
    placeholder = "secondTextInput"
/>

refs를 사용하지 않고도이 작업을 수행 할 수 있습니다 . 참조는 깨지기 쉬운 코드로 이어질 수 있으므로이 방법이 선호 됩니다. 문서의 반작용 가능한 다른 솔루션을 찾아 조언을 :

React로 여러 앱을 프로그래밍하지 않은 경우 일반적으로 첫 번째 성향은 앱에서 "일이 발생하도록"참조를 사용하는 것입니다. 이 경우 잠시 시간을내어 구성 요소 계층에서 상태를 소유해야하는 위치에 대해보다 비판적으로 생각하십시오. 종종 해당 상태를 "소유"하는 적절한 장소가 계층 구조에서 더 높은 수준에 있다는 것이 분명해집니다. 상태를 설정하면 "일을 발생시키기"위해 심판을 사용하려는 욕구가 종종 제거됩니다. 대신 데이터 흐름이 일반적으로 목표를 달성합니다.

대신 상태 변수를 사용하여 두 번째 입력 필드에 초점을 맞 춥니 다.

  1. 소품으로 전달할 상태 변수를 다음에 추가하십시오 DescriptionInput.

    initialState() {
      return {
        focusDescriptionInput: false,
      };
    }
    
  2. 이 상태 변수를 true로 설정하는 핸들러 메소드를 정의하십시오.

    handleTitleInputSubmit() {
      this.setState(focusDescriptionInput: true);
    }
    
  3. 에 enter / next를 제출 / 타자하면을 (를) TitleInput호출 handleTitleInputSubmit합니다. 이것은 focusDescriptionInputtrue로 설정 됩니다.

    <TextInput 
       style = {styles.titleInput}
       returnKeyType = {"next"}
       autoFocus = {true}
       placeholder = "Title" 
       onSubmitEditing={this.handleTitleInputSubmit}
    />
    
  4. DescriptionInputfocusprop은 focusDescriptionInput상태 변수로 설정됩니다 . 따라서 focusDescriptionInput3 단계에서 변경 DescriptionInput하면으로 다시 렌더링됩니다 focus={true}.

    <TextInput
       style = {styles.descriptionInput}          
       multiline = {true}
       maxLength = {200}
       placeholder = "Description" 
       focus={this.state.focusDescriptionInput}
    />
    

refs는 더 약한 코드로 이어질 수 있기 때문에 refs를 사용하지 않는 좋은 방법입니다. :)

편집 : @LaneRettig에 h / t를 추가하여 React Native TextInput을 추가 소품 및 메소드로 감싸서 응답해야한다고 지적했습니다 focus.

    // Props:
    static propTypes = { 
        focus: PropTypes.bool,
    } 

    static defaultProps = { 
        focus: false,
    } 

    // Methods:
    focus() {
        this._component.focus(); 
    } 

    componentWillReceiveProps(nextProps) {
        const {focus} = nextProps; 

        focus && this.focus(); 
    }

React Native 0.36부터 focus()텍스트 입력 노드에서 (다른 답변에서 제안 된) 호출 은 더 이상 지원되지 않습니다. 대신 TextInputStateReact Native 에서 모듈을 사용할 수 있습니다 . 이것을 쉽게하기 위해 다음 도우미 모듈을 만들었습니다.

// TextInputManager
//
// Provides helper functions for managing the focus state of text
// inputs. This is a hack! You are supposed to be able to call
// "focus()" directly on TextInput nodes, but that doesn't seem
// to be working as of ReactNative 0.36
//
import { findNodeHandle } from 'react-native'
import TextInputState from 'react-native/lib/TextInputState'


export function focusTextInput(node) {
  try {
    TextInputState.focusTextInput(findNodeHandle(node))
  } catch(e) {
    console.log("Couldn't focus text input: ", e.message)
  }
}

그런 다음의 focusTextInput"ref" 에서 함수를 호출 할 수 있습니다 TextInput. 예를 들면 다음과 같습니다.

...
<TextInput onSubmit={() => focusTextInput(this.refs.inputB)} />
<TextInput ref="inputB" />
...

래핑 뷰를 바꾸고 TextInput을 가져 오는 것 외에 다른 코드 변경이 필요없는 작은 라이브러리를 만들었습니다.

import { Form, TextInput } from 'react-native-autofocus'

export default () => (
  <Form>
    <TextInput placeholder="test" />
    <TextInput placeholder="test 2" />
  </Form>
)

https://github.com/zackify/react-native-autofocus

여기에 자세히 설명되어 있습니다 : https://zach.codes/autofocus-inputs-in-react-native/


반응 네이티브 0.45.1을 사용하여 사용자 이름 TextInput에서 return 키를 누른 후 암호 TextInput에 포커스를 설정하는 데 문제가 발생했습니다.

여기에 최고 등급의 솔루션을 대부분 시도한 후 github에서 내 요구를 충족시키는 솔루션을 찾았습니다. https://github.com/shoutem/ui/issues/44#issuecomment-290724642

그것을 요 ​​약하기:

import React, { Component } from 'react';
import { TextInput as RNTextInput } from 'react-native';

export default class TextInput extends Component {
    render() {
        const { props } = this;

        return (
            <RNTextInput
                {...props}
                ref={(input) => props.inputRef && props.inputRef(input)}
            />
        );
    }
}

그리고 나는 이것을 다음과 같이 사용합니다 :

import React, {Component} from 'react';
import {
    View,
} from 'react-native';
import TextInput from "../../components/TextInput";

class Login extends Component {
    constructor(props) {
        super(props);
        this.passTextInput = null
    }

    render() {
        return (
            <View style={{flex:1}}>
                <TextInput
                    style={{flex:1}}
                    placeholder="Username"
                    onSubmitEditing={(event) => {
                        this.passTextInput.focus()
                    }}
                />

                <TextInput
                    style={{flex:1}}
                    placeholder="Password"
                    inputRef={(input) => {
                        this.passTextInput = input
                    }}
                />
            </View>
        )
    }
}

RN 0.50.3의 경우 다음과 같은 방법으로 가능합니다.

<TextInput 
  autoFocus={true} 
  onSubmitEditing={() => {this.PasswordInputRef._root.focus()}} 
/>

<TextInput ref={input => {this.PasswordInputRef = input}} />

이 내용이 표시되어야합니다 .PasswordInputRef. _root .focus ()


tcomb-form-native내가 있는 그대로 사용 하면이 작업도 수행 할 수 있습니다. 요령은 다음과 같습니다. TextInput직접 소품을 설정하는 대신을 통해 수행합니다 options. 양식의 필드를 다음과 같이 참조 할 수 있습니다.

this.refs.form.getComponent('password').refs.input.focus()

따라서 최종 제품은 다음과 같습니다.

var t = require('tcomb-form-native');
var Form = t.form.Form;

var MyForm = t.struct({
  field1:     t.String,
  field2:     t.String,
});

var MyComponent = React.createClass({

  _getFormOptions () {
    return {
      fields: {
        field1: {
          returnKeyType: 'next',
          onSubmitEditing: () => {this.refs.form.getComponent('field2').refs.input.focus()},
        },
      },
    };
  },

  render () {

    var formOptions = this._getFormOptions();

    return (
      <View style={styles.container}>
        <Form ref="form" type={MyForm} options={formOptions}/>
      </View>
    );
  },
});

(여기에서 아이디어를 게시 remcoanker에 제공 : https://github.com/gcanti/tcomb-form-native/issues/96 )


이것이 내가 달성 한 방법입니다. 그리고 아래 예제는 React 16.3에서 소개 된 React.createRef () API를 사용했습니다.

class Test extends React.Component {
  constructor(props) {
    super(props);
    this.secondTextInputRef = React.createRef();
  }

  render() {
    return(
        <View>
            <TextInput
                placeholder = "FirstTextInput"
                returnKeyType="next"
                onSubmitEditing={() => { this.secondTextInputRef.current.focus(); }}
            />
            <TextInput
                ref={this.secondTextInputRef}
                placeholder = "secondTextInput"
            />
        </View>
    );
  }
}

나는 이것이 당신을 도울 것이라고 생각합니다.


레거시 문자열 참조 대신 콜백 참조 사용 :

<TextInput
    style = {styles.titleInput}
    returnKeyType = {"next"}
    autoFocus = {true}
    placeholder = "Title"
    onSubmitEditing={() => {this.nextInput.focus()}}
/>
<TextInput
    style = {styles.descriptionInput}  
    multiline = {true}
    maxLength = {200}
    placeholder = "Description"
    ref={nextInput => this.nextInput = nextInput}
/>

내 시나리오는 <CustomBoladonesTextInput /> RN <TextInput /> 래핑 입니다.

이 문제를 다음과 같이 해결했습니다.

내 양식은 다음과 같습니다

  <CustomBoladonesTextInput 
      onSubmitEditing={() => this.customInput2.refs.innerTextInput2.focus()}
      returnKeyType="next"
      ... />

  <CustomBoladonesTextInput 
       ref={ref => this.customInput2 = ref}
       refInner="innerTextInput2"
       ... />

CustomBoladonesTextInput의 컴포넌트 정의에서 refField를 다음과 같이 내부 참조 소품에 전달합니다.

   export default class CustomBoladonesTextInput extends React.Component {
      render() {        
         return (< TextInput ref={this.props.refInner} ... />);     
      } 
   }

그리고 짜잔. 모든 것이 다시 작동합니다. 도움이 되었기를 바랍니다


React Native의 GitHub 문제에서이 솔루션을 사용해보십시오.

https://github.com/facebook/react-native/pull/2149#issuecomment-129262565

TextInput 구성 요소에 ref 소품을 사용해야합니다.
그런 다음 onSubmitEditing prop에서 호출되어 두 번째 TextInput 참조로 초점을 이동시키는 함수를 작성해야합니다.

var InputScreen = React.createClass({
    _focusNextField(nextField) {
        this.refs[nextField].focus()
    },

    render: function() {
        return (
            <View style={styles.container}>
                <TextInput
                    ref='1'
                    style={styles.input}
                    placeholder='Normal'
                    returnKeyType='next'
                    blurOnSubmit={false}
                    onSubmitEditing={() => this._focusNextField('2')}
                />
                <TextInput
                    ref='2'
                    style={styles.input}
                    keyboardType='email-address'
                    placeholder='Email Address'
                    returnKeyType='next'
                    blurOnSubmit={false}
                    onSubmitEditing={() => this._focusNextField('3')}
                />
                <TextInput
                    ref='3'
                    style={styles.input}
                    keyboardType='url'
                    placeholder='URL'
                    returnKeyType='next'
                    blurOnSubmit={false}
                    onSubmitEditing={() => this._focusNextField('4')}
                />
                <TextInput
                    ref='4'
                    style={styles.input}
                    keyboardType='numeric'
                    placeholder='Numeric'
                    blurOnSubmit={false}
                    onSubmitEditing={() => this._focusNextField('5')}
                />
                <TextInput
                    ref='5'
                    style={styles.input}
                    keyboardType='numbers-and-punctuation'
                    placeholder='Numbers & Punctuation'
                    returnKeyType='done'
                />
            </View>
        );
    }
});

TextInput다른 구성 요소 내에있는 경우 허용 된 솔루션이 작동 하려면 참조를 ref부모 컨테이너 로 "팝핑"해야합니다 .

// MyComponent
render() {
    <View>
        <TextInput ref={(r) => this.props.onRef(r)} { ...this.props }/>
    </View>
}

// MyView
render() {
    <MyComponent onSubmitEditing={(evt) => this.myField2.focus()}/>
    <MyComponent onRef={(r) => this.myField2 = r}/>
}

<TextInput placeholder="Nombre"
    ref="1"
    editable={true}
    returnKeyType="next"
    underlineColorAndroid={'#4DB6AC'}
    blurOnSubmit={false}
    value={this.state.First_Name}
    onChangeText={First_Name => this.setState({ First_Name })}
    onSubmitEditing={() => this.focusNextField('2')}
    placeholderTextColor="#797a7a" style={{ marginBottom: 10, color: '#808080', fontSize: 15, width: '100%', }} />

<TextInput placeholder="Apellido"
    ref="2"
    editable={true}
    returnKeyType="next"
    underlineColorAndroid={'#4DB6AC'}
    blurOnSubmit={false}
    value={this.state.Last_Name}
    onChangeText={Last_Name => this.setState({ Last_Name })}
    onSubmitEditing={() => this.focusNextField('3')}
    placeholderTextColor="#797a7a" style={{ marginBottom: 10, color: '#808080', fontSize: 15, width: '100%', }} />

메소드 추가

focusNextField(nextField) {
    this.refs[nextField].focus();
}

에서 을 캡처하는 방법이 있습니다 TextInput. 해 키지 만 아무것도 아닌 것보다 낫습니다 .

onChangeText새 입력 값을 이전 값과 비교하여 a를 확인 하는 핸들러를 정의하십시오 \t. 발견되면 @boredgames에 표시된대로 필드를 진행하십시오.

변수 username에 사용자 이름 값이 포함되어 있고 setUsername상점 (구성 요소 상태, redux 상점 등)에서 변경하기위한 조치를 전달 한다고 가정하면 다음과 같이하십시오.

function tabGuard (newValue, oldValue, callback, nextCallback) {
  if (newValue.indexOf('\t') >= 0 && oldValue.indexOf('\t') === -1) {
    callback(oldValue)
    nextCallback()
  } else {
    callback(newValue)
  }
}

class LoginScene {
  focusNextField = (nextField) => {
    this.refs[nextField].focus()
  }

  focusOnPassword = () => {
    this.focusNextField('password')
  }

  handleUsernameChange = (newValue) => {
    const { username } = this.props            // or from wherever
    const { setUsername } = this.props.actions // or from wherever

    tabGuard(newValue, username, setUsername, this.focusOnPassword)
  }

  render () {
    const { username } = this.props

    return (
      <TextInput ref='username'
                 placeholder='Username'
                 autoCapitalize='none'
                 autoCorrect={false}
                 autoFocus
                 keyboardType='email-address'
                 onChangeText={handleUsernameChange}
                 blurOnSubmit={false}
                 onSubmitEditing={focusOnPassword}
                 value={username} />
    )
  }
}

귀하의 구성 요소에서 :

constructor(props) {
        super(props);
        this.focusNextField = this
            .focusNextField
            .bind(this);
        // to store our input refs
        this.inputs = {};
    }
    focusNextField(id) {
        console.log("focus next input: " + id);
        this
            .inputs[id]
            ._root
            .focus();
    }

참고 : NativeBase 'Library'Input의._root TextInput에 대한 참조이므로 사용 했습니다.

이 같은 텍스트 입력에서

<TextInput
         onSubmitEditing={() => {
                          this.focusNextField('two');
                          }}
         returnKeyType="next"
         blurOnSubmit={false}/>


<TextInput      
         ref={input => {
              this.inputs['two'] = input;
                        }}/>

여기에 : focus 속성을 가진 입력 구성 요소에 대한 시약 솔루션이 있습니다.

이 prop이 true로 설정되어 있으면 필드에 포커스가 설정되고 false가 아니면 포커스가 없습니다.

불행히도이 구성 요소에는 : ref가 정의되어 있어야하며 .focus ()를 호출하는 다른 방법을 찾을 수 없습니다. 나는 제안에 행복하다.

(defn focusable-input [init-attrs]
  (r/create-class
    {:display-name "focusable-input"
     :component-will-receive-props
       (fn [this new-argv]
         (let [ref-c (aget this "refs" (:ref init-attrs))
               focus (:focus (ru/extract-props new-argv))
               is-focused (.isFocused ref-c)]
           (if focus
             (when-not is-focused (.focus ref-c))
             (when is-focused (.blur ref-c)))))
     :reagent-render
       (fn [attrs]
         (let [init-focus (:focus init-attrs)
               auto-focus (or (:auto-focus attrs) init-focus)
               attrs (assoc attrs :auto-focus auto-focus)]
           [input attrs]))}))

https://gist.github.com/Knotschi/6f97efe89681ac149113ddec4c396cc5


NativeBase를 UI 구성 요소로 사용하는 경우이 샘플을 사용할 수 있습니다

<Item floatingLabel>
    <Label>Title</Label>
    <Input
        returnKeyType = {"next"}
        autoFocus = {true}
        onSubmitEditing={(event) => {
            this._inputDesc._root.focus(); 
        }} />
</Item>
<Item floatingLabel>
    <Label>Description</Label>
    <Input
        getRef={(c) => this._inputDesc = c}
        multiline={true} style={{height: 100}} />
        onSubmitEditing={(event) => { this._inputLink._root.focus(); }} />
</Item>

참고 URL : https://stackoverflow.com/questions/32748718/react-native-how-to-select-the-next-textinput-after-pressing-the-next-keyboar

반응형