React Native实现带区号选择器的手机号输入UI及自定义键盘需求
解决方案
一、调整react-native-phone-number-input的UI样式
默认组件支持通过多维度样式属性自定义各部分外观,你可以针对国家选择按钮、区号文本、输入容器分别设置样式,匹配目标UI:
import PhoneInput from 'react-native-phone-number-input'; import { useState } from 'react'; import { StyleSheet, View, TouchableOpacity } from 'react-native'; // 组件内部状态 const [phoneNumber, setPhoneNumber] = useState(''); const [countryCode, setCountryCode] = useState('AE'); const [isKeyboardVisible, setIsKeyboardVisible] = useState(false); // 渲染输入框 <PhoneInput defaultValue={phoneNumber} defaultCode={countryCode} onChangeFormattedText={(text) => setPhoneNumber(text)} onChangeCountry={(country) => setCountryCode(country.cca2)} containerStyle={styles.phoneContainer} textContainerStyle={styles.textContainer} codeTextStyle={styles.codeText} flagButtonStyle={styles.flagButton} textInputProps={{ editable: false, // 禁用系统输入,避免弹出默认键盘 showSoftInputOnFocus: false, }} onPress={() => setIsKeyboardVisible(true)} // 点击触发自定义键盘显示 />
对应的样式定义:
const styles = StyleSheet.create({ phoneContainer: { width: '80%', height: 65, backgroundColor: '#fff', // 按目标UI调整背景色 borderColor: '#ccc', borderWidth: 1, borderRadius: 8, flexDirection: 'row', alignItems: 'center', paddingHorizontal: 10, }, textContainer: { flex: 1, marginLeft: 10, borderWidth: 0, // 移除默认输入框边框 }, codeText: { fontSize: 16, fontWeight: '500', color: '#333', }, flagButton: { padding: 0, }, });
二、实现自定义数字键盘
封装一个独立的数字键盘组件,通过状态控制显示/隐藏,点击按键时更新手机号并保持格式化:
const CustomNumberKeyboard = ({ onNumberPress, onDeletePress, onClose }) => { const numbers = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '', '0', '⌫']; return ( <View style={styles.keyboardContainer}> <TouchableOpacity onPress={onClose} style={styles.closeButton}> <Text>完成</Text> </TouchableOpacity> <View style={styles.keyboardGrid}> {numbers.map((num, index) => ( <TouchableOpacity key={index} style={styles.keyButton} onPress={() => { if (num === '⌫') { onDeletePress(); } else if (num) { onNumberPress(num); } }} > <Text style={styles.keyText}>{num}</Text> </TouchableOpacity> ))} </View> </View> ); }; // 键盘样式 const styles = StyleSheet.create({ keyboardContainer: { position: 'absolute', bottom: 0, left: 0, right: 0, backgroundColor: '#fff', borderTopWidth: 1, borderTopColor: '#eee', paddingVertical: 20, }, closeButton: { alignSelf: 'flex-end', paddingRight: 20, paddingBottom: 10, }, keyboardGrid: { flexDirection: 'row', flexWrap: 'wrap', justifyContent: 'center', }, keyButton: { width: '30%', height: 60, alignItems: 'center', justifyContent: 'center', marginVertical: 5, }, keyText: { fontSize: 20, fontWeight: 'bold', color: '#333', }, });
三、整合组件并处理手机号格式化
使用react-native-phone-number-input提供的parsePhoneNumber工具,确保输入的手机号符合对应国家的格式规范:
import { parsePhoneNumber } from 'react-native-phone-number-input'; // 处理数字按键点击 const handleNumberPress = (num) => { const newNumber = phoneNumber + num; try { const parsed = parsePhoneNumber(newNumber, countryCode); setPhoneNumber(parsed?.formattedNumber || newNumber); } catch (e) { setPhoneNumber(newNumber); } }; // 处理删除按键点击 const handleDeletePress = () => { if (phoneNumber.length === 0) return; const newNumber = phoneNumber.slice(0, -1); try { const parsed = parsePhoneNumber(newNumber, countryCode); setPhoneNumber(parsed?.formattedNumber || newNumber); } catch (e) { setPhoneNumber(newNumber); } }; // 在render中整合输入框与键盘 return ( <View style={styles.container}> {/* 手机号输入框 */} <PhoneInput // 上述配置属性 /> {/* 自定义数字键盘 */} {isKeyboardVisible && ( <CustomNumberKeyboard onNumberPress={handleNumberPress} onDeletePress={handleDeletePress} onClose={() => setIsKeyboardVisible(false)} /> )} </View> );
四、替代方案:完全自定义输入组件
如果react-native-phone-number-input的样式限制过多,可以拆分实现:
- 用
react-native-country-picker-modal做国家选择器 - 自定义文本显示区域替代输入框
- 搭配上述自定义数字键盘
示例代码:
import CountryPicker from 'react-native-country-picker-modal'; // 组件内部状态 const [country, setCountry] = useState({ cca2: 'AE', callingCode: '971' }); // 渲染自定义输入组件 <View style={styles.customPhoneInput}> <CountryPicker countryCode={country.cca2} onSelect={(selectedCountry) => setCountry(selectedCountry)} withCallingCode withFlag containerButtonStyle={styles.countryPickerButton} /> <TouchableOpacity style={styles.phoneDisplay} onPress={() => setIsKeyboardVisible(true)} > <Text style={styles.phoneText}>{phoneNumber || '请输入手机号'}</Text> </TouchableOpacity> </View> // 对应样式 const styles = StyleSheet.create({ customPhoneInput: { width: '80%', height: 65, flexDirection: 'row', alignItems: 'center', borderColor: '#ccc', borderWidth: 1, borderRadius: 8, paddingHorizontal: 10, }, countryPickerButton: { padding: 0, width: 80, }, phoneDisplay: { flex: 1, height: '100%', justifyContent: 'center', marginLeft: 10, }, phoneText: { fontSize: 16, color: '#333', }, });
这种方式可以完全控制UI的每一部分,更灵活匹配目标设计。
内容的提问来源于stack exchange,提问作者Anjali
相关产品推荐
相关产品推荐

