حذف، نمایش و مدیریت کیبورد اندروید
در این جلسه از سری مباحث آموزش برنامه نویسی اندروید قصد دارم نحوه مخفی کردن و نمایش کیبورد (Keyboard) سیستم عامل اندروید را بررسی کنم. همچنین در ادامه آموزش از کتابخانهای استفاده خواهیم کرد که علاوه بر مخفی کردن و نمایش کیبورد، رویداد مربوطه را به ما اعلام میکند.
مدیریت کیبورد اندروید
به نام خدا. اگر برنامه نویس و توسعه دهنده موبایل و بخصوص اندروید هستید به احتمال زیاد با چالش نمایش کیبورد هنگام عدم نیاز به آن، روبرو شدهاید. یا اینکه بخشی از برنامه شما باید به صورتی پیاده سازی شود که یک یا چند عملیات بر اساس وضعیت کیبورد، یعنی مخفی یا نمایان بودن آن انجام شود.
در این آموزش ابتدا نحوه حذف کیبورد توسط کلاس InputMethodManager را بررسی کرده و در قسمت بعد، با استفاده از کتابخانه KeyboardVisibilityEvent علاوه بر امکان حذف و نمایش کیبورد، یک شنونده (Listener) نیز برای شنود رویداد حذف و ظاهر شدن کیبورد تعریف میکنیم.
طبق مبحث آموزش ساخت پروژه در اندروید استودیو یک پروژه اندرویدی با نام KeyboardManagement میسازم. اکتیویتی را از نوع Empty Activity و زبان را Java انتخاب کردم.
حذف و نمایش کیبورد اندروید توسط کلاس InputMethodManager
برای مثال یک فرم عضویت را درنظر بگیرید. طبیعتا بعد از اینکه کاربر اطلاعات لازم را وارد کرده و روی دکمه ثبت نام ضربه بزند، نیازی به باز ماندن کیبورد نیست و عدم مخفی شدن آن، برای کاربر ایجاد مزاحمت کرده که از لحاظ تجربه کاربری (UX) یک آیتم منفی محسوب میگردد. بنابراین باید کاری کنیم تا به محض کلیک کردن کاربر روی Button ثبت نام، کیبورد مخفی شود.
در layout اکتیویتی سه ویجت از نوع TextView، EditText و Button تعریف میکنم:
activity_main.xml
<?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:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <TextView android:id="@+id/txt_result" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="متن پیش فرض" android:textSize="22sp" /> <EditText android:id="@+id/txt_input" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:id="@+id/submit_btn" android:text="ثبت" /> </LinearLayout>
در مرحله بعد یک Listener برای دکمه تعریف میکنم به صورتی که متن وارد شده در EditText را روی TextView ست میکند:
MainActivity.java
package ir.android_studio.keyboardmanagement; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class MainActivity extends AppCompatActivity { TextView txtResult; EditText txtInput; Button btnSubmit; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); txtResult = findViewById(R.id.txt_result); txtInput = findViewById(R.id.txt_input); btnSubmit = findViewById(R.id.submit_btn); btnSubmit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String userText = txtInput.getText().toString(); txtResult.setText(userText); } }); } }
پروژه را اجرا کرده و یک متن آزمایشی ثبت میکنم:
ملاحظه میکنید بعد از پایان کار همچنان کیبورد نمایش داده میشود.
برای مخفی کردن کیبورد یک متد با نام دلخواه closeKeyboard به اکتیویتی و بعد از متد onCreate اضافه میکنم:
private void closeKeyboard() { View focusView = this.getCurrentFocus(); if (focusView != null) { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(focusView.getWindowToken(), 0); } }
در خط نخست، view ای که روی آن focus (تمرکز) شده را در یک متغیر از جنس View ذخیره میکنم. من نام این متغیر را focusView انتخاب کردم. بنابراین در پروژه فعلی ما، هنگامی که کاربر روی EditText کلیک میکند، این view ذخیره میشود. در ادامه یک شرط تعریف شده که ابتدا بررسی میکند focusView برابر با null نباشد. یعنی چنانچه هیچ view ای در حالت focus قرار نگرفته باشد، کدهای درون این شرط اجرا نخواهد شد.
درون این شرط یک نمونه از کلاس InputMethodManager با نام imm ساختهام. در خط آخر، توسط متد hideSoftInputFromWindow این کلاس، SoftInput یا به عبارتی همان کیبورد (ورودی نرم افزاری) مخفی (hide) میشود.
در نهایت، متد را در Listener دکمه فراخوانی میکنم:
btnSubmit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String userText = txtInput.getText().toString(); txtResult.setText(userText); closeKeyboard(); } });
کد کامل اکتیویتی:
MainActivity.java
package ir.android_studio.keyboardmanagement; import androidx.appcompat.app.AppCompatActivity; import android.content.Context; 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; public class MainActivity extends AppCompatActivity { TextView txtResult; EditText txtInput; Button btnSubmit; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); txtResult = findViewById(R.id.txt_result); txtInput = findViewById(R.id.txt_input); btnSubmit = findViewById(R.id.submit_btn); btnSubmit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String userText = txtInput.getText().toString(); txtResult.setText(userText); closeKeyboard(); } }); } private void closeKeyboard() { View focusView = this.getCurrentFocus(); if (focusView != null) { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(focusView.getWindowToken(), 0); } } }
پروژه را دوباره اجرا میکنم:
حالا بلافاصله بعد از کلیک روی دکمه ثبت، کیبوردی که به واسطه focus شدن روی EditText باز شده بود، مخفی شد.
مدیریت کیبورد اندروید توسط کتابخانه KeyboardVisibilityEvent
در قسمت قبل بدون استفاده از کتابخانه و صرفا توسط کلاس داخلی اندروید، کیبورد را مخفی کردیم. اما در این قسمت برای مدیریت کیبورد نرم افزاری اندروید از کتابخانه KeyboardVisibilityEvent استفاده میکنیم که علاوه بر امکان نمایش دادن یا مخفی کردن کیبورد، به رویداد باز یا بسته شدن کیبورد هم میتوانیم گوش دهیم. یعنی این کتابخانه مخفی و ظاهر شدن کیبورد را گزارش میدهد که در برخی موارد ممکن است توسعه دهنده به آن نیاز داشته باشد.
آدرس معرفی کتابخانه در گیت هاب:
https://github.com/yshrsmz/KeyboardVisibilityEvent
طبق توضیحات صفحه گیت هاب کتابخانه برای افزودن آن به پروژه باید خط زیر را در build.gradle اضافه کنم:
implementation 'net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:LATEST_VERSION'
البته نیاز به نوشتن دستی ورژن کتابخانه نیست و با کلیک روی آن، به این لینک هدایت میشویم که در قسمت Maven build settings (گزینه Gradle) خط زیر نمایش داده میشود:
implementation 'net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:3.0.0-RC2'
پروژه را سینک میکنم تا کتابخانه اضافه شود.
مخفی کردن و نمایش کیبورد
برای مخفی کردن کیبورد کافیست خط زیر را در متد Listener دکمه بجای متد closeKeyboard اضافه کنم:
UIUtil.hideKeyboard(MainActivity.this);
UIUtil یکی از کلاسهای کتابخانه است. متد hideKeyboard این کتابخانه، کیبورد را مخفی میکند. علاوه بر این، متد showKeyboard عمل خلاف متد قبل، یعنی نمایش کیبورد را انجام میدهد. البته در حالت عادی، با focus شدن کاربر روی یک EditText کیبورد به طور خودکار نمایش داده میشود اما ممکن است استثنائاتی وجود داشته باشد که لازم باشد اندروید را وادار به نمایش کیبورد کنیم. این متد بر خلاف متد hideKeyboard که فقط یک پارامتر ورودی دارد، پارامتر دوم هم باید وارد شود که نام EditText مدنظر ماست. این متد را به onCreate اکتیویتی اضافه کردم:
UIUtil.showKeyboard(MainActivity.this, txtInput);
گوش دادن به رویداد حذف یا ظاهر شدن کیبورد
با استفاده از متد setEventListener کلاس KeyboardVisibilityEvent این کتابخانه، به صورت زیر یک متد با نام onVisibilityChanged ساخته میشود:
KeyboardVisibilityEvent.setEventListener(this, new KeyboardVisibilityEventListener() { @Override public void onVisibilityChanged(boolean b) { } }); تغییر وضعیت کیبورد از طریق پارامتر b دریافت میشود. برای نمایش خروجی این متد، یک شرط تعریف میکنم که خروجی هر حالت در قالب یک Toast ظاهر میشود: KeyboardVisibilityEvent.setEventListener(this, new KeyboardVisibilityEventListener() { @Override public void onVisibilityChanged(boolean b) { if (b) { Toast.makeText(MainActivity.this, "کیبورد ظاهر شد", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, "کیبورد حذف شد", Toast.LENGTH_SHORT).show(); } } });
کد کامل اکتیویتی:
MainActivity.java
package ir.android_studio.keyboardmanagement; import androidx.appcompat.app.AppCompatActivity; import android.content.Context; 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 net.yslibrary.android.keyboardvisibilityevent.KeyboardVisibilityEvent; import net.yslibrary.android.keyboardvisibilityevent.KeyboardVisibilityEventListener; import net.yslibrary.android.keyboardvisibilityevent.util.UIUtil; public class MainActivity extends AppCompatActivity { TextView txtResult; EditText txtInput; Button btnSubmit; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); txtResult = findViewById(R.id.txt_result); txtInput = findViewById(R.id.txt_input); btnSubmit = findViewById(R.id.submit_btn); UIUtil.showKeyboard(MainActivity.this, txtInput); btnSubmit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String userText = txtInput.getText().toString(); txtResult.setText(userText); //closeKeyboard(); UIUtil.hideKeyboard(MainActivity.this); } }); KeyboardVisibilityEvent.setEventListener(this, new KeyboardVisibilityEventListener() { @Override public void onVisibilityChanged(boolean b) { if (b) { Toast.makeText(MainActivity.this, "کیبورد ظاهر شد", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, "کیبورد حذف شد", Toast.LENGTH_SHORT).show(); } } }); } private void closeKeyboard() { View focusView = this.getCurrentFocus(); if (focusView != null) { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(focusView.getWindowToken(), 0); imm.showSoftInput(focusView, 0); } } }
پروژه را اجرا میکنم:
مشاهده میکنید پیغامهای “کیبورد ظاهر شد” و “کیبورد حذف شد” در زمان مناسب نمایش داده شده است.
موفق و پیروز باشید.
مطالعهی بیشتر:
https://developer.android.com/reference/android/content/Context#INPUT_METHOD_SERVICE
https://developer.android.com/reference/android/app/Activity#getCurrentFocus()
توجه : سورس پروژه درون پوشه Exercises قرار دارد
تعداد صفحات : ۱۲
حجم : ۱ مگابایت
قیمت : رایگان
دانلود رایگان با حجم ۱ مگابایت لینک کمکی
واقعا خیلی کاربردی و مفید بود. خداقوت….
درود بر جناب مطهری
من توی یک اکتیویتی نیاز دارم با فشردن یک button، کیبورد روی یک editText باز بشه ، ولی نمیدونم مشکل کارم کجاست تا زمانی که روی editText کلیک نکنم کیبورد باز نمیشه
میشه راهنماییم بفرمایید؟
عبارت “open keyboard for editText after click on button” رو گوگل کنید و ببینید راهکارهایی که توسط سایر توسعه دهنده ها ذکر شده کدومش قابل اجرا هست. نتیجه رو هم اینجا بگید بقیه هموطنان استفاده کنن
درود بر جناب مطهری بابت آموزش های فوق الادشون. سپاس گزارم.
سلام خواهشا مباحث نسبتا جدید گوگل رو قرار بدید مثل data binding یا viewmodel ، navigation و …
سلام جناب مطهری
اگر کیبورد روی حالت شماره موبایل باشه یعنی inputType اون edittext از نوع تلفن باشه اول میره روی کیبورد متن بعد دوباره کلیک کنی ایندفعه بسته میشه؟
کد برای این کار نیست؟
سوالی بود یا خبری؟ من تست نکردم
سلام دوست عزیز.
ممنون از مطالب کاربردی و آموزنده ای که با ما به اشتراک میزاری.
عالی بود ⭐❤️