Jak wykryć, czy klawiatura jest otwarta w systemie Android?

Na blogu pojawił się jakiś czas temu wpis poświęcony klawiaturze. Opisywałem, w jaki sposób layout ma reagować na stan klawiatury. Dziś pójdziemy o krok dalej i rozszerzymy ten temat.

Po co wykrywać czy klawiatura jest otwarta?

Zdarzają się projekty, w których musimy ukryć pewne elementy na ekranie, gdy klawiatura jest wyświetlana. Może także przydać się w testach. Jak wiadomo co urządzenie to inna przekątna ekranu. Co za tym idzie, wygląd naszej aplikacji może się różnie zachowywać.

Uzupełnij wiedzę o: Analiza struktury layoutu za pomocą Hierarchy Viewer

W Jaki sposób wykryć, czy klawiatura jest otwarta lub zamknięta?

Ten wpis nie powstałby, gdyby to było takie proste. Nie ma do tego jednej funkcji, którą mógłbyś wywołać w kodzie. Ach dziwne, że Google tego nie chce wprowadzić. Może kiedyś…

Cała zabawa polega na tym, że na początku musimy pobrać wymiary naszej aktywności lub fragmentu. Następnie pobrać wymiary klawiatury, obliczyć różnicę i wyświetlić wynik. Proste?

Od początku…

Poniższy kod jest przedstawiony w języku Kotlin. Jeśli jeszcze nie znasz tego języka, zachęcam Cię do jego nauki. Z drugiej strony jest napisany w przystępnej formie, na pewno zrozumiesz wszystko 🙂

Na początku pobierzmy nasz widok (View) aktywności.

val myView = window.decorView.rootView
// lub
val myView2=findViewById<LinearLayout>(R.id.rootview)

Teraz musimy pobrać wysokość naszego widoku root:

            val r = Rect()
            myView.getWindowVisibleDisplayFrame(r)
            val screenHeight = myView.getRootView().getHeight()

Klasa View ma metodę o nazwie getWindowVisibleDisplayFrame(). Właśnie z niej możemy pobrać prostokąt, który zawiera część widoku widocznych dla użytkownika. Uwzględnia to pewne elementy systemu, które można umieścić na wierzchu widoku (takie jak klawiatura).

Oprócz tego musimy porównać wysokość klawiatury z wysokością widoku root, jak pokazano poniżej:

val keypadHeight = screenHeight - r.bottom
            if (keypadHeight > screenHeight * 0.15) {
                Log.d("TAG", "Open ")
            } else {
                Log.d("TAG", "Close ")
            }

Z widocznego prostokąta możemy uzyskać widoczną wysokość. Porównując widoczną wysokość z rzeczywistą wysokością widoków, określamy czy klawiatura została narysowana nad widokiem.

Następnie użyjemy detektora viewTreeObserver, aby znaleźć zmiany w widokach w konkretnej aktywności. ViewTreeObserver.OnGlobalLayoutListener pozwala reagować, gdy zmieni się globalny stan układu lub widoczność widoków w drzewie widoku. W tym obserwatorze umieszczamy powyższe bloki kodu, które zostały opisane.

 myView.getViewTreeObserver().addOnGlobalLayoutListener(ViewTreeObserver
.OnGlobalLayoutListener {
            ...
        })

Kompletny kod

Poniżej znajduje się cały kod poruszonego dzisiaj tematu.

class MainDetectKeyboardActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(net.myenv.paging.R.layout.activity_main_detect_keyboard)

        val myView = window.decorView.rootView
        myView.getViewTreeObserver()
              .addOnGlobalLayoutListener(ViewTreeObserver
              .OnGlobalLayoutListener {
            
            val r = Rect()
            myView.getWindowVisibleDisplayFrame(r)
            val screenHeight = myView.getRootView().getHeight()
            val keypadHeight = screenHeight - r.bottom
            if (keypadHeight > screenHeight * 0.15) {
                Log.d("TAG", "Open ")
            } else {
                Log.d("TAG", "Close ")
            }

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

    <EditText
        android:id="@+id/edittext"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

Co dalej?

  • Polub stronę MYENV na Facebooku oraz śledź mnie na Twitterze
  • Zachęcam do komentowania i pisania propozycji tematów, o których chcesz przeczytać
  • Poleć ten wpis za pomocą poniższych przycisków. Będę Ci za to bardzo wdzięczny 🙂
  • Życzę Ci miłego dnia i miłego kodowania 🙂