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

Cocos Creator 3.6安卓端获取虚拟键盘高度问题求助

安卓端Cocos Creator 3.6获取虚拟键盘高度的正确实现方案

问题分析

你现有代码的核心问题:

  1. 错误选择了监听视图(窗口rootView而非Cocos的GLSurfaceView),adjustResize实际作用于Cocos的游戏渲染视图,而非整个窗口的根视图
  2. 未处理监听器重复注册问题,且未过滤无效的高度触发值
  3. 键盘弹出前注册监听器,导致首次回调无法捕获键盘弹出后的布局变化

正确实现步骤

1. 确认Activity配置

确保AndroidManifest.xml中Activity的windowSoftInputMode仅设置adjustResize,不要叠加adjustPan:

android:windowSoftInputMode="adjustResize"

2. 原生安卓端(AppActivity.java)代码修改

替换原有键盘高度计算逻辑,直接监听Cocos的GLSurfaceView布局变化,并处理回调过滤与内存泄漏:

import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewTreeObserver;
import android.content.res.Resources;
import org.cocos2dx.lib.CocosHelper;
import org.cocos2dx.lib.CocosJavascriptJavaBridge;
import org.cocos2dx.lib.Cocos2dxGLSurfaceView;

public class AppActivity extends org.cocos2dx.lib.Cocos2dxActivity {
    private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener;
    private int lastKeyboardHeight = 0;

    // 供Cocos JS调用的注册方法
    public void registerKeyboardHeightListener() {
        // 先移除旧监听器,避免重复注册
        if (keyboardLayoutListener != null) {
            getGLSurfaceView().getViewTreeObserver().removeOnGlobalLayoutListener(keyboardLayoutListener);
        }

        keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Rect visibleFrame = new Rect();
                // 监听Cocos渲染视图的可见区域变化
                getGLSurfaceView().getWindowVisibleDisplayFrame(visibleFrame);

                // 获取屏幕真实高度(含状态栏、导航栏)
                DisplayMetrics displayMetrics = new DisplayMetrics();
                getWindowManager().getDefaultDisplay().getRealMetrics(displayMetrics);
                int screenFullHeight = displayMetrics.heightPixels;

                // 计算键盘高度:减去可见区域底部、导航栏高度
                int navigationBarHeight = getNavigationBarHeight();
                int keyboardHeight = screenFullHeight - visibleFrame.bottom - navigationBarHeight;

                // 过滤无效触发:高度差超过50才通知,避免微小布局波动
                if (Math.abs(keyboardHeight - lastKeyboardHeight) > 50) {
                    lastKeyboardHeight = keyboardHeight;
                    // 通知Cocos JS层
                    notifyCocosKeyboardHeight(Math.max(keyboardHeight, 0));
                }
            }
        };

        // 绑定监听器到Cocos视图
        getGLSurfaceView().getViewTreeObserver().addOnGlobalLayoutListener(keyboardLayoutListener);
    }

    // 获取系统导航栏高度
    private int getNavigationBarHeight() {
        Resources res = getResources();
        int resId = res.getIdentifier("navigation_bar_height", "dimen", "android");
        return resId > 0 ? res.getDimensionPixelSize(resId) : 0;
    }

    // 向Cocos JS层传递键盘高度
    private void notifyCocosKeyboardHeight(final int height) {
        CocosHelper.runOnGameThread(new Runnable() {
            @Override
            public void run() {
                // 调用JS全局回调方法
                String jsCmd = String.format("window.onKeyboardHeightChanged(%d)", height);
                CocosJavascriptJavaBridge.evalString(jsCmd);
            }
        });
    }

    // 页面销毁时清理监听器,防止内存泄漏
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (keyboardLayoutListener != null) {
            getGLSurfaceView().getViewTreeObserver().removeOnGlobalLayoutListener(keyboardLayoutListener);
            keyboardLayoutListener = null;
        }
    }
}

3. Cocos Creator JS层代码修改

注册全局回调,并在输入框编辑开始时触发原生监听器注册:

import { _decorator, Node, sys, native, Component } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('InputManager')
export class InputManager extends Component {
    @property(Node)
    inputNode: Node = null; // 你的输入框节点

    onLoad() {
        // 注册全局键盘高度回调
        window['onKeyboardHeightChanged'] = (height: number) => {
            this.adjustInputPosition(height);
        };
    }

    // 输入框编辑开始事件绑定的方法
    onInputStart() {
        if (sys.isNative && sys.os === sys.OS.ANDROID) {
            // 调用原生注册监听器
            native.reflection.callStaticMethod(
                "com/cocos/game/AppActivity",
                "registerKeyboardHeightListener",
                "()V"
            );
        }
    }

    // 调整输入框位置
    adjustInputPosition(keyboardHeight: number) {
        if (!this.inputNode) return;
        
        if (keyboardHeight > 0) {
            // 键盘弹出:将输入框移至键盘上方(20为间距,可根据布局调整)
            this.inputNode.setPositionY(keyboardHeight + 20);
        } else {
            // 键盘隐藏:恢复输入框原位置(这里假设原Y为0,根据实际布局修改)
            this.inputNode.setPositionY(0);
        }
    }
}

关键注意点

  • 必须监听Cocos的GLSurfaceView:adjustResize仅会调整该视图的大小,而非整个窗口的根视图
  • 过滤高度差:避免因状态栏、导航栏的微小变化触发无效回调
  • 清理监听器:在Activity销毁时移除监听器,防止内存泄漏
  • 避免adjustPan:该属性会让窗口整体平移而非resize,导致布局变化监听失效

内容的提问来源于stack exchange,提问作者Sahana Dattatreya Hegde

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 05:20:40