You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

KeyboardAvoidingView未正常工作,如何实现输入手机号时屏幕上滑?

解决React Native输入框被键盘遮挡问题:实现输入时屏幕上滑

问题根源分析

你的代码里几个关键问题导致KeyboardAvoidingView未生效:

  • Android端未设置有效behavior属性,仅给iOS配置了height,Android默认无适配行为
  • 内部内容用flex:1的View包裹,缺少可滚动容器,内容无法向上滑动
  • 布局层级嵌套逻辑导致KeyboardAvoidingView无法正确计算键盘高度偏移

具体修改方案

按以下步骤调整代码,即可实现输入时屏幕自动上滑:

1. 优化KeyboardAvoidingView配置

给Android设置behavior="padding",同时添加keyboardVerticalOffset适配状态栏/导航栏高度(可根据实际布局调整数值)。

2. 用ScrollView包裹可滚动内容

将内部的loginScreenVisible View替换为ScrollView,通过contentContainerStyle让内容撑满屏幕,确保ScrollView能响应键盘事件触发滚动。

3. 修正样式布局逻辑

移除loginScreenVisible的flex:1,将布局控制交给ScrollView的contentContainerStyle,避免内容挤压导致滚动失效。

修改后的完整代码

JSX部分

import { KeyboardAvoidingView, TouchableWithoutFeedback, Keyboard, ScrollView, View, Image, Text, ActivityIndicator, TouchableOpacity, Platform } from 'react-native';
// 导入你的其他组件(OTPInputView、PhoneInput等)

// ... 你的状态和函数定义(otpScreenVisible、loading、handleSendTheCode等)

return (
  <KeyboardAvoidingView
    behavior={Platform.OS === 'ios' ? 'height' : 'padding'}
    keyboardVerticalOffset={Platform.OS === 'ios' ? 60 : 20} // 根据状态栏/导航栏高度调整
    style={styles.container}
  >
    <ScrollView
      contentContainerStyle={styles.loginScreenContainer}
      keyboardShouldPersistTaps="handled"
      showsVerticalScrollIndicator={false}
    >
      <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
        <View style={styles.loginScreenVisible}>
          {/* 登录页图片 */}
          <Image
            source={require('../assets/images/mobileLoginPurple.png')}
            resizeMode="contain"
            style={styles.image}
          />

          <View style={styles.textContainer}>
            <Text style={styles.textPrimary}>Phone Verification</Text>
            <Text style={styles.textDescription}>
              We need to verify your Phone number before getting started !
            </Text>
          </View>

          {otpScreenVisible ? (
            <View style={styles.inputContainer}>
              <OTPInputView
                pinCount={6}
                style={{width: '90%', height: '40%'}}
                autoFocusOnLoad
                codeInputFieldStyle={styles.boxStyle}
                editable
                onCodeChanged={code => setCode(code)}
                codeInputHighlightStyle={styles.highLightStyle}
              />

              {loading ? (
                <ActivityIndicator
                  style={styles.activityIndicator}
                  animating={loading}
                  size="small"
                  color={colors.primary100}
                />
              ) : (
                <TouchableOpacity
                  style={styles.button}
                  onPress={handleVerifyOTP}
                >
                  <Text style={styles.buttonText}>Verify OTP</Text>
                </TouchableOpacity>
              )}

              <View style={styles.actionContainer}>
                <TouchableOpacity onPress={handleEditPhoneNum}>
                  <Text>Edit phone number?</Text>
                </TouchableOpacity>

                <TouchableOpacity onPress={handleResendOTP}>
                  <Text>Resend code</Text>
                </TouchableOpacity>
              </View>
            </View>
          ) : (
            <View style={styles.inputContainer}>
              <PhoneInput
                ref={phoneRef}
                defaultCountry="IN"
                placeholder="Phone Number"
                theme={theme == 'dark' ? 'dark' : 'light'}
              />
              {loading ? (
                <ActivityIndicator
                  style={styles.activityIndicator}
                  animating={loading}
                  size="small"
                  color={colors.primary100}
                />
              ) : (
                <TouchableOpacity
                  style={styles.button}
                  onPress={handleSendTheCode}
                >
                  <Text style={styles.buttonText}>Send the code</Text>
                </TouchableOpacity>
              )}
            </View>
          )}
        </View>
      </TouchableWithoutFeedback>
    </ScrollView>
  </KeyboardAvoidingView>
);

样式部分

StyleSheet.create({
  container: {
    flex: 1,
  },

  loginScreenContainer: {
    flexGrow: 1,
    alignItems: 'center',
    justifyContent: 'center', // 保持内容垂直居中,键盘弹出时自动上移
  },

  loginScreenVisible: {
    width: '100%',
    alignItems: 'center',
  },

  image: {
    width: '80%',
    height: 300,
    marginVertical: 50,
  },

  textContainer: {
    width: '80%',
    justifyContent: 'center',
    alignItems: 'center',
    textAlign: 'center',
  },

  textPrimary: {
    fontSize: 24,
    fontWeight: '800',
    color: 'black',
    marginBottom: 10,
  },

  textDescription: {
    fontSize: 13,
    textAlign: 'center',
    color: colors.text200,
  },

  inputContainer: {
    margin: 30,
    width: '80%',
    alignItems: 'center',
  },

  button: {
    backgroundColor: colors.primary100,
    width: '100%',
    padding: 10,
    marginTop: 20,
    borderRadius: 10,
    justifyContent: 'center',
    alignItems: 'center',
  },

  buttonText: {
    fontSize: 18,
    color: colors.text200,
  },

  boxStyle: {
    width: 40,
    height: 50,
    borderWidth: 3,
    borderColor: colors.primary100,
    color: colors.text100,
    fontSize: 20,
  },

  highLightStyle: {
    borderColor: colors.primary300,
  },

  actionContainer: {
    marginTop: 5,
    flexDirection: 'row',
    justifyContent: 'space-between',
    width: '100%',
  },

  activityIndicator: {
    marginVertical: 16,
  },
});

关键修改点说明

  • KeyboardAvoidingView:Android采用padding行为适配,iOS用height,keyboardVerticalOffset抵消状态栏/导航栏高度,确保输入框刚好停在键盘上方。
  • ScrollView:contentContainerStyle设置flexGrow:1让内容撑满屏幕,keyboardShouldPersistTaps="handled"保证点击空白处能收起键盘且不影响滚动。
  • 样式调整:移除inputContainer的flex:1,避免输入区域过度挤压,让ScrollView能正确计算滚动范围。

内容的提问来源于stack exchange,提问作者Sirigiri Sri Sai Sharanya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 15:34:56