Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Ẩn bàn phím ảo (Soft Keyboard) trong Android

Thường cần ẩn bàn phím sau khi user nhập xong (nhấn nút "Done", click ra ngoài, submit form). Android cung cấp InputMethodManager để điều khiển.

Cách 1: InputMethodManager (Phổ biến nhất)

import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.content.Context;

public void hideKeyboard(View view) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    if (imm != null) {
        // view: bất kỳ view nào đang focus (thường là EditText hoặc root view)
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }
}

// Sử dụng trong Activity:
hideKeyboard(findViewById(R.id.etInput)); // hoặc
hideKeyboard(getCurrentFocus()); // view đang focus
// hoặc
hideKeyboard(getWindow().getDecorView().getRootView()); // root view luôn an toàn

Cách 2: Window Soft Input Mode (Manifest/XML)

Tự động ẩn/hiện khi Activity start:



    

Cách 3: ẩn khi click ra ngoài (Touch Interceptor)

// Trong Activity
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        View view = getCurrentFocus();
        if (view != null) {
            Rect outRect = new Rect();
            view.getGlobalVisibleRect(outRect);
            if (!outRect.contains((int) ev.getRawX(), (int) ev.getRawY())) {
                // Click ra ngoài view đang focus
                view.clearFocus();
                hideKeyboard(view);
            }
        }
    }
    return super.dispatchTouchEvent(ev);
}

Cách 4: EditText IME Options (Nút Done/Next trên keyboard)


    android:inputType="text" />

// Code xử lý
editText.setOnEditorActionListener((v, actionId, event) -> {
    if (actionId == EditorInfo.IME_ACTION_DONE || 
        actionId == EditorInfo.IME_ACTION_NEXT ||
        (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) {
        hideKeyboard(v);
        // Xử lý submit
        return true;
    }
    return false;
});

Ví dụ hoàn chỉnh

Layout activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="https://schemas.android.com/apk/res/android"
    android:id="@+id/rootView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">

    <EditText
        android:id="@+id/etInput"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="Nhập văn bản..."
        android:imeOptions="actionDone"
        android:inputType="text"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

    <Button
        android:id="@+id/btnHideKeyboard"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="Ẩn bàn phím"
        app:layout_constraintTop_toBottomOf="@id/etInput"
        app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.java

import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    private EditText etInput;
    private View rootView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        etInput = findViewById(R.id.etInput);
        rootView = findViewById(R.id.rootView);
        Button btnHide = findViewById(R.id.btnHideKeyboard);

        // 1. Nút ẩn bàn phím
        btnHide.setOnClickListener(v -> hideKeyboard(etInput));

        // 2. Xử lý nút Done trên keyboard
        etInput.setOnEditorActionListener((v, actionId, event) -> {
            if (actionId == EditorInfo.IME_ACTION_DONE) {
                hideKeyboard(v);
                return true;
            }
            return false;
        });

        // 3. Click ra ngoài để ẩn (cách 1: setOnTouchListener trên root)
        rootView.setOnTouchListener((v, event) -> {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                hideKeyboard(etInput);
            }
            return false; // Quan trọng: false để không chặn touch event của child
        });
    }

    private void hideKeyboard(View view) {
        InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
        if (imm != null) {
            imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
        }
    }
}

Các flag hideSoftInputFromWindow

  • 0: Mặc định, ẩn ngay lập tức
  • HIDE_IMPLICIT_ONLY: Chỉ ẩn nếu không phải explicit show (user không chủ động mở)
  • HIDE_NOT_ALWAYS: Không ẩn nếu view khác cần keyboard

Hiện bàn phím (Programmatically)

public void showKeyboard(EditText editText) {
    editText.requestFocus();
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    if (imm != null) {
        imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
    }
}

// Trong onResume() nếu muốn auto-show:
@Override
protected void onResume() {
    super.onResume();
    etInput.postDelayed(() -> showKeyboard(etInput), 200); // Delay cho layout ready
}

Chạy ứng dụng

App khởi động, EditText focus (nếu manifest stateVisible). Gõ text → Nhấn "Done" trên keyboard hoặc nút "Ẩn bàn phím" hoặc click ra ngoài → Keyboard ẩn.

Lưu ý

  • Luôn check null cho InputMethodManager
  • getWindowToken() cần view đã attach vào window
  • Trong Fragment: requireActivity().getSystemService(...)
  • Dialog: dùng dialog.getWindow().setSoftInputMode(...)
  • Keyboard animation: không thể kiểm soát trực tiếp, dùng adjustResize/adjustPan trong manifest