Bagaimana cara mendeteksi apakah keyboard perangkat lunak terlihat di Perangkat Android atau tidak?

249

Apakah ada cara di Android untuk mendeteksi apakah perangkat lunak (alias "lunak") keyboard terlihat di layar?

andreea
sumber
1
apa yang bisa menjadi solusi untuk ini dalam kasus-kasus tertentu (jika keyboard pihak ke-3 diinstal) adalah untuk memeriksa notifikasi global seperti ketika keyboard terbuka ada pemberitahuan sistem yang mengatakan "ganti keyboard" - dapat dilakukan dengan NotificationListenerService
Prof
2
hampir 8 tahun dan masih belum ada solusi yang solid, oh jika mereka memperkenalkan satu, itu akan menjadi untuk API> 30 pula jadi tidak apa-apa ...
M.kazem Akhgary
Kemungkinan duplikat Android: Deteksi softkeyboard open
AbdelHady

Jawaban:

276

Ini bekerja untuk saya. Mungkin ini selalu merupakan cara terbaik untuk semua versi .

Akan lebih efektif untuk membuat properti visibilitas keyboard dan mengamati perubahan ini tertunda karena metode onGlobalLayout memanggil berkali-kali. Juga baik untuk memeriksa rotasi perangkat dan windowSoftInputModetidak 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)
            }
        }
    }
});
Brownsoo Han
sumber
3
Berikut adalah inti yang berfungsi: gist.github.com/faruktoptas/e9778e1f718214938b00c2dcd2bed109
Faruk Toptas
1
Letakkan ini di kelas utils dan lulus dalam aktivitas - sekarang berguna di seluruh aplikasi.
Justin
2
Dan di mana contentViewdinyatakan?
Code-Apprentice
1
@ Code-Apprentice Dalam aktivitas / fragmen yang Anda cari merespons perubahan keyboard lunak. ContentView adalah tampilan root dari tata letak aktivitas / fragmen ini.
airowe
1
Bekerja untuk saya di Android 6 dan 7.
V.March
71

coba ini:

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

    if (imm.isAcceptingText()) {
        writeToLog("Software Keyboard was shown");
    } else {
        writeToLog("Software Keyboard was not shown");
    }
IHeartAndroid
sumber
9
Ini tidak bekerja untuk saya. Cabang keyboard yang diperlihatkan memicu bahkan ketika keyboard tidak pernah ditampilkan atau ditampilkan dan kemudian ditutup.
Peter Ajtai
30
selalu kembali benar.
shivang Trivedi
1
Ya, itu selalu kembali benar.
Léon Pelletier
Salah. Ini selalu mengembalikan true
Gaurav Arora
178
Sangat menyedihkan bahwa kerangka Android kurang, dan lebih buruk, tidak konsisten dalam hal ini. Ini seharusnya super sederhana.
Vicky Chijwani
57

Saya membuat kelas sederhana yang dapat digunakan untuk ini: https://github.com/ravindu1024/android-keyboardlistener . Cukup salin ke proyek Anda dan gunakan sebagai berikut:

KeyboardUtils.addKeyboardToggleListener(this, new KeyboardUtils.SoftKeyboardToggleListener()
{
    @Override
    public void onToggleSoftKeyboard(boolean isVisible)
    {
        Log.d("keyboard", "keyboard visible: "+isVisible);
    }
});
ravindu1024
sumber
Di mana dalam kode exaclty saya harus meletakkan ini? Saya memasukkan ini ke dalam suatu kegiatan, namun, ia tidak mendeteksi tampilan atau hilangnya keyboard.
toom
Nah, Anda bisa meletakkannya di mana saja di dalam aktivitas Anda. Masukkan saja ke dalam metode onCreate () setelah panggilan setContentView () dan Anda akan mendapatkan panggilan balik. Btw, perangkat apa yang Anda coba?
ravindu1024
@ MaulikDodia saya memeriksa dan berfungsi dengan baik dalam fragmen. Atur seperti ini: KeyboardUtils.addKeyboardToggleListener (getActivity (), ini); dan itu harus bekerja. Perangkat apa yang Anda coba?
ravindu1024
Saya sedang mencoba perangkat Moto-G3. @ Ravindu1024
Maulik Dodia
Terima kasih untuk cuplikan ini, saya punya satu pertanyaan apakah kode ini diperlukan untuk menghapus pendengar?
Pratik Butani
28

Sangat mudah

1. Letakkan id di tampilan root Anda

rootViewhanyalah tampilan yang menunjuk ke tampilan root saya dalam hal ini 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. Inisialisasi tampilan root Anda di Aktivitas Anda:

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

3. Mendeteksi apakah keyboard dibuka atau ditutup dengan menggunakan 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");
                }
            }
        });
CommonSenseCode
sumber
15
hai sobat, bisakah Anda memberi tahu saya dari mana sihir 100 ini berasal? Kenapa tidak 101 atau 99? Terima kasih
Karoly
@ Karoly saya pikir ini mungkin dan 1. Tidak penting. Hanya ini yang harus kurang dari panjang keyboard sebenarnya
Vlad
@Karoly pada dasarnya, dia membandingkan ukuran jendela dengan ukuran tampilan root aktivitas Anda. penampilan keyboard lunak tidak mempengaruhi ukuran jendela utama. sehingga Anda masih dapat menurunkan nilai 100.
mr5
Angka ajaib tergantung pada tata letak topbar Anda di antara hal-hal lain. Jadi itu relatif terhadap aplikasi Anda. Saya menggunakan 400 di salah satu milik saya.
Morten Holmgaard
ingat bahwa onGlobalLayout disebut setiap frame, jadi pastikan Anda tidak melakukan hal-hal berat di sana.
Akshay Gaonkar
8

Saya menggunakan ini sebagai dasar: 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;
}
}

Kemudian tulis metode ini:

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;

}

Anda kemudian dapat menggunakan ini untuk menguji semua bidang (EditText, AutoCompleteTextView, dll) yang mungkin telah membuka papan tombol softkey:

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

Agaknya bukan solusi yang ideal, tetapi itu menyelesaikan pekerjaan.

Christopher Hackl
sumber
2
Ini bekerja. Jika Anda menerapkan sebagai singelton, Anda dapat menerapkan semua edittext pada perubahan fokus dan memiliki satu pendengar papan ketik global
Rarw
@depperm getActivity () khusus untuk Fragmen, coba YourActivityName.ini sebagai gantinya. Lihat juga: stackoverflow.com/questions/14480129/…
Christopher Hackl
6

Anda dapat merujuk ke jawaban ini - https://stackoverflow.com/a/24105062/3629912

Itu bekerja untuk saya setiap saat.

adb shell dumpsys window InputMethod | grep "mHasSurface"

Ini akan mengembalikan true, jika keyboard perangkat lunak terlihat.

aku - 'aku
sumber
10
Ini hanya berguna selama pengembangan - bukan solusi untuk digunakan dalam aplikasi. (Pengguna tidak akan menjalankan adb.)
ToolmakerSteve
5

Jadi setelah lama bermain-main dengan AccessibilityServices, insets jendela, deteksi ketinggian layar, dll, saya pikir saya menemukan cara untuk melakukan ini.

Penafian: menggunakan metode tersembunyi di Android, artinya mungkin tidak konsisten. Namun, dalam pengujian saya, sepertinya berhasil.

Metode ini adalah InputMethodManager # getInputMethodWindowVisibleHeight () , dan sudah ada sejak Lollipop (5.0).

Panggilan yang mengembalikan ketinggian, dalam piksel, dari keyboard saat ini. Secara teori, papan ketik tidak boleh setinggi 0 piksel, jadi saya melakukan pemeriksaan ketinggian sederhana (di Kotlin):

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

Saya menggunakan Android Hidden API untuk menghindari refleksi ketika saya memanggil metode tersembunyi (saya melakukan itu banyak untuk aplikasi yang saya kembangkan, yang sebagian besar merupakan aplikasi peretasan / penyetel), tetapi ini harus dimungkinkan dengan refleksi juga:

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
Petualang
sumber
Penggunaan refleksi yang luar biasa
kaustubhpatange
4

Ini jauh lebih rumit untuk persyaratan yang saya butuhkan. Semoga ini bisa membantu:

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

Nilai boolean primitif default untuk mKeyboardStatus akan diinisialisasi ke false .

Kemudian periksa nilainya sebagai berikut, dan lakukan tindakan jika perlu:

 mSearchBox.requestFocus();
    if(!isKeyboardActive()){
        showKeyboard();
    }else{
        dismissKeyboard();
    }
Bukti masa depan
sumber
4

Ini akan berfungsi jika Anda perlu memeriksa status keyboard:

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

Di mana UiUtils.KEYBOARD_VISIBLE_THRESHOLD_DP= 100 dan dip () adalah fungsi anko yang mengonversi dpToPx:

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

Saya melakukan ini dengan menetapkan GlobalLayoutListener, sebagai berikut:

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
                }
            }
        });
PearsonArtPhoto
sumber
Ini akan disebut SANGAT sering
Denis Kniazhev
Dalam hal apa ini akan berbeda dari jawaban @BrownsooHan? Saya mencari cara yang ditampilkan oleh aplikasi yang menarik dari aplikasi lain.
Evan Langlois
Jawabannya pada dasarnya sama dengan jawaban saya, hanya saya yang menjawab beberapa bulan sebelumnya, dan ia memiliki lebih banyak suara.
PearsonArtPhoto
3

Coba kode ini benar-benar berfungsi jika KeyboardShown ditampilkan, maka fungsi ini mengembalikan nilai sebenarnya ....

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;
}
Ravi Makvana
sumber
IsKeyboardShown terus memanggil dirinya sendiri ketika tidak ditampilkan.
Mandeep Singh
2

Dalam kasus saya, saya hanya punya satu EditTextuntuk mengatur tata letak saya jadi saya datang dengan solusi ini . Ini bekerja dengan baik, pada dasarnya itu adalah kebiasaan EditTextyang mendengarkan fokus dan mengirimkan siaran lokal jika fokus berubah atau jika tombol kembali / selesai ditekan. Agar berhasil, Anda perlu menempatkan boneka Viewdi tata letak Anda android:focusable="true"dan android:focusableInTouchMode="true"karena ketika Anda menelepon clearFocus()fokus akan dipindahkan ke tampilan fokus pertama. Contoh tampilan dummy:

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

Info tambahan

Solusi yang mendeteksi perbedaan dalam perubahan tata letak tidak bekerja dengan baik karena sangat tergantung pada kepadatan layar, karena 100px bisa banyak di perangkat tertentu dan tidak ada di beberapa orang lain Anda bisa mendapatkan hasil positif palsu. Vendor yang berbeda juga memiliki keyboard yang berbeda.

TheRedFox
sumber
1

Di Android Anda dapat mendeteksi melalui shell ADB. Saya menulis dan menggunakan metode ini:

{
        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();
        }
    }
}
Eyal Sooliman
sumber
1
Bisakah Anda meningkatkan jawaban ini dengan contoh yang lebih konkret, dengan semua impor dan contoh yang berfungsi?
Pengguna3
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();
            }
        }
});
pengguna3068659
sumber
1

Jawaban dari @iWantScala bagus tetapi tidak bekerja untuk saya
rootView.getRootView().getHeight()selalu memiliki nilai yang sama

salah satu caranya adalah dengan mendefinisikan dua vars

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

tambahkan pendengar global

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

lalu periksa

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

bekerja dengan baik

Vlad
sumber
1

Akhirnya ada cara langsung mulai dari Android R berdasarkan Kotlin sekarang.

 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 }
Bharadwaj Giridhar
sumber
0

Saya punya masalah serupa. Saya perlu bereaksi terhadap tombol Enter di layar (yang menyembunyikan keyboard). Dalam hal ini Anda dapat berlangganan OnEditorAction dari tampilan teks dengan keyboard yang terbuka - jika Anda memiliki beberapa kotak yang dapat diedit, maka berlanggananlah semuanya.

Di Aktivitas Anda, Anda memiliki kontrol penuh atas keyboard, jadi Anda tidak akan menghadapi masalah apakah keyboard dibuka atau tidak, jika Anda mendengarkan semua acara pembukaan dan penutupan.

Andras Balázs Lajtha
sumber
Tidak bekerja untuk saya. Saya hanya menerima kunci Enter di OnEditorAction.
3c71
0

Ada metode langsung untuk mengetahuinya. Dan, itu tidak membutuhkan perubahan tata letak.
Jadi ini berfungsi dalam mode layar penuh imersif juga.
Tapi, sayangnya, itu tidak berfungsi di semua perangkat. Jadi, Anda harus mengujinya dengan perangkat Anda.

Caranya adalah Anda mencoba menyembunyikan atau menampilkan keyboard lunak dan menangkap hasil dari percobaan itu.
Jika berfungsi dengan benar maka keyboard tidak benar-benar ditampilkan atau disembunyikan. Kami hanya meminta negara.

Agar tetap terkini, Anda cukup mengulangi operasi ini, misalnya setiap 200 milidetik, menggunakan Handler.

Implementasi di bawah ini hanya melakukan satu pemeriksaan.
Jika Anda melakukan beberapa pemeriksaan, maka Anda harus mengaktifkan semua tes (_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;
        }
    }
};
Fies
sumber
bagaimana menyebutnya dan di mana?
Mahdi Astanei
0

Berikut adalah solusi untuk mengetahui apakah papan tombol softkey terlihat.

  1. Periksa untuk menjalankan layanan pada sistem menggunakan ActivityManager.getRunningServices (max_count_of_services);
  2. Dari instance ActivityManager.RunningServiceInfo yang dikembalikan, periksa nilai clientCount untuk layanan keyboard lunak.
  3. ClientCount yang disebutkan di atas akan bertambah setiap kali, keyboard lunak ditampilkan. Misalnya, jika clientCount awalnya 1, itu akan menjadi 2 ketika keyboard ditampilkan.
  4. Pada pemberhentian keyboard, clientCount dikurangi. Dalam hal ini, ulang ke 1.

Beberapa keyboard populer memiliki kata kunci tertentu di Nama kelasnya:

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

Dari ActivityManager.RunningServiceInfo, periksa pola di atas di ClassNames. Juga, ActivityManager.RunningServiceInfo clientPackage = android, menunjukkan bahwa keyboard terikat ke sistem.

Informasi yang disebutkan di atas dapat dikombinasikan untuk cara yang ketat untuk mengetahui apakah keyboard lunak terlihat.

Satishkumar
sumber
0

Seperti yang Anda ketahui, papan ketik Perangkat Lunak android hanya akan terlihat bila ada kemungkinan pengetikan. Dengan kata lain, Keyboard hanya dapat terlihat bila EditText terfokus. itu berarti Anda bisa mendapatkan cuaca Keyboard terlihat atau tidak dengan menggunakan 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;
    }
});

Sekarang Anda dapat menggunakan variabel isKeyBoardVisible di mana saja di kelas untuk mendapatkan cuaca keyboard Terbuka atau Tidak. Itu bekerja dengan baik untuk saya.

Catatan: Proses ini tidak berfungsi ketika Keyboard dibuka secara terprogram menggunakan InputMethodManager karena itu tidak memanggil OnFocusChangeListener.

sharath bhargav
sumber
tidak benar-benar hack, tidak berfungsi dalam kasus fragmen bersarang. Tidak dapat mengatakan tentang kegiatan karena saya belum mencoba ini.
Antroid
0

Saya mengonversi jawaban ke kotlin, semoga ini membantu pengguna 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

            }
        }
    }
}
Emre Akcan
sumber
0

Ini bekerja dengan menyesuaikan Tidak ada bendera aktivitas dan siklus hidup yang digunakan. Juga dengan Kotlin:

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

Metode yang berguna untuk menjaga tampilan selalu di atas keyboard

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

Di mana getFullViewBounds

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

Di mana getFullScreenSize

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
}

Di mana 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
}
Andrey Tuzov
sumber
-1

Saya melakukan ini sebagai berikut, tetapi hanya relevan jika tujuan Anda adalah untuk menutup / membuka keyboad.

tutup contoh: (memeriksa apakah keyboard sudah ditutup, jika tidak - menutup)

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);
                    }
                });
Itay Sued
sumber
Pertanyaan itu terkait dengan mengetahui apakah keyboard ditampilkan atau tidak
Gopal Singh Sirvi
-1

a mungkin menggunakan:

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

}
Milan Jurkulak
sumber
Ini hanya akan berfungsi untuk keyboard perangkat keras, bukan perangkat lunaknya satu
anthonymonori
-1

Saya menulis sampel .

Repositori ini dapat membantu mendeteksi status keyboard tanpa asumsi bahwa "keyboard harus lebih dari X bagian layar"

Аксенов Владимир
sumber
-1

Jika Anda mendukung apis untuk AndroidR di aplikasi Anda, maka Anda dapat menggunakan metode di bawah ini.

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

Catatan: Ini hanya tersedia untuk AndroidR dan versi Android di bawah ini perlu mengikuti beberapa jawaban lain atau saya akan memperbaruinya untuk itu.

Pranav Patel
sumber