简体   繁体   中英

Show soft keyboard in Android with Delphi OpenGL app (no FMX)

Hiyas.

Does anyone know how to achieve this?

I'm creating a "context" (a draw surface) with something like the following code:

Initially:

FApp:= Pandroid_app(PANativeActivity(DelphiActivity)^.instance);

FApp.userData:= Self;
FApp.onAppCmd:= OnAppCmd;

After receiving APP_CMD_INIT_WINDOW in OnAppCmd:

FDisplay := eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(FDisplay, nil, nil);
eglChooseConfig(FDisplay, @attribs[0], @config, 1, @numConfigs);
eglGetConfigAttrib(FDisplay, config, EGL_NATIVE_VISUAL_ID, @format);

ANativeWindow_setBuffersGeometry(FApp.window, 0, 0, format);

FSurface := eglCreateWindowSurface(FDisplay, config, FApp.window, nil);
FContext := eglCreateContext(FDisplay, config, nil, nil);

if  (eglMakeCurrent(FDisplay, FSurface, FSurface, FContext) = EGL_FALSE) then
    begin
    Abort;
    end;

However, I seem to need a "view" in order to make it focused such that I can then tell the Android system to enable and show the keyboard for it. The following code does not work (because I don't have focus, I believe):

ANativeActivity_showSoftInput(PANativeActivity(DelphiActivity), 0);

Does anyone know how to get a view without any FireMonkey code?

I found a reference that seemed to suggest that FApp^.window is a SurfaceHolder (because that's what you pass to eglCreateWindowSurface in their example code) but that didn't seem to work or take me very far.

Do I need to do something like in Java and create a GLSurfaceView descendant? But how do I do that?

Any help very much appreciated.

Daniel.

Edit:

I'm still trying to get this to work. All of the examples I can find are in Java so I've attempted to replicate them.

After APP_CMD_GAINED_FOCUS in OnAppCmd I'm using the following code:

    CallInUIThread(procedure
    var
    wnd: JWindow;
    ctx: JContext;
    ctxcls: JContextClass;
    imm: JInputMethodManager;
    immcls: JInputMethodManagerClass;

    begin
    wnd:= TJNativeActivity.Wrap(PANativeActivity(System.DelphiActivity)^.clazz).getWindow;
    wnd.getDecorView.setFocusable(True);
    wnd.getDecorView.setFocusableInTouchMode(True);

    ctx:= wnd.getContext;
    ctxcls:= JContextClass(ctx.getClass);

    imm:= JInputMethodManager(TJNativeActivity.Wrap(PANativeActivity(System.DelphiActivity)^.clazz).getSystemService(ctxcls.INPUT_METHOD_SERVICE));
    if  Assigned(imm) then
        begin
        immcls:= JInputMethodManagerClass(imm.getClass);
        imm.showSoftInput(wnd.getDecorView, immcls.SHOW_FORCED);
        end;
    end);

It uses some of the FireMonkey framework (for executing in the "UI" thread because trying to access the window otherwise gives a system error that views can't be touched by any other thread) but I should be able to replace that by implementing a JRunnable. I also still don't have a "logical" view...

However, the real problem with this code is that imm is not assigned a value when I try to get it from the context. All of the Java examples assume that it will be.

Further edit:

I think as a last-ditch effort, I have modified the AndroidManifest.template.xml file with the following lines:

    android:configChanges="orientation|keyboard"
    android:windowSoftInputMode="stateAlwaysVisible">

It still doesn't appear.

Eureka! I have it!

I should have gotten it sooner because I'm copying what FMX does but I thought at the time that I could do it more simply, ie do what they do in Java.

It seems that instead of using the InputMethodManager, I need to access the "TextEditorProxy" of the native activity instance that Delphi creates for Android apps.

I'm still using a part of the FireMonkey framework here in order to call CallInUIThread but I will replace it in time with my own JRunnable and call to the Activity's runOnUiThread.

Without further ado, here is the code:

    CallInUIThread(procedure
            var
            fmx: JFMXNativeActivity;
            TextView: JFMXTextEditorProxy;

            begin
            fmx:= TJFMXNativeActivity.Wrap(FApp^.activity.clazz);
            TextView:= fmx.getTextEditorProxy;
            TextView.setFocusable(true);
            TextView.setFocusableInTouchMode(true);
            TextView.requestFocus;
            TextView.showSoftInput(true);
            end);

I still don't know for sure where the input goes to but I shall find out, I hope.

Daniel.

after googled 2 days, I stitch up a solution that works with Delphi XE11.1 .

here is the code, make use of it:

CallInUIThread(
procedure
var
  wnd: JWindow;
  ctx: JContext;
  ctxcls: JContextClass;
  imm: JInputMethodManager;
  immcls: JInputMethodManagerClass;
  view: JView;
  ret: Boolean;
begin
  wnd := MainActivity.getWindow;
  view := wnd.getDecorView;
  view.setFocusable(True);
  view.setFocusableInTouchMode(True);
  ret := MainActivity.getVirtualKeyboard.showFor(View);
end);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM