Як визначити, чи клавіатура програмного забезпечення видно на пристрої Android чи ні?


249

Чи є в Android спосіб виявити, чи на екрані видно програмне забезпечення (так само "м'яка") клавіатура?



1
що може бути вирішенням цього питання в певних випадках (якщо встановлена ​​сторона-клавіатура) - це перевірка глобальних сповіщень, оскільки при відкритій клавіатурі є системне сповіщення, яке говорить "змінити клавіатуру" - це можна зробити за допомогою NotificationListenerService
Проф

2
майже 8 років, і досі немає твердого рішення, о, якщо вони введуть його, це буде для API> 30 все одно, то не майте уваги ...
М.казем Ахгарі

Відповіді:


71

Прямого шляху немає - див. Http://groups.google.com/group/android-platform/browse_thread/thread/1728f26f2334c060/5e4910f0d9eb898a, де відповіла Діанна Хакборн з команди Android. Однак ви можете виявити це побічно, перевіривши, чи змінився розмір вікна в #onMeasure. Див. Як перевірити видимість клавіатури програмного забезпечення в Android? .


276

Це працює для мене. Можливо, це завжди найкращий спосіб для всіх версій .

Було б ефективно зробити властивість видимості клавіатури і спостерігати за тим, щоб зміни були відкладені, оскільки метод onGlobalLayout викликає багато разів. Також добре перевірити обертання пристрою, а windowSoftInputModeчи ні adjustNothing.

boolean isKeyboardShowing = false;
void onKeyboardVisibilityChanged(boolean opened) {
    print("keyboard " + opened);
}

// ContentView is the root view of the layout of this activity/fragment    
contentView.getViewTreeObserver().addOnGlobalLayoutListener(
    new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {

        Rect r = new Rect();
        contentView.getWindowVisibleDisplayFrame(r);
        int screenHeight = contentView.getRootView().getHeight();

        // r.bottom is the position above soft keypad or device button.
        // if keypad is shown, the r.bottom is smaller than that before.
        int keypadHeight = screenHeight - r.bottom;

        Log.d(TAG, "keypadHeight = " + keypadHeight);

        if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
            // keyboard is opened
            if (!isKeyboardShowing) {
                isKeyboardShowing = true
                onKeyboardVisibilityChanged(true)
            }
        }
        else {
            // keyboard is closed
            if (isKeyboardShowing) {
                isKeyboardShowing = false
                onKeyboardVisibilityChanged(false)
            }
        }
    }
});


1
Помістіть це в клас утиліти та передайте активність - тепер корисна у всьому додатку.
Джастін

2
А де contentViewзадекларовано?
Код-учень

1
@ Code-Apprentice У діяльності / фрагменті ви хочете реагувати на зміни м'якої клавіатури. ContentView - це кореневий вигляд макета цієї активності / фрагмента.
airowe

1
Працював для мене на Android 6 та 7.
V.March

71

спробуйте це:

InputMethodManager imm = (InputMethodManager) getActivity()
            .getSystemService(Context.INPUT_METHOD_SERVICE);

    if (imm.isAcceptingText()) {
        writeToLog("Software Keyboard was shown");
    } else {
        writeToLog("Software Keyboard was not shown");
    }

9
Це не працює для мене. Клавіатура, що відображається гілкою, спрацьовує навіть у тому випадку, коли клавіатура ніколи не була показана або показана, а потім закрита.
Пітер Айтай

30
воно завжди повертає правду.
shivang Trivedi

1
Так, це завжди повертається правдою.
Леон Пелтьє,

Неправильно. Це завжди повертається правдою
Gaurav Arora

178
Це жалюгідне , що Android рамка не вистачає, і що ще гірше, непослідовне в цьому відношенні. Це повинно бути надпростим.
Vicky Chijwani

57

Я створив простий клас, який можна використовувати для цього: https://github.com/ravindu1024/android-keyboardlistener . Просто скопіюйте його у свій проект та використовуйте наступне:

KeyboardUtils.addKeyboardToggleListener(this, new KeyboardUtils.SoftKeyboardToggleListener()
{
    @Override
    public void onToggleSoftKeyboard(boolean isVisible)
    {
        Log.d("keyboard", "keyboard visible: "+isVisible);
    }
});

Де в екземплярі коду я повинен це ставити? Я ставлю це до активності, проте він не виявляє жодної появи або зникнення клавіатури.
Том

Ну, ви можете розмістити його в будь-якому місці своєї діяльності. Просто поставте його в метод onCreate () після виклику setContentView (), і вам слід отримувати зворотні дзвінки. Btw, на якому пристрої ви його приміряєте?
ravindu1024

@MaulikDodia Я перевірив, і це чудово працює у фрагментах. Налаштуйте його так: KeyboardUtils.addKeyboardToggleListener (getActivity (), this); і це має працювати. На якому пристрої ви його приміряєте?
ravindu1024

Я пробую на пристрої Moto-G3. @ Ravindu1024
Maulik Dodia

Дякую за цей фрагмент, у мене є одне запитання про те, що цей код необхідний для видалення слухача?
Пратік Бутані

28

Дуже легко

1. Введіть ідентифікатор у свій кореневий вигляд

rootView- це лише подання, що вказує на мій кореневий вигляд у цьому випадку relative layout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/addresses_confirm_root_view"
                android:background="@color/WHITE_CLR">

2. Ініціалізуйте свій кореневий вигляд у своїй діяльності:

RelativeLayout rootView = (RelativeLayout) findViewById(R.id.addresses_confirm_root_view);

3. Визначте, чи клавіатуру відкрити чи закрити за допомогою getViewTreeObserver()

    rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                int heightDiff = rootView.getRootView().getHeight() - rootView.getHeight();

                if (heightDiff > 100) { 
                    Log.e("MyActivity", "keyboard opened");
                } else { 
                    Log.e("MyActivity", "keyboard closed");
                }
            }
        });

15
ей, приятелю, скажіть, будь ласка, звідки ця чарівна 100? Чому б не 101 чи 99? Спасибі
Каролі

@Karoly я думаю, що це може бути і 1. Неважливо. Тільки це повинно бути менше реальної довжини клавіатури
Влад

@Karoly в основному він порівнює розмір вікна з розміром виду кореня вашої діяльності. зовнішній вигляд м’якої клавіатури не впливає на розмір головного вікна. тож ви все ще можете знизити значення 100.
mr5,

Магічне число залежить від вашого макета верхньої панелі серед іншого. Тож це відносно вашого додатка. В одному моєму я використав 400.
Мортен

пам’ятайте, що onGlobalLayout називається кожним кадром, тому переконайтеся, що ви там не робите важких речей.
Акшай Гаонкар

8

Я використовував це як основу: http://www.ninthavenue.com.au/how-to-check-if-the-software-keyboard-is-shown-in-android

/**
* To capture the result of IMM hide/show soft keyboard
*/
public class IMMResult extends ResultReceiver {
     public int result = -1;
     public IMMResult() {
         super(null);
}

@Override 
public void onReceiveResult(int r, Bundle data) {
    result = r;
}

// poll result value for up to 500 milliseconds
public int getResult() {
    try {
        int sleep = 0;
        while (result == -1 && sleep < 500) {
            Thread.sleep(100);
            sleep += 100;
        }
    } catch (InterruptedException e) {
        Log.e("IMMResult", e.getMessage());
    }
    return result;
}
}

Потім написав цей метод:

public boolean isSoftKeyboardShown(InputMethodManager imm, View v) {

    IMMResult result = new IMMResult();
    int res;

    imm.showSoftInput(v, 0, result);

    // if keyboard doesn't change, handle the keypress
    res = result.getResult();
    if (res == InputMethodManager.RESULT_UNCHANGED_SHOWN ||
            res == InputMethodManager.RESULT_UNCHANGED_HIDDEN) {

        return true;
    }
    else
        return false;

}

Потім ви можете використовувати це для тестування всіх полів (EditText, AutoCompleteTextView тощо), які, можливо, відкрили програмну клавіатуру:

    InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
    if(isSoftKeyboardShown(imm, editText1) | isSoftKeyboardShown(imm, autocompletetextview1))
        //close the softkeyboard
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

Адже не ідеальне рішення, але це робить роботу.


2
Це працює. Якщо ви реалізуєте як singelton, ви можете звернутися до всіх редакційних текстів про зміну фокусу і мати одного глобального слухача клавіатури
Rarw

@depperm getActivity () специфічний для фрагментів, спробуйте замість цього YourActivityName.this. Дивіться також: stackoverflow.com/questions/14480129/…
Крістофер Хакл


6

Ви можете посилатися на цю відповідь - https://stackoverflow.com/a/24105062/3629912

Це працювало для мене щоразу.

adb shell dumpsys window InputMethod | grep "mHasSurface"

Якщо ви побачите програмну клавіатуру, вона повернеться правдою


10
Це корисно лише під час розробки - не рішення для використання в додатку. (У користувачів не буде запущено adb.)
ToolmakerSteve

5

Тож після довгого часу розмовляючи з AccessibilityServices, вставками вікон, виявленням висоти екрана тощо, я думаю, що я знайшов спосіб це зробити.

Відмова від відповідальності: він використовує прихований метод в Android, це означає, що він може не бути послідовним. Однак, на моєму тестуванні, здається, це працює.

Метод - InputMethodManager # getInputMethodWindowVisibleHeight () , і існує з Lollipop (5.0).

Виклик, який повертає висоту поточної клавіатури в пікселях. Теоретично клавіатура не повинна бути висотою 0 пікселів, тому я зробив просту перевірку висоти (у Котліні):

val imm by lazy { context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager }
if (imm.inputMethodWindowVisibleHeight > 0) {
    //keyboard is shown
else {
    //keyboard is hidden
}

Я використовую Android Hidden API, щоб уникнути рефлексії, коли я називаю приховані методи (я роблю це багато для програм, які я розробляю, в основному це програми хакі / тюнерів), але це має бути можливо і з відображенням:

val imm by lazy { context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager }
val windowHeightMethod = InputMethodManager::class.java.getMethod("getInputMethodWindowVisibleHeight")
val height = windowHeightMethod.invoke(imm) as Int
//use the height val in your logic

Дивовижне використання роздумів
kaustubhpatange

4

Це було набагато менш складним для вимог, які мені були потрібні. Сподіваюсь, це може допомогти:

Про MainActivity:

public void dismissKeyboard(){
    InputMethodManager imm =(InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(mSearchBox.getWindowToken(), 0);
    mKeyboardStatus = false;
}

public void showKeyboard(){
    InputMethodManager imm =(InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
    mKeyboardStatus = true;
}

private boolean isKeyboardActive(){
    return mKeyboardStatus;
}

Первісне бульове значення для mKeyboardStatus за замовчуванням буде ініціалізовано на значення false .

Потім перевірте значення наступним чином та виконайте дію, якщо необхідно:

 mSearchBox.requestFocus();
    if(!isKeyboardActive()){
        showKeyboard();
    }else{
        dismissKeyboard();
    }

4

Це має спрацювати, якщо вам потрібно перевірити стан клавіатури:

fun Activity.isKeyboardOpened(): Boolean {
    val r = Rect()

    val activityRoot = getActivityRoot()
    val visibleThreshold = dip(UiUtils.KEYBOARD_VISIBLE_THRESHOLD_DP)

    activityRoot.getWindowVisibleDisplayFrame(r)

    val heightDiff = activityRoot.rootView.height - r.height()

    return heightDiff > visibleThreshold;
}

fun Activity.getActivityRoot(): View {
    return (findViewById<ViewGroup>(android.R.id.content)).getChildAt(0);
}

Де UiUtils.KEYBOARD_VISIBLE_THRESHOLD_DP= 100 і dip () - anko func, який перетворює dpToPx:

fun dip(value: Int): Int {
    return (value * Resources.getSystem().displayMetrics.density).toInt()
}

3

Я зробив це, встановивши GlobalLayoutListener так:

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
        new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                int heightView = activityRootView.getHeight();
                int widthView = activityRootView.getWidth();
                if (1.0 * widthView / heightView > 3) {
                    //Make changes for Keyboard not visible
                } else {
                    //Make changes for keyboard visible
                }
            }
        });

Це буде називатися ДУЖЕ часто
Денис Княжев

У яких випадках це буде відрізнятися від відповіді @BrownsooHan? Я шукаю спосіб відображення програми, яка перетягує інші програми, щоб вийти з шляху клавіатури.
Еван Ланглуа

Його відповідь принципово така ж, як і моя, тільки я зробив свою скаргу за багато місяців до його, і він має більше прихильників.
PearsonArtPhoto

3

Спробуйте цей код, він справді працює, якщо KeyboardShown відображається, тоді ця функція повертає справжнє значення ....

private final String TAG = "TextEditor";
private TextView mTextEditor;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_editor);
    mTextEditor = (TextView) findViewById(R.id.text_editor);
    mTextEditor.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            isKeyboardShown(mTextEditor.getRootView());
        }
    });
}

private boolean isKeyboardShown(View rootView) {
    /* 128dp = 32dp * 4, minimum button height 32dp and generic 4 rows soft keyboard */
    final int SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD = 128;

    Rect r = new Rect();
    rootView.getWindowVisibleDisplayFrame(r);
    DisplayMetrics dm = rootView.getResources().getDisplayMetrics();
    /* heightDiff = rootView height - status bar height (r.top) - visible frame height (r.bottom - r.top) */
    int heightDiff = rootView.getBottom() - r.bottom;
    /* Threshold size: dp to pixels, multiply with display density */
    boolean isKeyboardShown = heightDiff > SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD * dm.density;

    Log.d(TAG, "isKeyboardShown ? " + isKeyboardShown + ", heightDiff:" + heightDiff + ", density:" + dm.density
            + "root view height:" + rootView.getHeight() + ", rect:" + r);

    return isKeyboardShown;
}

Програма ISKeyboardShown продовжує телефонувати, коли її не відображається.
Mandeep Singh

2

У моєму випадку я мав лише одного EditTextкерувати у своєму макеті, тому я придумав це рішення. Це добре працює, в основному це звичай, EditTextякий слухає фокус і передає локальну трансляцію, якщо фокус змінюється або якщо натискається кнопка "назад / зроблено". Для роботи вам потрібно розмістити манекен Viewу вашому макеті android:focusable="true"і android:focusableInTouchMode="true"тому, що коли ви телефонуєте, clearFocus()фокус буде переведений на перший фокусується вид. Приклад виду манекена:

<View
android:layout_width="1dp"
android:layout_height="1dp"
android:focusable="true"
android:focusableInTouchMode="true"/>

Додаткова інформація

Рішення, яке виявляє різницю в зміні компонувань, працює не дуже добре, оскільки це сильно залежить від щільності екрана, оскільки 100px може бути багато на певному пристрої, і нічого в деяких інших ви не можете отримати помилкові позитиви. Також різні постачальники мають різні клавіатури.


1

В Android ви можете виявити через оболонку ADB. Я написав і використовую цей метод:

{
        JSch jsch = new JSch();
        try {
            Session session = jsch.getSession("<userName>", "<IP>", 22);
            session.setPassword("<Password>");
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.connect();

            ChannelExec channel = (ChannelExec)session.openChannel("exec");
            BufferedReader in = new BufferedReader(new    
            InputStreamReader(channel.getInputStream()));
            channel.setCommand("C:/Android/android-sdk/platform-tools/adb shell dumpsys window 
            InputMethod | findstr \"mHasSurface\"");
            channel.connect();

            String msg = null;
            String msg2 = " mHasSurface=true";

            while ((msg = in.readLine()) != null) {
                Boolean isContain = msg.contains(msg2);
                log.info(isContain);
                if (isContain){
                    log.info("Hiding keyboard...");
                    driver.hideKeyboard();
                }
                else {
                    log.info("No need to hide keyboard.");
                }
            }

            channel.disconnect();
            session.disconnect();

        } catch (JSchException | IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

1
Чи можете ви покращити цю відповідь на конкретнішому прикладі з усім імпортом та робочим прикладом?
User3

1
final View activityRootView = findViewById(R.id.rootlayout);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {

            Rect r = new Rect();
            activityRootView.getWindowVisibleDisplayFrame(r);

            int screenHeight = activityRootView.getRootView().getHeight();
            Log.e("screenHeight", String.valueOf(screenHeight));
            int heightDiff = screenHeight - (r.bottom - r.top);
            Log.e("heightDiff", String.valueOf(heightDiff));
            boolean visible = heightDiff > screenHeight / 3;
            Log.e("visible", String.valueOf(visible));
            if (visible) {
                Toast.makeText(LabRegister.this, "I am here 1", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(LabRegister.this, "I am here 2", Toast.LENGTH_SHORT).show();
            }
        }
});

1

Відповідь @iWantScala чудова, але для мене робота не
rootView.getRootView().getHeight()завжди однакова

один із способів - визначити дві вари

private int maxRootViewHeight = 0;
private int currentRootViewHeight = 0;

додати глобального слухача

rootView.getViewTreeObserver()
    .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            currentRootViewHeight = rootView.getHeight();
            if (currentRootViewHeight > maxRootViewHeight) {
                maxRootViewHeight = currentRootViewHeight;
            }
        }
    });

потім перевірити

if (currentRootViewHeight >= maxRootViewHeight) {
    // Keyboard is hidden
} else {
    // Keyboard is shown
}

працює чудово


1

Зрештою, існує прямий шлях від Android R на базі Котліна.

 val imeInsets = view.rootWindowInsets.getInsets(Type.ime()) 
    if (imeInsets.isVisible) { 
     //Ime is visible
     //Lets move our view by the height of the IME
     view.translationX = imeInsets.bottom }

0

У мене була подібна проблема. Мені потрібно було реагувати на кнопку Enter на екрані (яка приховувала клавіатуру). У цьому випадку ви можете підписатися на OnEditorAction текстового перегляду, за допомогою якого клавіатура була відкрита - якщо у вас є кілька редагованих полів, тоді підпишіться на всі вони.

У своїй діяльності ви маєте повний контроль над клавіатурою, тому в жодному разі ви не зіткнетеся з проблемою, відкрита чи ні клавіатура, якщо ви слухаєте всі події відкриття та закриття.


Не працює для мене. Я отримую лише ключ Enter у OnEditorAction.
3c71

0

Існує прямий метод, щоб дізнатися це. І це не потребує змін компоновки.
Таким чином, він працює і в режимі повноекранного режиму.
Але, на жаль, це працює не на всіх пристроях. Тож вам доведеться перевірити це на своїх пристроях.

Хитрість полягає в тому, що ви намагаєтесь сховати або показати м'яку клавіатуру і зафіксувати результат цієї спроби.
Якщо вона працює правильно, клавіатура насправді не відображається і не приховується. Ми просто просимо державу.

Щоб бути в курсі останніх, ви просто повторіть цю операцію, наприклад, кожні 200 мілісекунд, використовуючи обробник.

Реалізація нижче - лише одна перевірка.
Якщо ви робите кілька перевірок, вам слід включити всі (_keyboardVisible) тести.

public interface OnKeyboardShowHide
{
    void    onShowKeyboard( Object param );
    void    onHideKeyboard( Object param );
}

private static Handler      _keyboardHandler    = new Handler();
private boolean             _keyboardVisible    = false;
private OnKeyboardShowHide  _keyboardCallback;
private Object              _keyboardCallbackParam;

public void start( OnKeyboardShowHide callback, Object callbackParam )
{
    _keyboardCallback      = callback;
    _keyboardCallbackParam = callbackParam;
    //
    View view = getCurrentFocus();
    if (view != null)
    {
        InputMethodManager imm = (InputMethodManager) getSystemService( Activity.INPUT_METHOD_SERVICE );
        imm.hideSoftInputFromWindow( view.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY, _keyboardResultReceiver );
        imm.showSoftInput( view, InputMethodManager.SHOW_IMPLICIT, _keyboardResultReceiver );
    }
    else // if (_keyboardVisible)
    {
        _keyboardVisible = false;
        _keyboardCallback.onHideKeyboard( _keyboardCallbackParam );
    }
}

private ResultReceiver      _keyboardResultReceiver = new ResultReceiver( _keyboardHandler )
{
    @Override
    protected void onReceiveResult( int resultCode, Bundle resultData )
    {
        switch (resultCode)
        {
            case InputMethodManager.RESULT_SHOWN :
            case InputMethodManager.RESULT_UNCHANGED_SHOWN :
                // if (!_keyboardVisible)
                {
                    _keyboardVisible = true;
                    _keyboardCallback.onShowKeyboard( _keyboardCallbackParam );
                }
                break;
            case InputMethodManager.RESULT_HIDDEN :
            case InputMethodManager.RESULT_UNCHANGED_HIDDEN :
                // if (_keyboardVisible)
                {
                    _keyboardVisible = false;
                    _keyboardCallback.onHideKeyboard( _keyboardCallbackParam );
                }
                break;
        }
    }
};

як це називати і де?
Махді Астаней

0

Ось вирішення питання про те, чи видно програмну клавішу.

  1. Перевірте наявність службових служб у системі за допомогою ActivityManager.getRunningServices (max_count_of_services);
  2. З повернених екземплярів ActivityManager.RunningServiceInfo перевірте значення clientCount для служби м'якої клавіатури
  3. Вищезгаданий клієнтський рахунок буде збільшуватися кожного разу, відображається м'яка клавіатура. Наприклад, якщо клієнтська кількість спочатку була 1, це було б 2, коли відображається клавіатура.
  4. При звільненні з клавіатури зменшується клієнтська кількість. У цьому випадку вона скидається до 1.

Деякі популярні клавіатури мають певні ключові слова у своїх класахНазви:

  1. Google AOSP = IME
  2. Swype = IME
  3. Swiftkey = KeyboardService
  4. Fleksy = клавіатура
  5. Adaptxt = IME (KPTAdaptxtIME)
  6. Smart = клавіатура (SmartKeyboard)

Від ActivityManager.RunningServiceInfo перевірте вищезазначені шаблони в ClassNames. Також ActivityManager.RunningServiceInfo clientPackage = android, що вказує на те, що клавіатура прив'язана до системи.

Вищезгадану інформацію можна суворо поєднати, щоб дізнатись, чи видно м'яку клавіатуру.


0

Як ви, можливо, знаєте, клавіатура програмного забезпечення для Android буде видно лише тоді, коли можлива подія введення тексту. Іншими словами, клавіатура стає видимою лише тоді, коли EditText зосереджена. це означає, що ви можете дізнатися, що Клавіатура видно чи ні, використовуючи OnFocusChangeListener .

//Declare this Globally

public boolean isKeyBoardVisible = false;

//In OnCreate *[For Activity]*, OnCreateView *[For Fragment]*

text_send.setOnFocusChangeListener(new View.OnFocusChangeListener() {

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if(hasFocus)
            isKeyBoardVisible = true;
        else
            isKeyBoardVisible = false;
    }
});

Тепер ви можете використовувати змінну isKeyBoardVisible в будь-якому місці класу, щоб отримати погоду на клавіатурі "Відкрити" або "Ні". Це добре спрацювало для мене.

Примітка: Цей процес не працює, коли клавіатура відкривається програмно за допомогою InputMethodManager, оскільки це не викликає OnFocusChangeListener.


насправді не хак, не працював у вкладеному фрагменті. Не можу сказати про діяльність, як я ще не пробував цього на цьому.
antroid

0

Я перетворив відповідь у kotlin, сподіваюся, це допоможе користувачам kotlin.

private fun checkKeyboardVisibility() {
    var isKeyboardShowing = false

    binding.coordinator.viewTreeObserver.addOnGlobalLayoutListener {
        val r = Rect()
        binding.coordinator.getWindowVisibleDisplayFrame(r)
        val screenHeight = binding.coordinator.rootView.height

        // r.bottom is the position above soft keypad or device button.
        // if keypad is shown, the r.bottom is smaller than that before.
        val keypadHeight = screenHeight - r.bottom


        if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
            // keyboard is opened
            if (!isKeyboardShowing) {
                isKeyboardShowing = true

            }
        } else {
            // keyboard is closed
            if (isKeyboardShowing) {
                isKeyboardShowing = false

            }
        }
    }
}

0

Він працює з налаштовуваннямНощого прапора активності та подій життєвого циклу використовуються. Також з Котліном:

/**
 * This class uses a PopupWindow to calculate the window height when the floating keyboard is opened and closed
 *
 * @param activity The parent activity
 *  The root activity that uses this KeyboardManager
 */
class KeyboardManager(private val activity: AppCompatActivity) : PopupWindow(activity), LifecycleObserver {

    private var observerList = mutableListOf<((keyboardTop: Int) -> Unit)>()

    /** The last value of keyboardTop */
    private var keyboardTop: Int = 0

    /** The view that is used to calculate the keyboard top  */
    private val popupView: View?

    /** The parent view  */
    private var parentView: View

    var isKeyboardShown = false
        private set

    /**
     * Create transparent view which will be stretched over to the full screen
     */
    private fun createFullScreenView(): View {
        val view = LinearLayout(activity)
        view.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT)
        view.background = ColorDrawable(Color.TRANSPARENT)
        return view
    }

    init {
        this.popupView = createFullScreenView()
        contentView = popupView

        softInputMode = LayoutParams.SOFT_INPUT_ADJUST_RESIZE or LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE
        inputMethodMode = INPUT_METHOD_NEEDED

        parentView = activity.findViewById(android.R.id.content)

        width = 0
        height = LayoutParams.MATCH_PARENT

        popupView.viewTreeObserver.addOnGlobalLayoutListener {
            val rect = Rect()
            popupView.getWindowVisibleDisplayFrame(rect)

            val keyboardTop = rect.bottom
            if (this.keyboardTop != keyboardTop) {
                isKeyboardShown = keyboardTop < this.keyboardTop
                this.keyboardTop = keyboardTop
                observerList.forEach { it(keyboardTop) }
            }
        }
        activity.lifecycle.addObserver(this)
    }

    /**
     * This must be called after the onResume of the Activity or inside view.post { } .
     * PopupWindows are not allowed to be registered before the onResume has finished
     * of the Activity
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun start() {
        parentView.post {
            if (!isShowing && parentView.windowToken != null) {
                setBackgroundDrawable(ColorDrawable(0))
                showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0)
            }
        }
    }

    /**
     * This manager will not be used anymore
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun close() {
        activity.lifecycle.removeObserver(this)
        observerList.clear()
        dismiss()
    }

    /**
     * Set the keyboard top observer. The observer will be notified when the keyboard top has changed.
     * For example when the keyboard is opened or closed
     *
     * @param observer The observer to be added to this provider
     */
    fun registerKeyboardTopObserver(observer: (keyboardTop: Int) -> Unit) {
        observerList.add(observer)
    }
}

Корисний метод для збереження перегляду завжди над клавіатурою

fun KeyboardManager.updateBottomMarginIfKeyboardShown(
        view: View,
        activity: AppCompatActivity,
        // marginBottom of view when keyboard is hide
        marginBottomHideKeyboard: Int,
        // marginBottom of view when keybouard is shown
        marginBottomShowKeyboard: Int
) {
    registerKeyboardTopObserver { bottomKeyboard ->
        val bottomView = ViewUtils.getFullViewBounds(view).bottom
        val maxHeight = ScreenUtils.getFullScreenSize(activity.windowManager).y
        // Check that view is within the window size
        if (bottomView < maxHeight) {
            if (bottomKeyboard < bottomView) {
                ViewUtils.updateMargin(view, bottomMargin = bottomView - bottomKeyboard +
                        view.marginBottom + marginBottomShowKeyboard)
            } else ViewUtils.updateMargin(view, bottomMargin = marginBottomHideKeyboard)
        }
    }
}

Де отриматиFullViewBounds

fun getLocationOnScreen(view: View): Point {
    val location = IntArray(2)
    view.getLocationOnScreen(location)
    return Point(location[0], location[1])
}

fun getFullViewBounds(view: View): Rect {
     val location = getLocationOnScreen(view)
     return Rect(location.x, location.y, location.x + view.width,
            location.y + view.height)
 }

Де отриматиFullScreenSize

fun getFullScreenSize(wm: WindowManager? = null) =
            getScreenSize(wm) { getRealSize(it) }

private fun getScreenSize(wm: WindowManager? = null, block: Display.(Point) -> Unit): Point {
    val windowManager = wm ?: App.INSTANCE.getSystemService(Context.WINDOW_SERVICE)
            as WindowManager
    val point = Point()
    windowManager.defaultDisplay.block(point)
    return point
}

Де updateMargin

fun updateMargin(
        view: View,
        leftMargin: Int? = null,
        topMargin: Int? = null,
        rightMargin: Int? = null,
        bottomMargin: Int? = null
) {
    val layoutParams = view.layoutParams as ViewGroup.MarginLayoutParams
    if (leftMargin != null) layoutParams.leftMargin = leftMargin
    if (topMargin != null) layoutParams.topMargin = topMargin
    if (rightMargin != null) layoutParams.rightMargin = rightMargin
    if (bottomMargin != null) layoutParams.bottomMargin = bottomMargin
    view.layoutParams = layoutParams
}

-1

Я зробив це наступним чином, але це відповідає лише тому, що ваша мета - закрити / відкрити клавіатуру.

приклад закриття: (перевірка, чи клавіатура вже закрита, якщо ні - закриття)

imm.showSoftInput(etSearch, InputMethodManager.HIDE_IMPLICIT_ONLY, new ResultReceiver(null) {
                    @Override
                    protected void onReceiveResult(int resultCode, Bundle resultData) {
                        super.onReceiveResult(resultCode, resultData);
                        if (resultCode != InputMethodManager.RESULT_UNCHANGED_HIDDEN)
                            imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
                    }
                });

Питання пов’язане з тим, щоб дізнатися, чи відображається клавіатура чи ні
Гопал Сінгх Сірві,

-1

можливо, використовується:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    Log.d(
    getClass().getSimpleName(), 
    String.format("conf: %s", newConfig));

    if (newConfig.hardKeyboardHidden != hardKeyboardHidden) {
        onHardwareKeyboardChange(newConfig.hardKeyboardHidden);

        hardKeyboardHidden = newConfig.hardKeyboardHidden;
    }

    if (newConfig.keyboardHidden != keyboardHidden) {
        onKeyboardChange(newConfig.keyboardHidden);

        keyboardHidden = newConfig.hardKeyboardHidden;
    }

}

public static final int KEYBOARDHIDDEN_UNDEFINED = 0;
public static final int KEYBOARDHIDDEN_NO = 1;
public static final int KEYBOARDHIDDEN_YES = 2;
public static final int KEYBOARDHIDDEN_SOFT = 3;

//todo
private void onKeyboardChange(int keyboardHidden) {

}

//todo
private void onHardwareKeyboardChange(int hardKeyboardHidden) {

}

Це працюватиме лише для апаратної клавіатури, а не для програмного забезпечення
anthonymonori

-1

Я написав зразок .

Це сховище може допомогти виявити стан клавіатури без припущення, що "клавіатура повинна бути більше X частини екрану"


-1

Якщо ви підтримуєте apis для AndroidR у своєму додатку, тоді ви можете скористатися наведеним нижче методом.

In kotlin :
    var imeInsets = view.rootWindowInsets.getInsets(Type.ime()) 
    if (imeInsets.isVisible) { 
        view.translationX = imeInsets.bottom 
    }

Примітка. Це доступно лише для версій AndroidR і нижче. Для Android-версії потрібно дотримуватися деяких інших відповідей, або я для цього оновлю її.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.