Can't get backspace to work in codemirror, under Phonegap on Android 4.x?
Asked Answered
Q

1

8

I need a web-based text/code editor that behaves well, for my App.

I'm trying to use codemirror under Phonegap and currently I'm having problems getting backspace to work for previously entered text. This is a huge problem for my use case. Now I've had a look around and it seems like it's not a direct codemirror problem, but rather the android and virtual keyboard malarkey, see this question: Android: Backspace in WebView/BaseInputConnection

I'm using Phonegap version 2.6.0, latest codemirror version (as of last night) and testing on Android 4.2.2. This seems to be specific to WebView on Android, could anyone verify that's not an issue on iOS?

I'm not averse to doing some Java code to rectify the problem, but I'm not sure how to 'hook' into the cordova's implementation of WebView, as all the code that's exposed to me consists of:

package com.mycompany.MyAppName;

import android.os.Bundle;
import org.apache.cordova.*;

public class MyAppName extends DroidGap{
    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        // Set by <content src="index.html" /> in config.xml
        super.loadUrl(Config.getStartUrl());
        //super.loadUrl("file:///android_asset/www/index.html")
    }
}

unless I'm supposed to look into Cordovas source tree. Essentially what I want to know is how I can implement the solution at the link above in my case. Any help is greatly appreciated!

Quelpart answered 11/5, 2013 at 16:11 Comment(1)
Yes, this is not a problem which is specific to CodeMirror as it also occurs with Ace. It also works great when using a hardware keyboard. It is an issue with the virtual on-screen keyboard.Trihedron
C
10

Override init Activity method :

public class ProjectName extends DroidGap
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        init(); // Don't forget this, you'll get runtime error otherwise!

        // The following does the trick:
        super.appView.getSettings().setUseWideViewPort(true);
        super.appView.getSettings().setLoadWithOverviewMode(true);

        // Set by <content src="index.html" /> in config.xml
        super.loadUrl(Config.getStartUrl());
        //super.loadUrl("file:///android_asset/www/index.html")
        super.setIntegerProperty("loadUrlTimeoutValue", 10000); 
    }

    /**
     * Create and initialize web container with default web view objects.
     */
    @Override
    public void init() {
        CordovaWebView webView = new CustomWebView(ProjectName.this);
        CordovaWebViewClient webViewClient;
        if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB)
        {
            webViewClient = new CordovaWebViewClient(this, webView);
        }
        else
        {
            webViewClient = new IceCreamCordovaWebViewClient(this, webView);
        }
        this.init(webView, webViewClient, new CordovaChromeClient(this, webView));
    }

}

Create on CustomWebView which extends CordovaWebView

public class CustomWebView extends CordovaWebView{

    public CustomWebView(Context context) {
        super(context);
    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        MyCustomInputConnection connection = new MyCustomInputConnection(this, false);

        return connection;
    }

}

Create your custom InputConnection :

public class MyCustomInputConnection extends BaseInputConnection{

    public MyCustomInputConnection(View targetView, boolean fullEditor) {
        super(targetView, fullEditor);
    }

    @Override
    public boolean deleteSurroundingText(int beforeLength, int afterLength) {       
        // magic: in latest Android, deleteSurroundingText(1, 0) will be called for backspace
        if (beforeLength == 1 && afterLength == 0) {
            // backspace
            return super.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))
                && super.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
        }

        return super.deleteSurroundingText(beforeLength, afterLength);
    }
}
Crum answered 29/5, 2013 at 19:35 Comment(6)
It works! thank you so much! Can I ask what the two custom settings are for, beneath the "The following does the trick" comment? I had to disable them, since the page rendered all 'minimized' as if the scale was different.Quelpart
I don't remenber, i will disable them aswell :pCrum
@Nisk, the setUseWideViewPort method is not recommended. It is recommended that you use <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> instead.Trihedron
@MichaelSchwartz Did you eventually figure this one out? I'm having the same issue.Kroeger
Has anyone made a cordova plugin for this?Draghound
has anyone made react native plugin for thisEmbryonic

© 2022 - 2024 — McMap. All rights reserved.