Bagaimana cara menyembunyikan keyboard lunak di Android setelah mengklik di luar EditText?

354

Ok semua orang tahu bahwa untuk menyembunyikan keyboard Anda perlu menerapkan:

InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);

Tetapi yang penting di sini adalah bagaimana menyembunyikan keyboard ketika pengguna menyentuh atau memilih tempat lain yang bukan EditTextatau softKeyboard?

Saya mencoba menggunakan onTouchEvent()pada orang tua saya Activitytetapi hanya berfungsi jika pengguna menyentuh di luar tampilan lain dan tidak ada scrollview.

Saya mencoba menerapkan sentuhan, klik, pendengar fokus tanpa hasil.

Saya bahkan mencoba menerapkan scrollview saya sendiri untuk mencegat acara sentuh tetapi saya hanya bisa mendapatkan koordinat acara dan bukan tampilan yang diklik.

Apakah ada cara standar untuk melakukan ini ?? di iPhone itu sangat mudah.

htafoya
sumber
Yah saya menyadari bahwa scrollview tidak benar-benar masalah, tetapi label yang ada di sana. Tampilannya adalah tata letak vertikal dengan sesuatu seperti: TextView, EditText, TextView, EditText, dll. Dan textViews tidak akan membiarkan edittext kehilangan fokus dan menyembunyikan keyboard
htafoya
Anda dapat menemukan solusi untuk di getFields()sini: stackoverflow.com/questions/7790487/…
Reto
Keyboard dapat ditutup dengan menekan tombol kembali, jadi saya akan mengatakan itu dipertanyakan apakah ini sepadan dengan usaha
gerrytan
4
Saya menemukan jawaban ini: stackoverflow.com/a/28939113/2610855 Yang terbaik.
Loenix

Jawaban:

575

Cuplikan berikut hanya menyembunyikan keyboard:

public static void hideSoftKeyboard(Activity activity) {
    InputMethodManager inputMethodManager = 
        (InputMethodManager) activity.getSystemService(
            Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(
        activity.getCurrentFocus().getWindowToken(), 0);
}

Anda dapat menempatkan ini di kelas utilitas, atau jika Anda mendefinisikannya dalam suatu kegiatan, hindari parameter aktivitas, atau panggilan hideSoftKeyboard(this).

Bagian tersulit adalah kapan menyebutnya. Anda dapat menulis metode yang berulang-ulang Viewdi setiap aktivitas Anda, dan memeriksa apakah itu adalah instanceof EditTextjika tidak mendaftar setOnTouchListenerke komponen itu dan semuanya akan jatuh pada tempatnya. Jika Anda bertanya-tanya bagaimana cara melakukannya, itu sebenarnya cukup sederhana. Inilah yang Anda lakukan, Anda menulis metode rekursif seperti berikut ini, sebenarnya Anda dapat menggunakan ini untuk melakukan apa saja, seperti mengatur tipografi kustom dll ... Ini adalah metode

public void setupUI(View view) {

    // Set up touch listener for non-text box views to hide keyboard.
    if (!(view instanceof EditText)) {
        view.setOnTouchListener(new OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                hideSoftKeyboard(MyActivity.this);
                return false;
            }
        });
    }

    //If a layout container, iterate over children and seed recursion.
    if (view instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            View innerView = ((ViewGroup) view).getChildAt(i);
            setupUI(innerView);
        }
    }
}

Itu saja, panggil metode ini setelah Anda setContentViewberaktivitas. Jika Anda bertanya-tanya parameter apa yang akan Anda lewati, itu adalah idwadah induk. Tetapkan sebuah idke wadah induk Anda seperti

<RelativeLayoutPanel android:id="@+id/parent"> ... </RelativeLayout>

dan telepon setupUI(findViewById(R.id.parent)), itu saja.

Jika Anda ingin menggunakan ini secara efektif, Anda dapat membuat extended Activitydan memasukkan metode ini, dan membuat semua aktivitas lain dalam aplikasi Anda memperpanjang aktivitas ini dan memanggilnya setupUI()dalam onCreate()metode.

Semoga ini bisa membantu.

Jika Anda menggunakan lebih dari 1 aktivitas, tentukan id umum untuk tata letak induk seperti <RelativeLayout android:id="@+id/main_parent"> ... </RelativeLayout>

Kemudian rentangkan kelas dari Activitydan definisikan setupUI(findViewById(R.id.main_parent))Di dalamnya OnResume()dan perluas kelas ini sebagai ganti dari `` Activityin your program


Ini adalah versi Kotlin dari fungsi di atas:

@file:JvmName("KeyboardUtils")

fun Activity.hideSoftKeyboard() {
    currentFocus?.let {
        val inputMethodManager = ContextCompat.getSystemService(this, InputMethodManager::class.java)!!
        inputMethodManager.hideSoftInputFromWindow(it.windowToken, 0)
    }
}
Navneeth G
sumber
Saya belum menguji diri saya tetapi sepertinya itu akan berhasil dan karena memiliki ulasan tinggi saya akan mengubah jawaban yang diterima untuk ini.
htafoya
4
Bukankah seharusnya sangat sulit? Saya kehabisan pemrograman Android sekarang, jadi perbaiki jika saya salah. Anda bisa melacak EditText yang terfokus kapan saja, dan meminta saja untuk kehilangan fokusnya selama OnTouchEvent?
Navneeth G
25
Tidak yakin apakah ada orang lain yang mengalami masalah ini, tetapi ini menyebabkan aplikasi mogok saat Anda memanggil hideSoftKeyboard jika tidak ada yang difokuskan. Anda dapat menyelesaikan ini dengan mengelilingi baris kedua metode denganif(activity.getCurrentFocus() != null) {...}
Frank Cangialosi
14
Masalah dengan pendekatan ini adalah mengasumsikan bahwa semua pandangan lain tidak perlu mengatur OnTouchListeneruntuk mereka. Anda bisa mengatur logika itu ViewGroup.onInterceptTouchEvent(MotionEvent)ke tampilan root.
Alex.F
2
Tidak berfungsi saat saya mengeklik kontrol lain agar keyboard tetap dibuka
mohitum
285

Anda dapat mencapai ini dengan melakukan langkah-langkah berikut:

  1. Jadikan tampilan induk (tampilan konten aktivitas Anda) dapat diklik dan fokus dengan menambahkan atribut berikut

        android:clickable="true" 
        android:focusableInTouchMode="true" 
    
  2. Terapkan metode hideKeyboard ()

        public void hideKeyboard(View view) {
            InputMethodManager inputMethodManager =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
        }
    
  3. Terakhir, atur onFocusChangeListener dari edittext Anda.

        edittext.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (!hasFocus) {
                    hideKeyboard(v);
                }
            }
        });
    

Seperti yang ditunjukkan dalam salah satu komentar di bawah, ini mungkin tidak berfungsi jika tampilan induknya adalah ScrollView. Untuk kasus seperti itu, InTouchMode yang dapat diklik dan dapat ditambahkan pada tampilan langsung di bawah ScrollView.

vida
sumber
67
Menurut pendapat saya ini adalah jawaban yang benar. Lebih sedikit kode, tidak ada iterasi yang tidak perlu ...
gattshjoty
14
Saya suka jawaban ini banyak. Satu hal yang perlu diperhatikan adalah bahwa ini tidak berfungsi untuk saya ketika menambahkan clickabledan focusableInTouchModeke ScrollViewelemen root saya . Saya harus menambahkan ke orang tua langsung saya EditTextyang merupakan LinearLayout.
Adam Johns
10
Bekerja dengan sempurna untuk saya. Meskipun, jika Anda memiliki dua widget editeks, Anda harus memastikan bahwa Anda menangani onfokus untuk keduanya dengan benar jika tidak, Anda tidak akan perlu menyembunyikan keyboard tanpa perlu bersembunyi.
Marka A
1
@ Marka Saya tidak punya masalah dengan ini, Ketika saya klik pada EditText lainnya, keyboard tetap, jika diklik di latar belakang itu menyembunyikan seperti seharusnya. Saya memang memiliki beberapa penanganan lain di onFocusChange, hanya mengubah latar belakang EditText ketika ia memiliki fokus, tidak ada fensi.
CularBytes
3
@Shrikant - Saya melihat flicker juga dengan beberapa teks edit. Saya hanya mengatur onFocusChangeListener pada induk alih-alih pada setiap teks edit, dan beralih kondisi untuk mengatakan if (hasFocus) {hideKeyboard (v); } Tidak memperhatikan kedipan lagi beralih btwn edit teks.
manisha
69

Cukup timpa kode di bawah ini dalam Activity

 @Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    if (getCurrentFocus() != null) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
    }
    return super.dispatchTouchEvent(ev);
}
sumit sonawane
sumber
4
Solusi sederhana, Tambahkan aktivitas dan itu akan mengurus fragmen juga
Rohit Maurya
1
Solusi lain adalah membuat BaseActivity dan memperluasnya di semua Kegiatan
sumit sonawane
1
Solusi brilian
Ahmed Adel Ismail
1
Anda menyelamatkan saya agar layar saya tidak berkedip saat menutup keyboard. Jempolan!
Dimas Mendes
1
Bagus, tapi itu terlalu bagus untuk menjadi kenyataan: sederhana, sangat singkat, dan itu berhasil ... sayangnya, ada masalah: ketika keyboard ditampilkan, setiap kali kita menyentuh EditText yang meminta keyboard, itu turun dan secara otomatis.
Chrysotribax
60

Saya menemukan jawaban yang diterima agak rumit.

Inilah solusi saya. Tambahkan OnTouchListenerke tata letak utama Anda, yaitu .:

findViewById(R.id.mainLayout).setOnTouchListener(this)

dan letakkan kode berikut dalam metode onTouch.

InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);

Dengan cara ini Anda tidak perlu mengulang semua pandangan.

roepit
sumber
@roepit - saya mendapatkan classCastexception untuk mencoba menampilkan tata letak ke tampilan. apakah saya melewatkan sesuatu?
katzenhut
Bisakah Anda referensi kode Anda di suatu tempat? Saya tidak tahu apa yang salah ketika saya tidak bisa melihat tata letak dan aktivitas / kode fragmen Anda.
roepit
Jawaban terbaik di luar sana, masih mencoba membungkus kepala saya di sekitar cara kerjanya tho.
user40797
apakah ini akan berfungsi jika Anda mengklik bilah judul aplikasi?
user1506104
1
Ini berfungsi sempurna untuk menyembunyikan keyboard! Perhatikan bahwa ini sebenarnya tidak menghilangkan fokus EditText, itu hanya menyembunyikan keyboard. Untuk juga tidak memfokuskan EditText, tambahkan misalnya android:onClick="stealFocusFromEditTexts"ke xml tampilan induk dan kemudian public void stealFocusFromEditTexts(View view) {}ke aktivitasnya. Metode on-klik tidak perlu melakukan apa-apa, itu hanya harus ada agar tampilan induk menjadi fokus / dapat dipilih, yang diperlukan untuk mencuri fokus dari anak. EditText
Jacob R
40

Saya punya satu solusi lagi untuk menyembunyikan keyboard dengan:

InputMethodManager imm = (InputMethodManager) getSystemService(
    Activity.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);

Di sini lewat HIDE_IMPLICIT_ONLYdi posisi showFlagdan 0di posisi hiddenFlag. Ini akan menutup keyboard lunak dengan paksa.

Saurabh Pareek
sumber
3
Terima kasih itu bekerja ..... di atas semua saya telah mencoba tetapi tidak berfungsi sementara saya mendapatkan nilai dari kotak dialog editext teks dan menutup kotak dialog ...
PankajAndroid
Terima kasih, ini hanya berfungsi, dan jauh lebih bersih daripada yang lain di atas! +1
Edmond Tamas
Ini berfungsi seperti yang diharapkan, terima kasih atas solusi Anda +1
tryp
Bekerja seperti pesona bagi saya. +1 untuk solusi elegan.
saintjab
2
maaf, tetapi metode ini beralih, jadi jika keadaan keyboard sudah ditutup, itu akan menampilkan keyboard
HendraWD
16

Yah saya berhasil menyelesaikan masalah, saya membatalkan dispatchTouchEvent pada aktivitas saya, di sana saya menggunakan yang berikut untuk menyembunyikan keyboard.

 /**
 * Called to process touch screen events. 
 */
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {

    switch (ev.getAction()){
        case MotionEvent.ACTION_DOWN:
            touchDownTime = SystemClock.elapsedRealtime();
            break;

        case MotionEvent.ACTION_UP:
            //to avoid drag events
            if (SystemClock.elapsedRealtime() - touchDownTime <= 150){  

                EditText[] textFields = this.getFields();
                if(textFields != null && textFields.length > 0){

                    boolean clickIsOutsideEditTexts = true;

                    for(EditText field : textFields){
                        if(isPointInsideView(ev.getRawX(), ev.getRawY(), field)){
                            clickIsOutsideEditTexts = false;
                            break;
                        }
                    }

                    if(clickIsOutsideEditTexts){
                        this.hideSoftKeyboard();
                    }               
                } else {
                    this.hideSoftKeyboard();
                }
            }
            break;
    }

    return super.dispatchTouchEvent(ev);
}

EDIT: Metode getFields () hanyalah metode yang mengembalikan array dengan bidang teks dalam tampilan. Untuk menghindari membuat array ini di setiap sentuhan, saya membuat array statis bernama sFields, yang dikembalikan pada metode getFields (). Array ini diinisialisasi pada metode onStart () seperti:

sFields = new EditText[] {mUserField, mPasswordField};


Itu tidak sempurna, waktu acara drag hanya didasarkan pada heuristik jadi kadang-kadang tidak menyembunyikan ketika melakukan clics panjang, dan saya juga selesai dengan membuat metode untuk mendapatkan semua editTexts per tampilan; selain itu keyboard akan bersembunyi dan ditampilkan ketika mengklik EditText lainnya.

Tetap saja, solusi yang lebih bersih dan lebih pendek dipersilakan

htafoya
sumber
8
Untuk membantu orang lain di masa depan, apakah Anda mempertimbangkan untuk mengedit kode dalam jawaban Anda untuk memasukkan getFields()metode Anda ? Itu tidak harus tepat, hanya sebuah contoh dengan mungkin hanya beberapa komentar yang menunjukkan bahwa ia mengembalikan array EditTextobjek.
Squonk
14

Gunakan OnFocusChangeListener .

Sebagai contoh:

editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (!hasFocus) {
            hideKeyboard();
        }
    }
});

Pembaruan : Anda juga dapat mengganti onTouchEvent()aktivitas Anda dan memeriksa koordinat sentuhan. Jika koordinat berada di luar EditText, sembunyikan keyboard.

Sergey Glotov
sumber
9
Masalahnya adalah bahwa edittext tidak kehilangan fokus ketika saya mengklik Label atau tampilan lain yang tidak dapat fokus.
htafoya
Dalam hal ini saya punya satu solusi lagi. Saya sudah memperbarui jawabannya.
Sergey Glotov
2
onTouchEvent dipanggil berkali-kali jadi ini bukan praktik yang baik juga
Jesus Dimrix
13

Saya menerapkan dispatchTouchEvent di Aktivitas untuk melakukan ini:

private EditText mEditText;
private Rect mRect = new Rect();
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    final int action = MotionEventCompat.getActionMasked(ev);

    int[] location = new int[2];
    mEditText.getLocationOnScreen(location);
    mRect.left = location[0];
    mRect.top = location[1];
    mRect.right = location[0] + mEditText.getWidth();
    mRect.bottom = location[1] + mEditText.getHeight();

    int x = (int) ev.getX();
    int y = (int) ev.getY();

    if (action == MotionEvent.ACTION_DOWN && !mRect.contains(x, y)) {
        InputMethodManager input = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        input.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
    }
    return super.dispatchTouchEvent(ev);
}

dan saya mengujinya, berfungsi sempurna!

Jishi Chen
sumber
berfungsi, tetapi masalah dalam hal ini adalah bahwa jika kita memiliki lebih dari satu EditText maka kita perlu mempertimbangkan itu juga, tetapi saya menyukai jawaban Anda :-)
Lalit Poptani
getActionMasked (ev) sudah usang, jadi sekarang gunakan: final int action = ev.getActionMasked (); untuk baris pertama.
Andrew
12

Cara Desain Kotlin & Material lainnya menggunakan TextInputEditText (pendekatan ini juga kompatibel dengan EditTextView ) ...

1.Membuat tampilan induk (tampilan konten aktivitas / fragmen Anda) dapat diklik dan fokus dengan menambahkan atribut berikut

android:focusable="true"
android:focusableInTouchMode="true"
android:clickable="true"

2.Buat ekstensi untuk semua Tampilan (di dalam file ViewExtension.kt misalnya):

fun View.hideKeyboard(){
    val inputMethodManager = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
    inputMethodManager.hideSoftInputFromWindow(this.windowToken, 0)
}

3.Buat BaseTextInputEditText yang mewarisi TextInputEditText. Menerapkan metode onFocusChanged untuk menyembunyikan keyboard ketika tampilan tidak fokus:

class BaseTextInputEditText(context: Context?, attrs: AttributeSet?) : TextInputEditText(context, attrs){
    override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect)
        if (!focused) this.hideKeyboard()
    }
}

4. panggil saja tampilan kustom baru Anda di XML Anda:

<android.support.design.widget.TextInputLayout
        android:id="@+id/textInputLayout"
        ...>

        <com.your_package.BaseTextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            ... />

    </android.support.design.widget.TextInputLayout> 

Itu saja. Tidak perlu memodifikasi pengontrol Anda (fragmen atau aktivitas) untuk menangani kasus berulang ini.

Phil
sumber
Ya bagus tapi saya berharap ada cara yang lebih sederhana!
devDeejay
11

Mengesampingkan boolean dispatchTouchEvent publik (acara MotionEvent) di Aktivitas apa pun (atau memperluas kelas Kegiatan)

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    View view = getCurrentFocus();
    boolean ret = super.dispatchTouchEvent(event);

    if (view instanceof EditText) {
        View w = getCurrentFocus();
        int scrcoords[] = new int[2];
        w.getLocationOnScreen(scrcoords);
        float x = event.getRawX() + w.getLeft() - scrcoords[0];
        float y = event.getRawY() + w.getTop() - scrcoords[1];

        if (event.getAction() == MotionEvent.ACTION_UP 
 && (x < w.getLeft() || x >= w.getRight() 
 || y < w.getTop() || y > w.getBottom()) ) { 
            InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0);
        }
    }
 return ret;
}

Dan itu semua yang perlu Anda lakukan

Hoang Trinh
sumber
ini adalah cara termudah yang saya temukan untuk membuatnya bekerja. bekerja dengan beberapa EditText dan ScrollView
RJH
Mengujinya dengan beberapa EditText; berhasil! Satu-satunya kelemahan adalah bahwa ketika Anda melakukan gerakan drag itu bersembunyi juga.
RominaV
9

Saya memodifikasi solusi Andre Luis IM. Saya mencapai yang ini:

Saya membuat metode utilitas untuk menyembunyikan keyboard lunak dengan cara yang sama seperti yang dilakukan Andre Luiz IM:

public static void hideSoftKeyboard(Activity activity) {
    InputMethodManager inputMethodManager = (InputMethodManager)  activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}

Tetapi alih-alih mendaftarkan OnTouchListener untuk setiap tampilan, yang memberikan kinerja buruk, saya mendaftarkan OnTouchListener hanya untuk tampilan root. Karena gelembung acara hingga dikonsumsi (EditText adalah salah satu tampilan yang mengkonsumsinya secara default), jika tiba ke tampilan root, itu karena tidak dikonsumsi, jadi saya menutup keyboard lunak.

findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Utils.hideSoftKeyboard(activity);
        return false;
    }
});
Fernando Camargo
sumber
1
Ini tampaknya lebih aman bagi saya.
superarts.org
9

Saya sadar bahwa utas ini cukup lama, jawaban yang benar tampaknya valid dan ada banyak solusi yang berfungsi di luar sana, tetapi saya pikir pendekatan yang disebutkan di bawah ini mungkin memiliki manfaat tambahan mengenai efisiensi dan keanggunan.

Saya memerlukan perilaku ini untuk semua kegiatan saya, jadi saya membuat kelas CustomActivity yang diwarisi dari Kegiatan kelas dan "mengaitkan" fungsi dispatchTouchEvent . Ada dua kondisi utama yang harus diperhatikan:

  1. Jika fokus tidak berubah dan seseorang mengetuk di luar bidang input saat ini, maka abaikan IME
  2. Jika fokus telah berubah dan elemen fokus berikutnya bukanlah turunan dari bidang input apa pun, maka abaikan IME

Ini hasil saya:

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    if(ev.getAction() == MotionEvent.ACTION_UP) {
        final View view = getCurrentFocus();

        if(view != null) {
            final boolean consumed = super.dispatchTouchEvent(ev);

            final View viewTmp = getCurrentFocus();
            final View viewNew = viewTmp != null ? viewTmp : view;

            if(viewNew.equals(view)) {
                final Rect rect = new Rect();
                final int[] coordinates = new int[2];

                view.getLocationOnScreen(coordinates);

                rect.set(coordinates[0], coordinates[1], coordinates[0] + view.getWidth(), coordinates[1] + view.getHeight());

                final int x = (int) ev.getX();
                final int y = (int) ev.getY();

                if(rect.contains(x, y)) {
                    return consumed;
                }
            }
            else if(viewNew instanceof EditText || viewNew instanceof CustomEditText) {
                return consumed;
            }

            final InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);

            inputMethodManager.hideSoftInputFromWindow(viewNew.getWindowToken(), 0);

            viewNew.clearFocus();

            return consumed;
        }
    }       

    return super.dispatchTouchEvent(ev);
}

Catatan: Selain itu, saya menetapkan atribut ini ke tampilan root sehingga memungkinkan untuk menghapus fokus pada setiap bidang input dan mencegah bidang input mendapatkan fokus pada aktivitas awal (membuat konten melihat "catcher catcher"):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    final View view = findViewById(R.id.content);

    view.setFocusable(true);
    view.setFocusableInTouchMode(true);
}
fje
sumber
Super berfungsi dengan baik terima kasih !! Saya telah menempatkan satu upvote untuk jawaban Anda.
vijay
2
Saya pikir itu solusi terbaik untuk tata letak yang rumit. Tapi saya menemukan 2 kelemahan sejauh ini: 1. Menu konteks EditText tidak dapat diklik - klik apa pun di sana menyebabkan kehilangan fokus dari EditText 2. Ketika EditText kami berada di bawah tampilan dan kami mengkliknya (untuk memilih kata), kemudian setelah itu keyboard yang ditampilkan "titik klik" kami ada di keyboard, bukan di EditText - jadi kami kehilangan fokus lagi: /
sosite
@site, saya pikir saya telah mengatasi keterbatasan itu dalam jawaban saya; Lihatlah.
Andy Dennie
6

Saya menyukai pendekatan panggilan yang dispatchTouchEventdilakukan oleh htafoya, tetapi:

  • Saya tidak mengerti bagian pengatur waktu (tidak tahu mengapa harus mengukur waktu henti?)
  • Saya tidak suka mendaftar / batalkan registrasi semua EditText dengan setiap perubahan tampilan (bisa jadi cukup banyak perubahan tampilan dan editteks dalam hierarki yang kompleks)

Jadi, saya membuat solusi yang agak lebih mudah ini:

@Override
public boolean dispatchTouchEvent(final MotionEvent ev) {
    // all touch events close the keyboard before they are processed except EditText instances.
    // if focus is an EditText we need to check, if the touchevent was inside the focus editTexts
    final View currentFocus = getCurrentFocus();
    if (!(currentFocus instanceof EditText) || !isTouchInsideView(ev, currentFocus)) {
        ((InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE))
            .hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
    return super.dispatchTouchEvent(ev);
}

/**
 * determine if the given motionevent is inside the given view.
 * 
 * @param ev
 *            the given view
 * @param currentFocus
 *            the motion event.
 * @return if the given motionevent is inside the given view
 */
private boolean isTouchInsideView(final MotionEvent ev, final View currentFocus) {
    final int[] loc = new int[2];
    currentFocus.getLocationOnScreen(loc);
    return ev.getRawX() > loc[0] && ev.getRawY() > loc[1] && ev.getRawX() < (loc[0] + currentFocus.getWidth())
        && ev.getRawY() < (loc[1] + currentFocus.getHeight());
}

Ada satu kelemahan:

Beralih dari satu EditTextke yang lain EditTextmembuat keyboard bersembunyi dan melakukan pemasangan ulang - dalam kasus saya itu diinginkan seperti itu, karena itu menunjukkan bahwa Anda beralih di antara dua komponen input.

Christian R.
sumber
Metode ini bekerja paling baik dalam hal hanya bisa plug-and-play dengan FragmentActivity saya.
BillyRayCyrus
Terima kasih, ini cara terbaik! Saya baru saja menambahkan memeriksa untuk tindakan acara: int action = ev.getActionMasked (); if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN) {...}
sergey.n
Terima kasih! Anda menghemat waktu saya .. Jawaban terbaik.
I.d007
6

Plea: Saya tahu saya tidak punya pengaruh, tapi tolong jawab jawaban saya dengan serius.

Masalah: Singkirkan keyboard lunak saat mengklik menjauh dari keyboard atau edit teks dengan kode minimal.

Solusi: Perpustakaan eksternal yang dikenal sebagai Butterknife.

Solusi Satu Jalur:

@OnClick(R.id.activity_signup_layout) public void closeKeyboard() { ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); }

Solusi Lebih Mudah Dibaca:

@OnClick(R.id.activity_signup_layout) 
public void closeKeyboard() {
        InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}

Penjelasan: Bind OnClick Listener ke ID induk XML Layout aktivitas, sehingga setiap klik pada tata letak (bukan pada teks edit atau keyboard) akan menjalankan cuplikan kode yang akan menyembunyikan keyboard.

Contoh: Jika file tata letak Anda adalah R.layout.my_layout dan id tata letak Anda adalah R.id.my_layout_id, maka panggilan mengikat Butterknife Anda akan terlihat seperti:

(@OnClick(R.id.my_layout_id) 
public void yourMethod {
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}

Tautan Dokumentasi Butterknife: http://jakewharton.github.io/butterknife/

Pasang: Butterknife akan merevolusi pengembangan android Anda. Pikirkan itu.

Catatan: Hasil yang sama dapat dicapai tanpa menggunakan perpustakaan eksternal Butterknife. Cukup atur OnClickListener ke tata letak induk seperti dijelaskan di atas.

Charles Woodson
sumber
Solusi luar biasa dan sempurna! Terima kasih.
nullforlife
6

Di kotlin, kita bisa melakukan hal berikut. Tidak perlu mengulang semua tampilan. Ini akan bekerja untuk fragmen juga.

override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
    currentFocus?.let {
        val imm: InputMethodManager = getSystemService(
            Context.INPUT_METHOD_SERVICE
        ) as (InputMethodManager)
        imm.hideSoftInputFromWindow(it.windowToken, 0)
    }
    return super.dispatchTouchEvent(ev)
}
Sai
sumber
tidak bekerja dari fragmen
Nurseyit Tursunkulov
ini berfungsi tetapi memiliki bug. misalnya, jika saya ingin menempelkan teks di tampilan teks, keyboard menyembunyikan dan kemudian muncul. Agak menyebalkan.
George Shalvashvili
Jadi, beri tahu saya solusi terbaik ..
Sai
4

Berikut variasi lain pada jawaban fje yang membahas masalah yang diangkat oleh sosite.

Idenya di sini adalah untuk menangani tindakan turun dan naik dalam metode Kegiatan dispatchTouchEvent. Pada tindakan turun, kami mencatat tampilan yang saat ini difokuskan (jika ada) dan apakah sentuhan ada di dalamnya, menyimpan kedua bit informasi tersebut untuk nanti.

Pada tindakan selanjutnya, pertama-tama kami kirim, untuk memungkinkan tampilan lain berpotensi mengambil fokus. Jika setelah itu, tampilan yang saat ini fokus adalah tampilan yang awalnya fokus, dan sentuhan bawah ada di dalam tampilan itu, maka kami membiarkan keyboard terbuka.

Jika tampilan yang saat ini fokus berbeda dari tampilan yang semula fokus dan ini adalah EditText, maka kami juga membiarkan keyboard terbuka.

Kalau tidak kita tutup saja.

Jadi, singkatnya, ini berfungsi sebagai berikut:

  • saat menyentuh di dalam yang sedang difokuskan EditText, keyboard tetap terbuka
  • ketika berpindah dari fokus EditTextke yang lain EditText, keyboard tetap terbuka (tidak menutup / membuka kembali)
  • ketika menyentuh di mana saja di luar fokus EditTextyang saat ini bukan yang lain EditText, keyboard ditutup
  • ketika lama menekan dalam EditTextuntuk memunculkan bilah tindakan kontekstual (dengan tombol cut / copy / paste), keyboard tetap terbuka, meskipun tindakan UP terjadi di luar fokus EditText(yang bergerak ke bawah untuk memberikan ruang bagi CAB) . Namun, perlu diketahui bahwa ketika Anda mengetuk tombol di CAB, itu akan menutup keyboard. Itu mungkin atau mungkin tidak diinginkan; jika Anda ingin memotong / menyalin dari satu bidang dan menempel ke yang lain, itu akan menjadi. Jika Anda ingin menempel kembali ke yang sama EditText, itu tidak akan terjadi.
  • ketika fokus EditTextberada di bagian bawah layar dan Anda mengklik lama pada beberapa teks untuk memilihnya, EditTextfokus tetap dan karena itu keyboard terbuka seperti yang Anda inginkan, karena kami melakukan "sentuhan dalam batas tampilan" centang pada tindakan turun , bukan tindakan atas.

    private View focusedViewOnActionDown;
    private boolean touchWasInsideFocusedView;
    
    
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                focusedViewOnActionDown = getCurrentFocus();
                if (focusedViewOnActionDown != null) {
                    final Rect rect = new Rect();
                    final int[] coordinates = new int[2];
    
                    focusedViewOnActionDown.getLocationOnScreen(coordinates);
    
                    rect.set(coordinates[0], coordinates[1],
                            coordinates[0] + focusedViewOnActionDown.getWidth(),
                            coordinates[1] + focusedViewOnActionDown.getHeight());
    
                    final int x = (int) ev.getX();
                    final int y = (int) ev.getY();
    
                    touchWasInsideFocusedView = rect.contains(x, y);
                }
                break;
    
            case MotionEvent.ACTION_UP:
    
                if (focusedViewOnActionDown != null) {
                    // dispatch to allow new view to (potentially) take focus
                    final boolean consumed = super.dispatchTouchEvent(ev);
    
                    final View currentFocus = getCurrentFocus();
    
                    // if the focus is still on the original view and the touch was inside that view,
                    // leave the keyboard open.  Otherwise, if the focus is now on another view and that view
                    // is an EditText, also leave the keyboard open.
                    if (currentFocus.equals(focusedViewOnActionDown)) {
                        if (touchWasInsideFocusedView) {
                            return consumed;
                        }
                    } else if (currentFocus instanceof EditText) {
                        return consumed;
                    }
    
                    // the touch was outside the originally focused view and not inside another EditText,
                    // so close the keyboard
                    InputMethodManager inputMethodManager =
                            (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    inputMethodManager.hideSoftInputFromWindow(
                        focusedViewOnActionDown.getWindowToken(), 0);
                    focusedViewOnActionDown.clearFocus();
    
                    return consumed;
                }
                break;
        }
    
        return super.dispatchTouchEvent(ev);
    }
Andy Dennie
sumber
4

terlalu sederhana, cukup buat layout baru-baru ini Anda dapat diklik oleh kode ini:

android:id="@+id/loginParentLayout"
android:clickable="true"
android:focusableInTouchMode="true"

dan kemudian menulis metode dan OnClickListner untuk tata letak itu, sehingga ketika tata letak paling atas disentuh di mana pun itu akan memanggil metode di mana Anda akan menulis kode untuk menghilangkan keyboard. berikut ini adalah kode untuk keduanya; // Anda harus menulis ini di OnCreate ()

 yourLayout.setOnClickListener(new View.OnClickListener(){
                @Override
                public void onClick(View view) {
                    hideKeyboard(view);
                }
            });

metode yang dipanggil dari listner: -

 public void hideKeyboard(View view) {
     InputMethodManager imm =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }
swarnim dixit
sumber
4

Saya menemukan sedikit jawaban yang diterima kompleks untuk persyaratan sederhana ini. Inilah yang bekerja untuk saya tanpa ada kesalahan.

findViewById(R.id.mainLayout).setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
            return false;
        }
    });
Joohay
sumber
1
Jika Anda menggunakan NestedScrollViewatau tata letak yang rumit, lihat jawaban yang diterima: stackoverflow.com/a/11656129/2914140 . Anda harus tahu bahwa wadah lain mungkin mengkonsumsi sentuhan.
CoolMind
3

Ada pendekatan yang lebih sederhana, berdasarkan masalah yang sama iPhone. Cukup timpa tata letak latar belakang pada acara sentuh, tempat teks edit dimuat. Cukup gunakan kode ini di OnCreate aktivitas (login_fondo adalah tata letak root):

    final LinearLayout llLogin = (LinearLayout)findViewById(R.id.login_fondo);
    llLogin.setOnTouchListener(
            new OnTouchListener()
            {
                @Override
                public boolean onTouch(View view, MotionEvent ev) {
                    InputMethodManager imm = (InputMethodManager) mActivity.getSystemService(
                            android.content.Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(mActivity.getCurrentFocus().getWindowToken(), 0);
                    return false;
                }
            });
Alex RR
sumber
1
Seperti yang saya katakan dan saya ingat, ini hanya berfungsi jika formulir tidak ada di dalam ScrollView.
htafoya
1
Ini tidak berfungsi dengan baik jika tata letak latar belakang berisi tata letak anak-anak lain.
AxeEffect
Terima kasih telah mengingatkan bahwa onClick bukan satu-satunya pilihan.
Harpreet
3

Metode untuk menampilkan / menyembunyikan keyboard lunak

InputMethodManager inputMethodManager = (InputMethodManager) currentActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
    if (isShow) {
        if (currentActivity.getCurrentFocus() == null) {
            inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
        } else {
            inputMethodManager.showSoftInput(currentActivity.getCurrentFocus(), InputMethodManager.SHOW_FORCED);    
        }

    } else {
        if (currentActivity.getCurrentFocus() == null) {
            inputMethodManager.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0);
        } else {
            inputMethodManager.hideSoftInputFromInputMethod(currentActivity.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);    
        }

    }

Saya harap mereka bermanfaat

lalosoft
sumber
3

Yang ini adalah solusi termudah bagi saya (dan berhasil oleh saya).

Ini adalah metode untuk menyembunyikan keyboard.

public void hideKeyboard(View view){
        if(!(view instanceof EditText)){
            InputMethodManager inputMethodManager=(InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),0);
        }
    }

sekarang atur atribut klik tata letak induk dari aktivitas ke metode di atas hideKeyboardbaik dari tampilan Desain file XML Anda atau menulis kode di bawah ini dalam tampilan Teks file XML Anda.

android:onClick="hideKeyboard"
NullByte08
sumber
2

Saya telah memperbaiki metode ini, memasukkan kode berikut di beberapa kelas utilitas UI (lebih disukai, tidak harus) sehingga dapat diakses dari semua kelas Aktivitas atau Fragmen Anda untuk memenuhi tujuannya.

public static void serachAndHideSoftKeybordFromView(View view, final Activity act) {
    if(!(view instanceof EditText)) {
        view.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                hideSoftKeyboard(act);
                return false;
            }
        });
    }
    if (view instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            View nextViewInHierarchy = ((ViewGroup) view).getChildAt(i);
            serachAndHideSoftKeybordFromView(nextViewInHierarchy, act);
        }
    }
}
public static void hideSoftKeyboard (Activity activity) {
    InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}

Kemudian katakan misalnya Anda perlu memanggilnya dari aktivitas, panggil sebagai berikut;

UIutils.serachAndHideSoftKeybordFromView(findViewById(android.R.id.content), YourActivityName.this);

Memperhatikan

findViewById (android.R.id.content)

Ini memberi kami tampilan root dari grup saat ini (Anda tidak harus mengatur id pada tampilan root).

Bersulang :)

Uzair
sumber
2

Aktivitas

 @Override
 public boolean dispatchTouchEvent(MotionEvent ev) {
     ScreenUtils.hideKeyboard(this, findViewById(android.R.id.content).getWindowToken());
     return super.dispatchTouchEvent(ev);
 }

ScreenUtils

 public static void hideKeyboard(Context context, IBinder windowToken) {
     InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
     imm.hideSoftInputFromWindow(windowToken, InputMethodManager.HIDE_NOT_ALWAYS);
 }
icebail
sumber
3
Kode ini sederhana, tetapi memiliki masalah yang jelas: menutup keyboard saat di mana saja disentuh. Itu adalah jika Anda mengetuk lokasi yang berbeda dari EditText untuk memindahkan kursor input, itu menyembunyikan keyboard, dan keyboard muncul lagi oleh sistem.
Damn Vegetables
2

Tambahkan kode ini di kelas @Overide

public boolean dispatchTouchEvent(MotionEvent ev) {
    View view = getCurrentFocus();
    if (view != null && (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_MOVE) && view instanceof EditText && !view.getClass().getName().startsWith("android.webkit.")) {
        int scrcoords[] = new int[2];
        view.getLocationOnScreen(scrcoords);
        float x = ev.getRawX() + view.getLeft() - scrcoords[0];
        float y = ev.getRawY() + view.getTop() - scrcoords[1];
        if (x < view.getLeft() || x > view.getRight() || y < view.getTop() || y > view.getBottom())
            ((InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow((this.getWindow().getDecorView().getApplicationWindowToken()), 0);
    }
    return super.dispatchTouchEvent(ev);
}
Haseeb Javed
sumber
3
Meskipun ini dapat menjawab pertanyaan, lebih baik untuk menjelaskan bagian-bagian penting dari jawaban dan mungkin apa masalah dengan kode OP.
pirho
ya @pirho saya juga setuju dengan Anda, Haseeb perlu berkonsentrasi untuk memberikan jawaban yang tepat.
Dilip
2
@Dilip Tahukah Anda bahwa Anda juga dapat meningkatkan komentar yang Anda setujui? Ini hanya untuk menjaga bagian komentar tetap bersih sehingga tidak memiliki banyak komentar yang sebenarnya memiliki poin yang sama.
pirho
2

Alih-alih mengulangi semua tampilan atau mengabaikan dispatchTouchEvent.

Mengapa Tidak hanya mengesampingkan onUserInteraction () dari Kegiatan ini akan memastikan keyboard ditolak setiap kali pengguna mengetuk di luar EditText.

Akan berfungsi bahkan ketika EditText ada di dalam scrollView.

@Override
public void onUserInteraction() {
    if (getCurrentFocus() != null) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
    }
}
SKG
sumber
ini adalah jawaban yang lebih baik
ovluca
Iya! Itu jawaban yang sangat bersih. Dan jika Anda membuat AbstractActivity yang diperluas oleh semua Aktivitas Anda yang lain, Anda dapat menjadikannya sebagai perilaku default di seluruh aplikasi Anda.
wildcat12
1

Saya mendapatkan ini dengan sedikit variasi pada solusi Fernando Camarago. Dalam metode onCreate saya, saya melampirkan onTouchListener tunggal ke tampilan root tetapi mengirim tampilan daripada aktivitas sebagai argumen.

        findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() {           
        public boolean onTouch(View v, MotionEvent event) {
            Utils.hideSoftKeyboard(v);
            return false;
        }
    });

Dalam kelas Utils terpisah adalah ...

    public static void hideSoftKeyboard(View v) {
    InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 
    imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
AndyMc
sumber
1

Ini mungkin sudah tua tapi saya dapat ini berhasil dengan menerapkan kelas khusus

public class DismissKeyboardListener implements OnClickListener {

    Activity mAct;

    public DismissKeyboardListener(Activity act) {
        this.mAct = act;
    }

    @Override
    public void onClick(View v) {
        if ( v instanceof ViewGroup ) {
            hideSoftKeyboard( this.mAct );
        }
    }       
}

public void hideSoftKeyboard(Activity activity) {
        InputMethodManager imm = (InputMethodManager)
        getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
}

praktik terbaik di sini adalah membuat kelas Helper dan setiap kontainer Layout Relatif / Linear harus menerapkan ini.

**** Perhatikan bahwa hanya Wadah utama yang harus mengimplementasikan kelas ini (Untuk optimasi) ****

dan implementasikan seperti ini:

Parent.setOnClickListener( new DismissKeyboardListener(this) ); 

kata kunci ini untuk Aktivitas. jadi jika Anda berada di fragmen yang Anda gunakan seperti getActivity ();

--- jempol jika itu membantu Anda ... --- bersorak Ralph ---

ralphgabb
sumber
1

Ini adalah versi jawaban fje yang sedikit dimodifikasi yang sebagian besar bekerja dengan sempurna.

Versi ini menggunakan ACTION_DOWN sehingga melakukan tindakan gulir juga menutup keyboard. Itu juga tidak menyebarkan acara kecuali Anda mengklik EditText lain. Ini berarti bahwa mengklik di mana saja di luar EditText Anda, bahkan pada klik lainnya, cukup tutup keyboard.

@Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
    if(ev.getAction() == MotionEvent.ACTION_DOWN)
    {
        final View view = getCurrentFocus();

        if(view != null)
        {
            final View viewTmp = getCurrentFocus();
            final View viewNew = viewTmp != null ? viewTmp : view;

            if(viewNew.equals(view))
            {
                final Rect rect = new Rect();
                final int[] coordinates = new int[2];

                view.getLocationOnScreen(coordinates);

                rect.set(coordinates[0], coordinates[1], coordinates[0] + view.getWidth(), coordinates[1] + view.getHeight());

                final int x = (int) ev.getX();
                final int y = (int) ev.getY();

                if(rect.contains(x, y))
                {
                    super.dispatchTouchEvent(ev);
                    return true;
                }
            }
            else if(viewNew instanceof EditText || viewNew instanceof CustomEditText)
            {
                super.dispatchTouchEvent(ev);
                return true;
            }

            final InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);

            inputMethodManager.hideSoftInputFromWindow(viewNew.getWindowToken(), 0);

            viewNew.clearFocus();

            return true;
        }
    }
    return super.dispatchTouchEvent(ev);
}
Cadmonkey33
sumber
Sesuatu tidak terlihat di sini; Anda menugaskan keduanya viewdan viewTmpuntuk getCurrentFocus(), sehingga mereka akan selalu memiliki nilai yang sama.
Andy Dennie
1

Saya telah melakukan ini:

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
   View view = getCurrentFocus();
   if (view != null && (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_MOVE) && view instanceof EditText && !view.getClass().getName().startsWith("android.webkit.")) {
            int scrcoords[] = new int[2];
            view.getLocationOnScreen(scrcoords);
            float x = ev.getRawX() + view.getLeft() - scrcoords[0];
            float y = ev.getRawY() + view.getTop() - scrcoords[1];
            if (x < view.getLeft() || x > view.getRight() || y < view.getTop() || y > view.getBottom())
                hideKeyboard(this);
        }
    return super.dispatchTouchEvent(ev);
}

Sembunyikan kode keyboard :

public static void hideKeyboard(Activity act) {
    if(act!=null)
      ((InputMethodManager)act.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow((act.getWindow().getDecorView().getApplicationWindowToken()), 0);
  }

Selesai

Hiren Patel
sumber