パスコードで保護された画面を作成しようとしています。画面では、パスコードとして4つの数値入力を使用します。
これを行う方法は、TextInputコンポーネントを作成し、メイン画面で4回呼び出します。
私が抱えている問題は、前のTextInputの値を入力するときに、TextInputが次の問題にフォーカスしないことです。
すべてのPasscodeTextInputコンポーネントにrefを使用しています(これはレガシーメソッドであることが通知されていますが、他の方法はわかりません)。
このメソッドを試してみましたが(自分のコンポーネントを作成せずに)、運もありませんでした。[ 〜#〜]メソッド[〜#〜]
index.ios.js
import React, { Component } from 'react';
import { AppRegistry, TextInput, View, Text } from 'react-native';
import { PasscodeTextInput } from './common';
export default class ProgressBar extends Component {
render() {
const { centerEverything, container, passcodeContainer, textInputStyle} = styles;
return (
<View style={[centerEverything, container]}>
<View style={[passcodeContainer]}>
<PasscodeTextInput
autoFocus={true}
ref="passcode1"
onSubmitEditing={(event) => { this.refs.passcode2.focus() }} />
<PasscodeTextInput
ref="passcode2"
onSubmitEditing={(event) => { this.refs.passcode3.focus() }} />
<PasscodeTextInput
ref="passcode3"
onSubmitEditing={(event) => { this.refs.passcode4.focus() }}/>
<PasscodeTextInput
ref="passcode4" />
</View>
</View>
);
}
}
const styles = {
centerEverything: {
justifyContent: 'center',
alignItems: 'center',
},
container: {
flex: 1,
backgroundColor: '#E7DDD3',
},
passcodeContainer: {
flexDirection: 'row',
},
}
AppRegistry.registerComponent('ProgressBar', () => ProgressBar);
PasscodeTextInput.js
import React from 'react';
import {
View,
Text,
TextInput,
Dimensions
} from 'react-native';
const deviceWidth = require('Dimensions').get('window').width;
const deviceHeight = require('Dimensions').get('window').height;
const PasscodeTextInput = ({ ref, autoFocus, onSubmitEditing, onChangeText, value}) => {
const { inputStyle, underlineStyle } = styles;
return(
<View>
<TextInput
ref={ref}
autoFocus={autoFocus}
onSubmitEditing={onSubmitEditing}
style={[inputStyle]}
maxLength={1}
keyboardType="numeric"
placeholderTextColor="#212121"
secureTextEntry={true}
onChangeText={onChangeText}
value={value}
/>
<View style={underlineStyle} />
</View>
);
}
const styles = {
inputStyle: {
height: 80,
width: 60,
fontSize: 50,
color: '#212121',
fontSize: 40,
padding: 18,
margin: 10,
marginBottom: 0
},
underlineStyle: {
width: 60,
height: 4,
backgroundColor: '#202020',
marginLeft: 10
}
}
export { PasscodeTextInput };
更新1
index.ios.js
import React, { Component } from 'react';
import { AppRegistry, TextInput, View, Text } from 'react-native';
import { PasscodeTextInput } from './common';
export default class ProgressBar extends Component {
constructor() {
super()
this.state = {
autoFocus1: true,
autoFocus2: false,
autoFocus3: false,
autoFocus4: false,
}
}
onTextChanged(t) { //callback for immediate state change
if (t == 2) { this.setState({ autoFocus1: false, autoFocus2: true }, () => { console.log(this.state) }) }
if (t == 3) { this.setState({ autoFocus2: false, autoFocus3: true }, () => { console.log(this.state) }) }
if (t == 4) { this.setState({ autoFocus3: false, autoFocus4: true }, () => { console.log(this.state) }) }
}
render() {
const { centerEverything, container, passcodeContainer, testShit, textInputStyle } = styles;
return (
<View style={[centerEverything, container]}>
<View style={[passcodeContainer]}>
<PasscodeTextInput
autoFocus={this.state.autoFocus1}
onChangeText={() => this.onTextChanged(2)} />
<PasscodeTextInput
autoFocus={this.state.autoFocus2}
onChangeText={() => this.onTextChanged(3)} />
<PasscodeTextInput
autoFocus={this.state.autoFocus3}
onChangeText={() => this.onTextChanged(4)} />
<PasscodeTextInput
autoFocus={this.state.autoFocus4} />
</View>
</View>
);
}
}
const styles = {
centerEverything: {
justifyContent: 'center',
alignItems: 'center',
},
container: {
flex: 1,
backgroundColor: '#E7DDD3',
},
passcodeContainer: {
flexDirection: 'row',
},
}
AppRegistry.registerComponent('ProgressBar', () => ProgressBar);
ref
は 特別なプロパティ の1つであるため、ref
を_<TextInput>
_に転送することはできません。したがって、_this.refs.passcode2
_を呼び出すと、代わりに_<PasscodeTextInput>
_が返されます。
_<TextInput>
_からref
を取得するには、次のように変更してください。
PasscodeTextInput.js
_const PasscodeTextInput = ({ inputRef, ... }) => {
...
return (
<View>
<TextInput
ref={(r) => { inputRef && inputRef(r) }}
...
/>
</View>
...
);
}
_
次に、inputRef
から_<PasscodeTextInput>
_を変数に割り当て、focus()
を使用してフォーカスを切り替えます(RN _0.41.2
_以降は非推奨ではありません)。
index.ios.js
_return (
<PasscodeTextInput
autoFocus={true}
onChangeText={(event) => { event && this.passcode2.focus() }} />
<PasscodeTextInput
inputRef={(r) => { this.passcode2 = r }}
onChangeText={(event) => { event && this.passcode3.focus() }} />
<PasscodeTextInput
inputRef={(r) => { this.passcode3 = r }}
onChangeText={(event) => { event && this.passcode4.focus() }} />
<PasscodeTextInput
inputRef={(r) => { this.passcode4 = r }} />
);
_
PS:event && this.passcode2.focus()
は、古いパスコードをクリアして新しいパスコードを入力しようとしたときにフォーカスが切り替わらないようにします。
コンポーネントがマウントされた後にフォーカスできるTextInputのdefaultPropがあります。
autoFocus
Trueの場合、入力をcomponentDidMountにフォーカスします。デフォルト値はfalseです。詳細については、関連する Docs を参照してください。
componentDidUpdate
以降は正常に動作しません。その場合、ref
を使用してプログラムでフォーカスできます。
この画面スタイルは別の方法で処理しました。
4つの個別のTextInputを管理し、それぞれのフォーカスのナビゲーションを処理するのではなく(ユーザーが文字を削除したときに再び戻る)、画面に単一のTextInputがありますが、フォーカスがある(つまり0px x 0px)幅は表示されません。 、maxLength、キーボード構成など.
このTextInputはユーザーから入力を受け取りますが、実際には表示されません。入力されたテキストを一連の単純なView/Text要素としてレンダリングし、上記の画面によく似たスタイルを設定します。
このアプローチは私たちにとってはうまく機能し、「次の」または「前の」TextInputの次に何を集中するかを管理する必要はありませんでした。
Jasonが述べたように、フォーカスメソッドonChangeText
に加えて、maxLength={1}
を使用すると、何が追加されたかを確認せずに、すぐに次の入力にジャンプできます。 ((deprecatedに気付いたばかりですが、これは私が問題を解決した方法であり、v0.36まで正常に動作するはずです) link は、非推奨の関数を更新する方法を説明しています。
<TextInput
ref="first"
style={styles.inputMini}
maxLength={1}
keyboardType="numeric"
returnKeyType='next'
blurOnSubmit={false}
placeholderTextColor="gray"
onChangeText={(val) => {
this.refs['second'].focus()
}}
/>
<TextInput
ref="second"
style={styles.inputMini}
maxLength={1}
keyboardType="numeric"
returnKeyType='next'
blurOnSubmit={false}
placeholderTextColor="gray"
onChangeText={(val) => {
this.refs['third'].focus()
}}
/>
...
私のrefの使用も非推奨ですが、その時点で機能していたことを保証できるので、コードをコピーしたところです(うまくいけば今も機能します)。
最後に、このタイプの実装の主な問題はです。バックスペースを含む数値を削除しようとすると、フォーカスが次の数値にジャンプし、深刻なUXが発生します。問題。ただし、バックスペースキーの入力をリッスンして、次の入力に集中する代わりに別のことを実行できます。したがって、このタイプの実装を使用することを選択したかどうかをさらに調査するために、ここに link を残しておきます。
前述の問題のハッキーな解決策:何かを行う前にonChangeText
プロップに入力された内容を確認すると、次の入力にジャンプできますvalueはnumberであり、それ以外の場合(つまり、バックスペース)、ジャンプして戻ります。 (このアイデアを思いついただけで、まだ試していません。)
問題は、onSubmitEditing
が通常のキーボードの「Return」または「Enter」キーを押したときだと思います...キーパッドにこれらのボタンの1つがありません。
各入力に1文字のみを含める場合、onChangeText
を見て、テキストの長さが1かどうかを確認し、長さが本当に1の場合はfocusを呼び出します。
<TextInput
ref={input => {
this.nameOrId = input;
}}
/>
<TouchableOpacity
onPress={()=>{
this.nameOrId.focus()
}}
>
<Text>Click</Text>
</TouchableOpacity>