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

ScrollView嵌套ConstraintLayout时,TextInputEditText长文本点击滚至末尾问题

解决ScrollView嵌套长文本TextInputEditText的滚动与焦点异常问题

问题现象

  • 短文本编辑正常;当文本过长超出屏幕高度,点击文本顶部区域,页面会突然滚动到TextInputEditText末尾,光标失去焦点
  • 软键盘弹出但无法看到光标及上下文,输入内容需手动上滚才可见
  • 滚动到末尾后拖动光标上移无效

问题原因

  1. 滚动容器冲突:ScrollView作为外部滚动容器,与TextInputEditText自身的内部滚动逻辑冲突,导致系统获取焦点时强制滚动到EditText底部
  2. 布局约束不当:TextInputLayout设置了app:layout_constraintBottom_toBottomOf="parent",长文本下会拉伸布局,干扰ScrollView的滚动计算
  3. 焦点处理逻辑错误:手动调用requestFocus()和软键盘显示的时机不协调,没有保留点击位置的光标定位

解决方案

1. 调整布局文件(activity_main.xml)

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true" <!-- 确保子布局填充视口,避免滚动异常 -->
    tools:context=".MainActivity">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/constraintLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:layout_marginEnd="20dp"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/photo_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="photo"
            android:textSize="24sp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/content_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="content"
            android:textSize="24sp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/photo_text" />

        <com.google.android.material.textfield.TextInputLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="10dp"
            android:layout_marginTop="8dp"
            android:hint="content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/content_text"
            app:layout_constraintTop_toTopOf="@+id/content_text">

            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/content_edit"
                android:layout_width="match_parent"
                android:layout_height="250dp" <!-- 设置固定高度,也可替换为android:maxHeight="250dp"配合wrap_content -->
                android:gravity="top|start" <!-- 光标默认居左上,避免初始位置异常 -->
                android:scrollbars="vertical" <!-- 开启内部垂直滚动 -->
                android:text="@string/article" />
        </com.google.android.material.textfield.TextInputLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

2. 优化代码逻辑(MainActivity.kt)

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val contentEdit: TextInputEditText = findViewById(R.id.content_edit)
        val constraintLayout: ConstraintLayout = findViewById(R.id.constraintLayout)
        val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager

        // 监听焦点变化,自动处理软键盘与光标定位
        contentEdit.setOnFocusChangeListener { _, hasFocus ->
            if (hasFocus) {
                imm.showSoftInput(contentEdit, InputMethodManager.SHOW_IMPLICIT)
                // 确保光标停留在点击位置,防止自动跳到底部
                contentEdit.post {
                    contentEdit.scrollTo(0, contentEdit.scrollY)
                }
            } else {
                imm.hideSoftInputFromWindow(contentEdit.windowToken, 0)
            }
        }

        // 点击ConstraintLayout空白区域时清除焦点,避免干扰EditText操作
        constraintLayout.setOnTouchListener { _, event ->
            if (event.action == MotionEvent.ACTION_UP) {
                if (!isTouchInsideView(contentEdit, event.rawX, event.rawY)) {
                    contentEdit.clearFocus()
                }
            }
            false
        }
    }

    // 判断点击事件是否落在EditText范围内
    private fun isTouchInsideView(view: View, rawX: Float, rawY: Float): Boolean {
        val location = IntArray(2)
        view.getLocationOnScreen(location)
        val left = location[0]
        val top = location[1]
        val right = left + view.width
        val bottom = top + view.height
        return rawX in left..right && rawY in top..bottom
    }
}

3. 额外优化配置

在AndroidManifest.xml中对应Activity添加软键盘调整模式,避免布局被遮挡:

<activity
    android:name=".MainActivity"
    android:windowSoftInputMode="adjustResize">
    <!-- 其他配置 -->
</activity>

内容的提问来源于stack exchange,提问作者Kartone

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 21:14:54