如何让自定义View底部与软键盘对齐且无需修改Activity配置
可行解决方案
你遇到的问题本质是adjustPan模式下,系统默认只滚动到获得焦点的子EditText的底部,而非外层自定义ViewGroup的底部,你不需要修改Activity的windowSoftInputMode配置,两种方案可直接在自定义View内部实现:
方案1:重写焦点矩形计算逻辑(适配系统默认调整逻辑,无侵入)
系统在软键盘弹出计算需要露出的区域时,会调用焦点控件所在父容器的getFocusedRect方法获取需要保证可见的矩形范围,你只需要在自定义TestEditText中重写该方法,将返回范围替换为自身的完整边界即可,该逻辑和TextInputLayout的内部实现一致:
@Override public void getFocusedRect(Rect r) { // 直接返回当前自定义View的完整矩形,而非子EditText的矩形 r.set(0, 0, getWidth(), getHeight()); }
同时在initTestEditText方法中补充如下配置,保证父布局能正确接收子焦点的状态同步:
setFocusable(true); setFocusableInTouchMode(true); // 原有setAddStatesFromChildren(true)保留即可
不需要修改任何Activity配置,系统调整滚动时会自动将整个TestEditText的底部和软键盘顶部对齐。
方案2:自定义软键盘高度监听+主动调整位置(兼容所有windowSoftInputMode模式)
如果方案1在你的场景下不生效(比如Activity被设置了adjustNothing),可以在View内部自行监听软键盘高度变化,主动调整自身位置:
private int lastKeyboardHeight = 0; @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); // 监听WindowInsets变化获取软键盘高度 setOnApplyWindowInsetsListener((v, insets) -> { int keyboardHeight = insets.getInsets(WindowInsets.Type.ime()).bottom; if (keyboardHeight != lastKeyboardHeight) { lastKeyboardHeight = keyboardHeight; updatePositionForKeyboard(keyboardHeight); } return insets; }); requestApplyInsets(); } private void updatePositionForKeyboard(int keyboardHeight) { if (keyboardHeight > 0) { // 软键盘弹出,计算需要上移的距离 int[] location = new int[2]; getLocationOnScreen(location); int viewBottom = location[1] + getHeight(); int screenHeight = getResources().getDisplayMetrics().heightPixels; int keyboardTop = screenHeight - keyboardHeight; if (viewBottom > keyboardTop) { // View底部被软键盘遮挡,上移对应距离保证底部对齐软键盘顶部 setTranslationY(-(viewBottom - keyboardTop)); } } else { // 软键盘收起,恢复原始位置 setTranslationY(0); } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); setOnApplyWindowInsetsListener(null); }
该方案Android 11及以上系统可直接使用,低版本系统可配合ViewTreeObserver.OnGlobalLayoutListener监听布局高度变化计算软键盘高度,逻辑同理。
内容的提问来源于stack exchange,提问作者sweak
相关产品推荐
相关产品推荐

