InputMethodManager: API หลัก
InputMethodManager (IMM) เป็น System Service จัดการ Virtual Keyboard (IME) เมธอดหลัก:
hideSoftInputFromWindow(IBinder windowToken, int flags)- ซ่อนคีย์บอร์ดshowSoftInput(View view, int flags)- แสดงคีย์บอร์ดtoggleSoftInput(int showFlags, int hideFlags)- ToggleisAcceptingText()- เช็คว่ารับ Input อยู่ไหม
วิธีซ่อนคีย์บอร์ด (Common Patterns)
1. จาก View ใดๆ (Common)
public static void hideKeyboard(View view) {
if (view == null) return;
InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
// ใช้งาน
hideKeyboard(editText); // หรือ button, rootView, any view in window
2. จาก Activity/Fragment
// Activity
public void hideKeyboard() {
View view = getCurrentFocus();
if (view != null) {
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
// Fragment
public void hideKeyboard() {
View view = requireView().getRootView().findFocus(); // หรือ requireActivity().getCurrentFocus()
if (view != null) {
InputMethodManager imm = (InputMethodManager) requireContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
3. Extension Function (Kotlin)
// View.kt
fun View.hideKeyboard() {
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(windowToken, 0)
}
fun Activity.hideKeyboard() {
currentFocus?.let { it.hideKeyboard() }
}
fun Fragment.hideKeyboard() {
view?.let { it.hideKeyboard() }
}
// ใช้งาน
editText.hideKeyboard()
activity.hideKeyboard()
fragment.hideKeyboard()
การตั้งค่าใน Manifest / XML
1. ปิดคีย์บอร์ดตอนเริ่ม Activity
2. windowSoftInputMode Options
| Value | คำอธิบาย |
|---|---|
| stateHidden | ซ่อนคีย์บอร์ดตอน Activity เริ่ม (Default) |
| stateVisible | แสดงคีย์บอร์ดตอนเริ่ม |
| stateAlwaysHidden | ซ่อนตลอดกาล (แม้ EditText Focus) |
| stateAlwaysVisible | แสดงตลอดกาล |
| stateUnchanged | คงสถานะเดิม |
| adjustResize | Resize Layout ให้พอดีพื้นที่เหลือ (แนะนำ) |
| adjustPan | เลื่อน Layout ขึ้น (เก่า, ไม่แนะนำ) |
| adjustNothing | ไม่ปรับ Layout |
ตัวอย่างครบถ้วน: EditText + Button ซ่อนคีย์บอร์ด
Layout (activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
android:id="@+id/rootLayout"
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="พิมพ์ข้อความ..."
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="ซ่อนคีย์บอร์ด"
app:layout_constraintTop_toBottomOf="@id/etInput"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:id="@+id/tvResult"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="ผลลัพธ์จะแสดงที่นี่"
android:textSize="16sp"
app:layout_constraintTop_toBottomOf="@id/btnHideKeyboard"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
import android.os.Bundle;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private EditText etInput;
private Button btnHideKeyboard;
private TextView tvResult;
private View rootLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etInput = findViewById(R.id.etInput);
btnHideKeyboard = findViewById(R.id.btnHideKeyboard);
tvResult = findViewById(R.id.tvResult);
rootLayout = findViewById(R.id.rootLayout);
// Auto focus และแสดงคีย์บอร์ด (ถ้าต้องการ)
// etInput.requestFocus();
// showKeyboard(etInput);
btnHideKeyboard.setOnClickListener(v -> {
hideKeyboard(v); // ใช้ View ใดก็ได้ใน Window เดียวกัน
String text = etInput.getText().toString().trim();
tvResult.setText("ข้อความที่พิมพ์: " + (text.isEmpty() ? "(ว่าง)" : text));
Toast.makeText(this, "คีย์บอร์ดถูกซ่อนแล้ว", Toast.LENGTH_SHORT).show();
});
// กดที่พื้นที่ว่าง (Root Layout) -> ซ่อนคีย์บอร์ด
rootLayout.setOnClickListener(v -> {
hideKeyboard(v);
etInput.clearFocus(); // เอา Focus ออก
});
}
private void hideKeyboard(View view) {
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
// Optional: แสดงคีย์บอร์ด
private void showKeyboard(View view) {
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
if (imm != null) {
view.requestFocus();
imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
}
}
}
กรณีพิเศษและ Troubleshooting
1. Dialog/BottomSheet: ซ่อนคีย์บอร์ดเมื่อปิด
// DialogFragment
@Override
public void onDismiss(@NonNull DialogInterface dialog) {
super.onDismiss(dialog);
hideKeyboard(); // ใช้ method ด้านบน
}
// BottomSheetDialogFragment
@Override
public void onDismiss(@NonNull DialogInterface dialog) {
View view = getView();
if (view != null) hideKeyboard(view);
super.onDismiss(dialog);
}
2. RecyclerView/ListView: ซ่อนคีย์บอร์ดเวลา Scroll
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
hideKeyboard(recyclerView);
}
}
});
3. คีย์บอร์ดไม่ซ่อน (Common Issues)
- Window Token ผิด: ใช้ View ที่ Attach กับ Window เดียวกัน (getWindowToken() ต้องไม่ null)
- Flags: ลองใช้
InputMethodManager.HIDE_NOT_ALWAYSแทน 0 - Focus: เรียก
view.clearFocus()หลังซ่อน - Dialog: ใช้
dialog.getWindow().setSoftInputMode(...)
4. Android 11+ (API 30): IME Animations
// ควบคุม Animation การซ่อน/แสดง (Inset Animation)
WindowInsetsControllerCompat controller =
WindowCompat.getInsetsController(getWindow(), rootView);
controller.hide(WindowInsetsCompat.Type.ime()); // ซ่อนพร้อม Animation
controller.show(WindowInsetsCompat.Type.ime()); // แสดงพร้อม Animation
// ควบคุม Behavior
controller.setSystemBarsBehavior(
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
);
สรุป Checklist
- ใช้
InputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0) - View ใดก็ได้ใน Window เดียวกันใช้ได้ (Button, RootLayout, EditText เอง)
- Manifest:
android:windowSoftInputMode="stateHidden|adjustResize" - Kotlin: เขียน Extension Function ไว้ใช้ร่วม
- Fragment: ใช้
requireView()หรือrequireActivity() - API 30+: ใช้
WindowInsetsControllerCompatสำหรับ Animation Control