cocos creator android平台非全屏webview editorBox顶不起页面暂时解决方案

1:场景:游戏嵌入到android平台的webview(非全屏模式),cocos creator 引擎版本:2.3.1

2:问题:

a: 用到了输入框组件但是输入框聚焦用问题,cocos的editorBegin触发的不对,有时候editorBegin触发了但是键盘没有弹出来,很坑,不能忍,产品的需求是当键盘出来的时候抬高输入框尴尬的就是这点(我依据的是只要editorBegin方法触发我就抬高输入框)

b: 顶不起游戏页面,输入框被键盘遮挡,暂且还能忍

我起先是用html5的input代替,但是发现用百分比适配是有问题的,于是我转头去看cocoscreator的input实现,发现input框是依附到cocos节点上进行适配的,利用css的transform的matrix转换,于是自己定义了一个输入框组件,实现跟cocos的edtiroBox差不多,实现了updateMatrix方法,聚焦问题解决了,聚焦的时候一定会弹出键盘,聚焦的时候我抬高input依附的节点,更新input的位置,但是问题是在某些手机上输入框没有抬起,但是节点的位置实际上是已经抬起了的,不知道哪里的问题了哈哈:

具体实现:myInput.ts


const {ccclass, property,executeInEditMode} = cc._decorator;

/**
 * 
 * 输入框组件 原生html标签需要依附一个 ccc节点 设置位置信息
 * 
 */

let polyfill = {
    zoomInvalid: false
};
@ccclass
// @executeInEditMode
export default class MyInput extends cc.Component {

    @property(cc.EditBox)
    cocosBox: cc.EditBox = null;

    @property(cc.Float)
    fontSize: number = 20;
    /** input框html元素 */
    public inputElement: HTMLInputElement = null;

    public worldMat = new cc.Mat4();
    public cameraMat = new cc.Mat4();

    private vec: cc.Vec3 = cc.v3();

    private _m00 = 0;
    private _m01 = 0;
    private _m04 = 0;
    private _m05 = 0;
    private _m12 = 0;
    private _m13 = 0;
    private _w = 0;
    private _h = 0;

    private _isShow: boolean = true;

    private _cacheViewportRect = cc.rect(0,0,0,0);


    /**
     * 是否显示输入框
     * @param  {boolean} tag
     */
    public set isShow(tag: boolean) {
        if(!this.inputElement) {
            console.log('输入框为空');
            return;
        }
        this._isShow = tag;
        if(tag) {
            this.inputElement.style.display = '';
            this.inputElement.style.opacity = '1';
        } else {
            this.inputElement.style.display = 'none';
            this.inputElement.style.opacity = '0';
        }
    }

    public get isShow() {
        return this._isShow;
    }

    onLoad () {
        const container = cc.game.container;
        this.inputElement = document.createElement("input");

        this.inputElement.style.border = "1px solid black";
        this.inputElement.style.borderRadius = "100px";

        this.inputElement.style.background = 'transparent';
        this.inputElement.style.width = this.node.width + 'px';
        this.inputElement.style.height = this.node.height + 'px';
        // this.inputElement.style.active = ;
        this.inputElement.style.outline = 'medium';
        this.inputElement.style.padding = '10px 10px';
        this.inputElement.style.textTransform = 'uppercase';
        this.inputElement.style.position = "absolute";
        this.inputElement.style.bottom = "0px";
        this.inputElement.style.left = 1 + "px";
        this.inputElement.className = "myInput";
        this.inputElement.id = 'myInput0';
        this.inputElement.style.background = '#ffffff';
        this.inputElement.style.fontSize = this.fontSize + 'px';
        this.inputElement.placeholder = "请输入你的答案"

        container.appendChild(this.inputElement);
        
        if (cc.sys.OS_ANDROID === cc.sys.os &&
        (cc.sys.browserType === cc.sys.BROWSER_TYPE_SOUGOU ||
            cc.sys.browserType === cc.sys.BROWSER_TYPE_360)) {
            polyfill.zoomInvalid = true;
        }

        this.inputElement.onfocus = () => {
            console.log('focus',cc.view.getViewportRect());
            if(cc.sys.isBrowser && cc.sys.os === cc.sys.OS_IOS) {
                return;
            }
            this.node.y = 180;
            console.log('nodey is ',this.node.y);

            // console.log(this.cocosBox._impl._elem);
            // this.cocosBox.editBoxEditingDidBegan();
            this.scheduleOnce(() => {
                this.updateMatrix();
                console.log('viewport is ',cc.view.getViewportRect());
            },0)
        }

        this.inputElement.oninput = (data: any) => {
            console.log('input',data.data,this.node.y);
        
            if(this.node.y !== 180) {
                this.node.y = 180;
            }
        }

        this.inputElement.onchange = (event: Event) => {
            console.log('change',event);
            const targetEvent = event.target;
            console.log('value is ',targetEvent['value']);
        }

        this.inputElement.onblur = () => {
            console.log('失去焦点',cc.view.getViewportRect());

            const value = this.inputElement.value;
            this.node.y = -240;
            this.scheduleOnce(() => {
                this.updateMatrix();
                console.log('失去焦点:',cc.view.getViewportRect());
            },0)
            if(!value.trim()) {
                return;
            }
            
            this.sendBarrageData(value);
            this.inputElement.value = '';
        }

        this.inputElement.onkeydown = (event) => {
            console.log('key is ',event['key']);
            if(event['key'] && event['key'] === 'Enter') {
                // 软键盘的回车键
                this.inputElement.blur();
                this.node.y = -240;
                recoverInput();
                if(!this.inputElement.value.trim()) {
                    return;
                }
                this.sendBarrageData(this.inputElement.value);
            }
        }

        this.inputElement.onsubmit = () => {
            recoverInput();
        }

        this.inputElement.addEventListener('compositionstart',() => {
            console.log('compost start');
        });
        this.inputElement.addEventListener('compositionend',() => {
            this.node.y = -240;
            this.inputElement.blur();
            console.log('。。发送');
        });

        this.inputElement.addEventListener('touchstart',() => {
            console.log('touchstart');
        });

        document.addEventListener('touchstart',() => {
            console.log('document start');
        })

        const recoverInput = () => {

        }

        // 监听键盘是弹起还是收起不起作用
        var originalHeight=document.documentElement.clientHeight || document.body.clientHeight;
        window.onresize = function(){
            //键盘弹起与隐藏都会引起窗口的高度发生变化
            var resizeHeight=document.documentElement.clientHeight || document.body.clientHeight;
                if(resizeHeight < originalHeight){
                    console.log('---键盘弹起');
                }else{
                    console.log('--键盘收起');
                }
        }


        // this.isShow = false;
        this.test();
        

    }

    test() {
        const mat = cc.mat4();
        this.node.getWorldMatrix(mat);
        console.log('mat is ',mat);

        let vec = cc.v3(0,0,0);
        let _w = this.node.getContentSize().width;
        let _h = this.node.getContentSize().height;

        vec.x = -this.node.getAnchorPoint().x * _w;
        //@ts-ignore
        vec.y = -this.node.getAnchorPoint().y * _h;

        // vec 该节点的左下角 对世界矩阵进行变换
        cc.Mat4.transform(mat,mat,vec);
        console.log('vec is ',vec);
        console.log('mat is ',mat);

        let cameraMat;
        let camera = cc.Camera.findCamera(this.node);
        // camera.getWorldToScreenMatrix2D(cameraMat);
        // console.log("cameraMat is ",cameraMat);
    }

    protected onEnable(): void {
        if(cc.sys.isBrowser && cc.sys.os === cc.sys.OS_IOS) return;
        this.node.on(cc.Node.EventType.TOUCH_END,this.focusInput,this);
    }

    protected onDisable(): void {
        if(cc.sys.isBrowser && cc.sys.os === cc.sys.OS_IOS) return;
        this.node.off(cc.Node.EventType.TOUCH_END,this.focusInput,this);
    }

    focusInput() {
        if(!this.inputElement) return;
        this.inputElement.focus();
    }

     /**
     * 发送弹幕数据
     * @param  {string} str 弹幕数据
     */
    public sendBarrageData(str: string) {

        console.log('发送数据:',str);
        // httpManager.send('post',RequestUrl.ANSWER,{
        //     answer: str,
        //     game_id: facdeCenter.curGameId,
        //     turn_index: facdeCenter.turnIndex
        // },(data: any) => {
        //     console.log('发送弹幕数据,响应消息: ',data);
        //     if(data.err_code === 89007) {
        //         console.log('回合不正确');
        //     }
        //     if(data.status === "OK") {
        //         facdeCenter.selfIsAnswerRight = data.data;
        //         facdeCenter.hideInput(!data.data);
        //         const seatComp = facdeCenter.user2SeatMap[facdeCenter.userId];
        //         seatComp.isAnswerRight = true;
        //     }
        // });
    }

    start () {

    }

    // 更新输入框矩阵
    updateMatrix() {
        let node = this.node;
        node.getWorldMatrix(this.worldMat);
        let worldMat = this.worldMat;
        let worldMatm = worldMat.m;
        //@ts-ignore
        const conSize = node._contentSize;
        let container = cc.game.container;

        // check whether need to update
        if (this._m00 === worldMatm[0] && this._m01 === worldMatm[1] &&
            this._m04 === worldMatm[4] && this._m05 === worldMatm[5] &&
            this._m12 === worldMatm[12] && this._m13 === worldMatm[13] &&
            this._w === conSize.width && this._h === conSize.height &&
            this._cacheViewportRect.equals(cc.view._viewportRect)) {
            return;
        }

        this._m00 = worldMatm[0];
        this._m01 = worldMatm[1];
        this._m04 = worldMatm[4];
        this._m05 = worldMatm[5];
        this._m12 = worldMatm[12];
        this._m13 = worldMatm[13];

        this._w = conSize.width;
        this._h = conSize.height;

        //@ts-ignore
        this._cacheViewportRect.set(cc.view._viewportRect);
        //@ts-ignore
        let scaleX = cc.view._scaleX, scaleY = cc.view._scaleY,viewport = cc.view._viewportRect,dpr = cc.view._devicePixelRatio;

        //@ts-ignore
        this.vec.x = -node._anchorPoint.x * this._w;
        //@ts-ignore
        this.vec.y = -node._anchorPoint.y * this._h;

        cc.Mat4.transform(worldMat,worldMat,this.vec);

        let cameraMat;
        
        let camera = cc.Camera.findCamera(node);
        if(!camera) {
            console.log("摄像机为null");
            return;
        }
        camera.getWorldToScreenMatrix2D(this.cameraMat);
        cameraMat = this.cameraMat;
        // 摄像机移动到输入框的左下角
        cc.Mat4.multiply(cameraMat,cameraMat,worldMat);

        scaleX /= dpr;
        scaleY /= dpr;

        let cameraMatm = cameraMat.m;
        let a = cameraMatm[0] * scaleX, b = cameraMatm[1], c = cameraMatm[4], d = cameraMatm[5] * scaleY;
    
        let offsetX = container && container.style.paddingLeft && parseInt(container.style.paddingLeft);
        offsetX += viewport.x / dpr;
        let offsetY = container && container.style.paddingBottom && parseInt(container.style.paddingBottom);
        offsetY += viewport.y / dpr;
        let tx = cameraMatm[12] * scaleX + offsetX, ty = cameraMatm[13] * scaleY + offsetY;

        if (polyfill.zoomInvalid) {
            this.setSize(node.width * a, node.height * d);
            a = 1;
            d = 1;
        }

        let elem = this.inputElement;
        let matrix = "matrix(" + a + "," + -b + "," + -c + "," + d + "," + tx + "," + -ty + ")";
        if(!elem) {
            console.log('elemen is null');
            return;
        }
        elem.style['transform'] = matrix;
        elem.style['-webkit-transform'] = matrix;
        elem.style['transform-origin'] = '0px 100% 0px';
        elem.style['-webkit-transform-origin'] = '0px 100% 0px';

    }

    setSize (width, height) {
        let elem = this.inputElement;
        elem.style.width = width + 'px';
        elem.style.height = height + 'px';
    }
    
    /** 更新input框的 */
    update (dt) {
        if(!this.inputElement) return;
        this.updateMatrix();
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值