Yazılım klavyesinin Android Cihaz'da görünür olup olmadığını nasıl tespit edebilirim?


249

Android'de yazılımın ("yumuşak" olarak da bilinir) klavyenin ekranda görünüp görünmediğini tespit etmenin bir yolu var mı?



1
Bir ile yapılabilir - Ne (3. taraf klavye yüklüyse) Klavye "değişim klavye" diyen bir sistem bildirim yoktur açıkken gibi küresel bildirimleri kontrol etmektir bazı durumlarda bu bir çözüm olabilir NotificationListenerService
Prof

2
neredeyse 8 yıl ve hala sağlam bir çözüm yok, oh bir tanıştırırlarsa, onun için API> 30 olacak, bu yüzden
boş ver

Yanıtlar:



276

Bu benim için çalışıyor. Belki de bu her zaman tüm versiyonlar için en iyi yoldur .

OnGlobalLayout yöntemi birçok kez çağırdığı için klavye görünürlüğü özelliğinin yapılması ve bu değişikliklerin gecikmeli olarak gözlemlenmesi etkili olacaktır. Ayrıca cihazın dönüşünü kontrol etmek iyidir ve windowSoftInputModedeğildir 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)
            }
        }
    }
});

3
İşte çalışan bir öz
Faruk Toptas

1
Bunu bir utils sınıfına koyun ve aktiviteye geçin - şimdi tüm uygulamada yararlıdır.
Justin

2
Nerede contentViewilan edilir?
Code-Apprentice

1
@ Kod-Çırak Etkinlik / parçada yumuşak klavye değişikliklerine yanıt vermek istiyorsunuz. ContentView, bu etkinliğin / parçanın düzeninin kök görünümüdür.
airowe

1
Android 6 ve 7'de benim için çalıştı.
V.Mart

71

bunu dene:

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
Bu benim için işe yaramıyor. Gösterilen klavye, örneğin klavye hiç gösterilmediğinde veya gösterilip kapatıldığında bile tetiklenir.
Peter Ajtai

30
her zaman doğru olur.
shivang Trivedi

1
Evet, her zaman doğrudur.
Léon Pelletier

Yanlış. Bu her zaman doğru olur
Gaurav Arora

178
Öyle acıklı Android çerçeve eksik olduğunu ve daha da kötüsü, tutarsız bu konuda. Bu çok basit olmalı.
Vicky Chijwani

57

Bunun için kullanılabilecek basit bir sınıf oluşturdum: https://github.com/ravindu1024/android-keyboardlistener . Sadece projenize kopyalayın ve aşağıdaki gibi kullanın:

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

Exaclty kodunda nereye koymak zorunda? Bunu bir etkinliğe koydum, ancak herhangi bir klavye görünümünü veya kaybolmasını algılamıyor.
toom

Bunu, faaliyetinizin herhangi bir yerine koyabilirsiniz. Sadece setContentView () çağrısından sonra onCreate () yöntemine koyun ve geri aramalar almalısınız. Btw, hangi cihazı deniyorsun?
ravindu1024

@MaulikDodia Kontrol ettim ve parçalar halinde iyi çalışıyor. Bunu şu şekilde ayarlayın: KeyboardUtils.addKeyboardToggleListener (getActivity (), this); ve işe yaramalı. Hangi cihazı deniyorsun?
ravindu1024

Moto-G3 cihazında deniyorum. @ Ravindu1024
Maulik Dodia

Bu pasaj için teşekkürler, dinleyiciyi kaldırmak için bu kodun gerekli olduğu bir sorum var?
Pratik Butani

28

Çok kolay

1. Kimliği kök görünümünüze yerleştirin

rootViewbu durumda yalnızca kök görünümüme işaret eden bir görünümdür 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. Faaliyetinizde kök görünümünüzü başlatın:

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

3. Klavyenin aşağıdakileri kullanarak açılıp kapanmadığını tespit edin 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
hey dostum, lütfen bana bu büyünün 100 nereden geldiğini söyleyebilir misin? Neden 101 veya 99 olmasın? Teşekkürler
Karoly

@Karoly bence bu olabilir ve 1. Önemli değil. Sadece bu gerçek klavyenin uzunluğundan daha az olmalıdır
Vlad

@Karoly temel olarak, pencere boyutunu etkinliğinizin kök görünüm boyutuyla karşılaştırıyor. yazılım klavyesinin görünümü ana pencerenin boyutunu etkilemez. böylece 100 değerini hala düşürebilirsiniz.
mr5

Sihirli sayı, diğer şeylerin yanı sıra üst çubuk düzeninize bağlıdır. Yani uygulamanıza görecelidir. İçimde 400 tane kullandım.
Morten Holmgaard

onGlobalLayout'un her kareye çağrıldığını unutmayın, bu nedenle orada ağır şeyler yapmadığınızdan emin olun.
Akshay Gaonkar

8

Bunu temel olarak kullandım: 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;
}
}

Sonra bu yöntemi yazdı:

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;

}

Ardından, yazılım klavyesini açmış olabilecek tüm alanları (EditText, AutoCompleteTextView, vb.) Test etmek için kullanabilirsiniz:

    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);

Ek olarak ideal bir çözüm değil, ama işi hallediyor.


2
Bu çalışıyor. Singelton olarak uygularsanız, odak değişikliğindeki tüm düzenleme metinlerine başvurabilir ve bir global klavye dinleyicisine sahip olabilirsiniz
Rarw

@depperm getActivity (), Parçalara özeldir, bunun yerine YourActivityName.this komutunu deneyin. Ayrıca bakınız: stackoverflow.com/questions/14480129/…
Christopher Hackl


6

Bu cevaba başvurabilirsiniz - https://stackoverflow.com/a/24105062/3629912

Her zaman benim için çalıştı.

adb shell dumpsys window InputMethod | grep "mHasSurface"

Yazılım klavyesi görünürse, doğru dönecektir.


10
Bu sadece geliştirme sırasında kullanışlıdır - bir uygulamada kullanım için bir çözüm değildir. (Kullanıcılar adb yayınlamayacak.)
ToolmakerSteve

5

AccessibilityServices, pencere iç metinleri, ekran yükseklik algılama vb.

Feragatname: Android'de gizli bir yöntem kullanır, yani tutarlı olmayabilir. Ancak, testlerimde işe yarıyor gibi görünüyor.

Yöntem, InputMethodManager # getInputMethodWindowVisibleHeight () yöntemidir. ve Lollipop'tan (5.0) beri vardır.

Geçerli klavyenin yüksekliğini piksel cinsinden döndüren arama. Teorik olarak, bir klavye 0 piksel yüksekliğinde olmamalıdır, bu yüzden basit bir yükseklik kontrolü yaptım (Kotlin'de):

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

Gizli yöntemleri çağırdığımda yansımayı önlemek için Android Gizli API'sını kullanıyorum (çoğunlukla hacky / tuner uygulamaları olan geliştirdiğim uygulamalar için çok şey yapıyorum), ancak bu yansıma ile de mümkün olmalı:

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

Yansımaları Şaşırtıcı Kullanımı
Kaustubhpatange

4

Bu, ihtiyaç duyduğum gereksinimler için çok daha az karmaşıktı. Umarım bu yardımcı olabilir:

MainActivity'de:

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 için varsayılan temel boolean değeri false olarak başlatılır .

Ardından değeri aşağıdaki gibi kontrol edin ve gerekirse bir işlem gerçekleştirin:

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

4

Klavye durumunu kontrol etmeniz gerekiyorsa, bunun çalışması gerekir:

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);
}

Burada UiUtils.KEYBOARD_VISIBLE_THRESHOLD_DP= 100 ve dip (), dpToPx'i dönüştüren bir anko fonktur:

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

3

Bunu aşağıdaki gibi bir GlobalLayoutListener ayarlayarak yaptım:

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
                }
            }
        });

Buna ÇOK sık sık denir
Denis Kniazhev

Hangi durumlarda bu @BrownsooHan cevabından farklı olacaktır? Klavyenin dışına çıkmak için diğer uygulamaları çeken bir uygulamanın gösterdiği bir yol arıyorum.
Evan Langlois

Cevabı temelde benimkiyle aynı, sadece benimkini aylar önce yaptım ve daha fazla oyu var.
PearsonArtPhoto

3

KeyboardShown gösteriliyorsa gerçekten işe yarayan bu kodu deneyin, ardından bu işlev gerçek değeri döndürür.

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;
}

İsKeyboardShown gösterilmediğinde kendini çağırmaya devam eder.
Mandeep Singh

2

Benim durumumda EditTextbenim düzeni yönetmek için sadece bir tane vardı , bu yüzden bu çözüm beyaz geldi . İyi çalışır, temel EditTextolarak odak dinleyen ve odak değişirse veya geri / tamam düğmesine basıldığında yerel bir yayın gönderen bir gelenektir . Çalışmak Viewiçin mizanpajınıza bir kukla yerleştirmeniz gerekir android:focusable="true"ve android:focusableInTouchMode="true"çünkü aradığınızda clearFocus()odak ilk odaklanabilir görünüme yeniden atanır. Kukla görüntü örneği:

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

Ek bilgiler

Düzen değişikliklerindeki farkı tespit eden çözüm çok iyi çalışmıyor çünkü ekran yoğunluğuna güçlü bir şekilde bağlı, çünkü 100 piksel belirli bir cihazda çok fazla olabilir ve bazılarında hiçbir şey yanlış pozitifler alamazsınız. Ayrıca farklı satıcıların farklı klavyeleri vardır.


1

Android'de ADB kabuğu aracılığıyla tespit edebilirsiniz. Bu yöntemi yazdım ve kullandım:

{
        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
Bu cevabı daha somut bir örnekle, tüm ithalatlarla ve çalışan bir örnekle geliştirebilir misiniz?
Kullanıcı3

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

@İWantScala'nın cevabı harika ama benim için çalışmıyor
rootView.getRootView().getHeight() her zaman aynı değere sahip

bir yol iki değişken tanımlamaktır

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

küresel dinleyici ekle

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

sonra kontrol et

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

iyi çalışıyor


1

Sonunda Kotlin'e dayanan Android R'den başlayan doğrudan bir yol var.

 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

Benzer bir sorun yaşadım. Ekrandaki Enter düğmesine (klavyeyi gizleyen) tepki göstermem gerekiyordu. Bu durumda, klavyenin açık olduğu OnEditorAction metin görünümüne abone olabilirsiniz - birden fazla düzenlenebilir kutunuz varsa, hepsine abone olun.

Etkinliğinizde klavyenin tam kontrolü sizdedir, bu nedenle tüm açılış ve kapanış olaylarını dinlerseniz hiçbir noktada klavyenin açılıp açılmadığıyla karşılaşmazsınız.


Benim için çalışmıyor. Yalnızca OnEditorAction'da Enter tuşunu alıyorum.
3c71

0

Bunu bulmak için doğrudan bir yöntem var. Ayrıca, düzen değişiklikleri gerektirmez.
Böylece sürükleyici tam ekran modunda da çalışır.
Ancak, ne yazık ki, tüm cihazlarda çalışmaz. Bu yüzden cihaz (lar) ınızla test etmeniz gerekir.

Hile, yumuşak klavyeyi gizlemeye veya göstermeye çalışmanız ve bu denemenin sonucunu yakalamanızdır.
Doğru çalışıyorsa, klavye gerçekten gösterilmez veya gizlenmez. Sadece devleti istiyoruz.

Güncel kalmak için bir Handler kullanarak bu işlemi, örneğin her 200 milisaniyede bir tekrarlamanız yeterlidir.

Aşağıdaki uygulama sadece tek bir kontrol yapar.
Birden fazla kontrol yaparsanız, tüm (_keyboardVisible) testlerini etkinleştirmelisiniz.

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;
        }
    }
};

nasıl ve nerede?
Mehdi Astanei

0

Yazılım klavyesinin görünür olup olmadığını öğrenmek için bir geçici çözüm.

  1. ActivityManager.getRunningServices (max_count_of_services) kullanarak sistemde çalışan hizmet olup olmadığını kontrol edin;
  2. Döndürülen ActivityManager.RunningServiceInfo örneklerinden clientCount öğesini kontrol edin yumuşak klavye hizmeti için değerini .
  3. Yukarıda belirtilen clientCount her seferinde artacaktır, yazılım klavyesi gösterilir. Örneğin, clientCount başlangıçta 1 olsaydı, klavye gösterildiğinde 2 olurdu.
  4. Klavye işten çıkarıldığında, clientCount azaltılır. Bu durumda, 1'e sıfırlar.

Popüler klavyelerin bazılarının sınıflarında belirli anahtar kelimeler vardır

  1. Google AOSP = IME
  2. Swype = IME
  3. Swiftkey = KeyboardService
  4. Fleksy = klavye
  5. Adaptxt = IME (KPTAdaptxtIME)
  6. Smart = Klavye (SmartKeyboard)

ActivityManager.RunningServiceInfo öğesinden, ClassNames içinde yukarıdaki kalıpları kontrol edin. Ayrıca, ActivityManager.RunningServiceInfo'nun clientPackage klavyenin sisteme bağlı olduğunu gösteren = android.

Yukarıda belirtilen bilgiler, yazılım klavyesinin görünüp görünmediğini bulmak için katı bir şekilde birleştirilebilir.


0

Bildiğiniz gibi android Yazılım klavyesi yalnızca yazarak olası bir olay olduğunda görünür olacaktır. Başka bir deyişle, Klavye yalnızca EditText odaklandığında görünür hale gelir. Bu, OnFocusChangeListener'ı kullanarak Klavyenin görünür olup olmadığını havaya çıkarabileceğiniz anlamına gelir .

//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;
    }
});

Artık isKeyBoardVisible'ı kullanabilirsiniz klavyenin Açık veya Değil olduğu hava değişkenini sınıfın herhangi bir yerinde . Benim için iyi çalıştı.

Not: Bu işlem Klavye, InputFethodManager kullanılarak programlı olarak açıldığında çalışmaz, çünkü bu OnFocusChangeListener'ı çağırmaz.


gerçekten bir kesmek değil, iç içe bir parça durumda işe yaramadı. Henüz bu konuda deneyin vermedi gibi faaliyetleri üzerinde söyleyemeyiz.
Antroid

0

Cevabı kotlin'e çevirdim, umarım bu kotlin kullanıcılarına yardımcı olur.

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

Hiçbir etkinlik bayrağı ve yaşam döngüsü olayları kullanılmaz. Ayrıca Kotlin ile:

/**
 * 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)
    }
}

Görünümü her zaman klavyenin üstünde tutmak için kullanışlı yöntem

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)
        }
    }
}

GetFullViewBounds nerede

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)
 }

GetFullScreenSize nerede

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
}

Güncelleme nerede

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

Bunu şu şekilde yaptım, ancak sadece amacınız tuş takımını kapatmak / açmaksa yeniden alakalı.

close example: (klavyenin kapalı olup olmadığını kontrol etmek, eğer değilse - kapanış)

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);
                    }
                });

Soru, klavyenin gösterilip gösterilmediğini
bulmakla ilgiliydi

-1

a aşağıdakileri kullanıyor olabilir:

@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) {

}

Bu sadece donanım klavyesi için çalışacak, o bir yazılım değil
anthonymonori


-1

Uygulamanızda AndroidR için apis'i destekliyorsanız aşağıdaki yöntemi kullanabilirsiniz.

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

Not: Bu sadece AndroidR için kullanılabilir ve android sürümünün diğer cevaplardan bazılarını takip etmesi gerekir veya bunun için güncelleyeceğim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.