13

My app opens the input method picker (the menu where you choose a keyboard) with InputMethodManager.showInputMethodPicker(). My app doesn't actually create the picker (it's created by InputMethodManager) but I know it's a ContextMenu and its id is R.id.switchInputMethod.

enter image description here

The picker is part of a multi-step wizard so I need to know when the picker closes so my app can proceed to the next step. Right now I'm checking in a background thread if the default keyboard changed, but that doesn't help if the user selects the same keyboard or presses back.

So I need a way to tell when the picker closes (or some other clever way to know when to proceed).

Thanks in advance...

Barry Fruitman
  • 12,316
  • 13
  • 72
  • 135

3 Answers3

17

Here is a small trick. Please do test it and let us know if it works.

All you have to do is make your activity extend this InputMethodActivity. When you need the user to pick input method, call pickInput(), and onInputMethodPicked() will be called when the user is done.

package mobi.sherif.inputchangecheck;

import android.os.Bundle;
import android.os.Handler;
import android.content.Context;
import android.support.v4.app.FragmentActivity;
import android.view.inputmethod.InputMethodManager;

public abstract class InputMethodActivity extends FragmentActivity {
    protected abstract void onInputMethodPicked();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        mState = NONE;
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if(mState == PICKING) {
            mState = CHOSEN;
        }
        else if(mState == CHOSEN) {
            onInputMethodPicked();

        }
    }

    private static final int NONE = 0;
    private static final int PICKING = 1;
    private static final int CHOSEN = 2;
    private int mState;
    protected final void pickInput() {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.showInputMethodPicker();
        mState = PICKING;
    }
}
Sherif elKhatib
  • 45,786
  • 16
  • 89
  • 106
  • Why do you post the call to onInputMethodPicked() instead of calling it directly? – Barry Fruitman Dec 28 '12 at 23:51
  • Thank you for your answer! It is correct and I prefer using onWindowFocusChanged(), but I awarded the bounty to CapDroid since he answered first with essentially the same answer as yours (check window focus). – Barry Fruitman Dec 30 '12 at 23:57
  • 1
    For me, this only sort of worked. I'm `Settings.Secure.getString(getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);` to determine if my keyboard was selected, however, I don't think the value is set when `onInputMethodPicked` is called. I ended up adding a Handler to the class, and `postDelaying` by 300ms the implementation just so the value returned could settle. Its hacky, but it worked. – Vijay Sharma Aug 26 '15 at 00:46
  • Please pardon me, but how/where do I call `pickInput()`? I tried to assign it to a button's onclick listener by doing `pickInput();`, but it says that the method cannot be resolved. – Erlend K.H. Jan 02 '19 at 19:00
  • @ErlendK.H.You must extend this activity or just copy and paste all the methods to your own activity. – Behnam Maboudi Jan 30 '19 at 08:09
0

There is no such mechanism for check InputMethodPicker is open or not.

But you can check it via another way like as using hasWindowFocus() method for check has focus of your root layout.

Below is sample code:

Main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mainlayout"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />

    <Button
        android:id="@+id/btnPicker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Picker" />

    <Button
        android:id="@+id/btnCheck"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Stop" />

</LinearLayout>

DemoappActivity.class

public class DemoappActivity extends Activity {
    /** Called when the activity is first created. */


    Button btn1 , btn2;
    InputMethodManager imeManager;

    LinearLayout mLayoutRoot;
    TimerTask timertask;
    Timer timer;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mLayoutRoot = (LinearLayout)findViewById(R.id.mainlayout);
        imeManager = (InputMethodManager) getApplicationContext().getSystemService(INPUT_METHOD_SERVICE);
        btn1 = (Button)findViewById(R.id.btnPicker);
        btn1.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                showInputMethodPicker();
            }
        });
        btn2 = (Button)findViewById(R.id.btnCheck);
        btn2.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                timer.cancel();
            }
        });
        checkMyWindowHasFocus();
    }
    @Override
    protected void onDestroy() {

        timer.cancel();
        super.onDestroy();
    }

    public void checkMyWindowHasFocus()
    {
        timertask = new TimerTask() {

            @Override
            public void run() {
                System.out.println("has window focus..."+mLayoutRoot.hasWindowFocus());
                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        Toast.makeText(getApplicationContext(), "Has focus "+mLayoutRoot.hasWindowFocus(), Toast.LENGTH_SHORT).show();
                    }
                });
            }
        };
        timer = new Timer();
        timer.schedule(timertask, 500, 5000);

    }

    private void showInputMethodPicker() {

        if (imeManager != null) {
            imeManager.showInputMethodPicker();

        } else {
            Toast.makeText(this, "Error",Toast.LENGTH_LONG).show();
        }
    }
}
Niranj Patel
  • 32,980
  • 10
  • 97
  • 133
  • so you mean to say if your Root Layout isn't having focus then it means `InputMethodPicker` is opened? then what about other cases which takes root layout focus away? – Mohammed Azharuddin Shaikh Dec 27 '12 at 06:38
  • 1
    This works quite well, except I think Activity.onWindowFocusChanged() is better than a background thread. I'm still testing the code and will reply again soon. Thank you. – Barry Fruitman Dec 28 '12 at 20:28
  • Thanks very much for your answer! I never would have thought to check window focus. Your solution works great (although I prefer using onWindowFocusChanged()). – Barry Fruitman Dec 30 '12 at 23:51
0

Simple you can know by using buildin function:

 @Override
        public void onWindowFocusChanged(boolean hasFocus) {
            super.onWindowFocusChanged(hasFocus);
            isMyInputMethodEnabled();// write what ever you want to do after default keyboard selected
        }


  public void isMyInputMethodEnabled() {
        String imId = Settings.Secure.getString(getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
        if (imId.contains(getPackageName())) {
            startActivity(new Intent(this, Main_uk.class));
            finish();
        }
    }