یک روش ورودی ایجاد کنید

ویرایشگر روش ورودی (IME) یک کنترل کاربر است که به کاربران اجازه می دهد متن را وارد کنند. Android یک چارچوب روش ورودی توسعه‌یافته ارائه می‌کند که به برنامه‌ها اجازه می‌دهد روش‌های ورودی جایگزینی مانند صفحه‌کلید روی صفحه یا ورودی گفتار را در اختیار کاربران قرار دهند. پس از نصب IME ها، کاربر می تواند یکی از تنظیمات سیستم را انتخاب کرده و در کل سیستم استفاده کند. فقط یک IME را می توان در یک زمان فعال کرد.

برای افزودن یک IME به سیستم Android، یک برنامه Android حاوی کلاسی ایجاد کنید که InputMethodService گسترش دهد. علاوه بر این، شما معمولاً یک فعالیت "تنظیمات" ایجاد می کنید که گزینه ها را به سرویس IME منتقل می کند. همچنین می توانید رابط کاربری تنظیماتی را که به عنوان بخشی از تنظیمات سیستم نمایش داده می شود، تعریف کنید.

این صفحه موضوعات زیر را پوشش می دهد:

اگر با IME کار نکرده‌اید، ابتدا مقاله مقدماتی روش‌های ورودی روی صفحه را بخوانید.

چرخه حیات IME

نمودار زیر چرخه حیات یک IME را شرح می دهد:

تصویری که چرخه زندگی یک IME را نشان می دهد.
شکل 1. چرخه حیات یک IME.

بخش‌های زیر نحوه پیاده‌سازی UI و کد مرتبط با یک IME را که از این چرخه حیات پیروی می‌کند، توضیح می‌دهد.

اجزای IME را در مانیفست اعلام کنید

در سیستم اندروید، IME یک برنامه اندرویدی است که شامل یک سرویس ویژه IME است. فایل مانیفست برنامه باید سرویس را اعلام کند، مجوزهای لازم را درخواست کند، یک فیلتر قصد مطابق با action.view.InputMethod ارائه کند، و متادیتا را ارائه دهد که ویژگی‌های IME را تعریف می‌کند. علاوه بر این، برای ارائه یک رابط تنظیمات که به کاربر اجازه می دهد رفتار IME را تغییر دهد، می توانید یک فعالیت "تنظیمات" را تعریف کنید که می تواند از تنظیمات سیستم راه اندازی شود.

قطعه زیر یک سرویس IME را اعلام می کند. این مجوز BIND_INPUT_METHOD را درخواست می کند تا به سرویس اجازه دهد IME را به سیستم متصل کند، یک فیلتر هدف تنظیم می کند که با عملکرد android.view.InputMethod مطابقت داشته باشد، و ابرداده را برای IME تعریف می کند:

<!-- Declares the input method service. -->
<service android:name="FastInputIME"
    android:label="@string/fast_input_label"
    android:permission="android.permission.BIND_INPUT_METHOD">
    <intent-filter>
        <action android:name="android.view.InputMethod" />
    </intent-filter>
    <meta-data android:name="android.view.im"
               android:resource="@xml/method" />
</service>

قطعه بعدی فعالیت تنظیمات را برای IME اعلام می کند. دارای یک فیلتر هدف برای ACTION_MAIN است که نشان می‌دهد این فعالیت نقطه ورودی اصلی برنامه IME است:

<!-- Optional: an activity for controlling the IME settings. -->
<activity android:name="FastInputIMESettings"
    android:label="@string/fast_input_settings">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
    </intent-filter>
</activity>

همچنین می‌توانید مستقیماً از رابط کاربری آن به تنظیمات IME دسترسی داشته باشید.

API روش ورودی

کلاس‌های مخصوص IME در بسته‌های android.inputmethodservice و android.view.inputmethod یافت می‌شوند. کلاس KeyEvent برای مدیریت کاراکترهای صفحه کلید مهم است.

بخش مرکزی یک IME یک جزء سرویس است - کلاسی که InputMethodService گسترش می دهد. این کلاس علاوه بر پیاده‌سازی چرخه عمر سرویس عادی، برای ارائه رابط کاربری IME شما، مدیریت ورودی کاربر و تحویل متن به فیلدی که فوکوس دارد، تماس‌هایی نیز دارد. به‌طور پیش‌فرض، کلاس InputMethodService بیشتر پیاده‌سازی را برای مدیریت وضعیت و دید IME و برقراری ارتباط با فیلد ورودی فعلی ارائه می‌کند.

کلاس های زیر نیز مهم هستند:

BaseInputConnection
کانال ارتباطی را از یک InputMethod به برنامه‌ای که ورودی آن را دریافت می‌کند، تعریف می‌کند. شما از آن برای خواندن متن در اطراف مکان نما، ارسال متن به جعبه متن و ارسال رویدادهای کلید خام به برنامه استفاده می کنید. برنامه ها باید این کلاس را به جای پیاده سازی رابط پایه InputConnection گسترش دهند.
KeyboardView
یک برنامه افزودنی از View که صفحه کلید را رندر می کند و به رویدادهای ورودی کاربر پاسخ می دهد. چیدمان صفحه کلید توسط نمونه ای از Keyboard مشخص می شود که می توانید آن را در یک فایل XML تعریف کنید.

UI روش ورودی را طراحی کنید

دو عنصر بصری اصلی برای یک IME وجود دارد: نمای ورودی و نمای کاندیدا . شما فقط باید عناصری را پیاده سازی کنید که با روش ورودی که طراحی می کنید مرتبط هستند.

نمای ورودی

نمای ورودی رابط کاربری است که در آن کاربر متن را به صورت کلیک کلید، دست خط یا اشاره وارد می کند. هنگامی که IME برای اولین بار نمایش داده می شود، سیستم onCreateInputView() را فراخوانی می کند. در اجرای این روش، طرحی را که می خواهید در پنجره IME نمایش دهید ایجاد کنید و طرح را به سیستم برگردانید. قطعه زیر نمونه ای از پیاده سازی متد onCreateInputView() را نشان می دهد:

کاتلین

override fun onCreateInputView(): View {
    return layoutInflater.inflate(R.layout.input, null).apply {
        if (this is MyKeyboardView) {
            setOnKeyboardActionListener(this@MyInputMethod)
            keyboard = latinKeyboard
        }
    }
}

جاوا

@Override
public View onCreateInputView() {
    MyKeyboardView inputView =
        (MyKeyboardView) getLayoutInflater().inflate(R.layout.input, null);

    inputView.setOnKeyboardActionListener(this);
    inputView.setKeyboard(latinKeyboard);

    return inputView;
}

در این مثال، MyKeyboardView نمونه‌ای از پیاده‌سازی سفارشی KeyboardView است که یک Keyboard ارائه می‌کند.

مشاهده نامزدها

نمای نامزدها رابط کاربری است که در آن IME اصلاحات یا پیشنهادات بالقوه کلمه را برای کاربر نمایش می دهد. در چرخه حیات IME، زمانی که سیستم برای نمایش نمای نامزدها آماده باشد onCreateCandidatesView() فرا می خواند. در اجرای این روش، طرحی را برگردانید که پیشنهادات کلمه را نشان می دهد، یا اگر نمی خواهید چیزی نشان داده شود، null را برگردانید. پاسخ تهی رفتار پیش‌فرض است، بنابراین در صورت عدم ارائه پیشنهاد، نیازی به اجرای آن ندارید.

ملاحظات طراحی رابط کاربری

این بخش برخی از ملاحظات طراحی UI برای IME ها را شرح می دهد.

اندازه های صفحه نمایش متعدد را مدیریت کنید

UI برای IME شما باید بتواند برای اندازه های مختلف صفحه نمایش مقیاس بندی کند و هم جهت افقی و هم عمودی را مدیریت کند. در حالت IME غیر تمام صفحه، فضای کافی برای برنامه برای نمایش فیلد متن و هر زمینه مرتبط با آن بگذارید، به طوری که بیش از نیمی از صفحه توسط IME اشغال نشود. در حالت تمام صفحه IME، این یک مشکل نیست.

انواع مختلف ورودی را مدیریت کنید

فیلدهای متنی Android به شما امکان می دهد نوع ورودی خاصی مانند متن آزاد، اعداد، URL ها، آدرس های ایمیل و رشته های جستجو را تنظیم کنید. هنگامی که یک IME جدید را پیاده سازی می کنید، نوع ورودی هر فیلد را شناسایی کرده و رابط مناسب را برای آن فراهم کنید. با این حال، لازم نیست IME خود را تنظیم کنید تا بررسی کنید آیا کاربر متن معتبری را برای نوع ورودی وارد می کند یا خیر. این مسئولیت بر عهده برنامه ای است که دارای فیلد متنی است.

به عنوان مثال، در اینجا رابطی است که IME لاتین برای ورودی متن پلت فرم اندروید ارائه می کند:

تصویری که ورودی متن را در یک IME لاتین نشان می دهد
شکل 2. ورودی متن لاتین IME.

و اینجا رابطی است که IME لاتین برای ورودی عددی پلتفرم اندروید ارائه می کند:

تصویری که یک ورودی عددی را در یک IME لاتین نشان می دهد
شکل 3. ورودی عددی لاتین IME.

وقتی یک فیلد ورودی فوکوس دریافت می‌کند و IME شما شروع می‌شود، سیستم onStartInputView() را فراخوانی می‌کند و یک شی EditorInfo ارسال می‌کند که حاوی جزئیات مربوط به نوع ورودی و سایر ویژگی‌های فیلد متنی است. در این شی، فیلد inputType شامل نوع ورودی فیلد متنی است.

فیلد inputType یک int است که شامل الگوهای بیت برای تنظیمات مختلف نوع ورودی است. برای آزمایش آن برای نوع ورودی فیلد متن، آن را با ثابت TYPE_MASK_CLASS ماسک کنید، مانند این:

کاتلین

inputType and InputType.TYPE_MASK_CLASS

جاوا

inputType & InputType.TYPE_MASK_CLASS

الگوی بیت نوع ورودی می تواند یکی از چندین مقدار داشته باشد، از جمله:

TYPE_CLASS_NUMBER
فیلد متنی برای وارد کردن اعداد. همانطور که در شکل 3 نشان داده شده است، IME لاتین یک صفحه شماره برای فیلدهایی از این نوع نمایش می دهد.
TYPE_CLASS_DATETIME
یک فیلد متنی برای وارد کردن تاریخ و زمان.
TYPE_CLASS_PHONE
فیلد متنی برای وارد کردن شماره تلفن.
TYPE_CLASS_TEXT
یک فیلد متنی برای وارد کردن هر کاراکتر پشتیبانی شده.

این ثابت ها با جزئیات بیشتری در مستندات مرجع برای InputType توضیح داده شده اند.

فیلد inputType می‌تواند حاوی بیت‌های دیگری باشد که نشان‌دهنده گونه‌ای از نوع فیلد متنی است، مانند:

TYPE_TEXT_VARIATION_PASSWORD
نوعی از TYPE_CLASS_TEXT برای وارد کردن رمزهای عبور. روش ورودی، dingbats را به جای متن واقعی نمایش می دهد.
TYPE_TEXT_VARIATION_URI
نوعی از TYPE_CLASS_TEXT برای وارد کردن URL های وب و سایر شناسه های منبع یکنواخت (URI).
TYPE_TEXT_FLAG_AUTO_COMPLETE
گونه ای از TYPE_CLASS_TEXT برای وارد کردن متنی که برنامه به طور خودکار از فرهنگ لغت، جستجو یا امکانات دیگر تکمیل می کند.

هنگام آزمایش این انواع inputType با ثابت مناسب پوشش دهید. ثابت‌های ماسک موجود در مستندات مرجع برای InputType فهرست شده‌اند.

ارسال متن به برنامه

همانطور که کاربر متن را با IME شما وارد می کند، می توانید با ارسال رویدادهای کلیدی جداگانه یا با ویرایش متن اطراف مکان نما در قسمت متن برنامه، متن را به برنامه ارسال کنید. در هر صورت، از یک نمونه از InputConnection برای تحویل متن استفاده کنید. برای دریافت این نمونه، InputMethodService.getCurrentInputConnection() را فراخوانی کنید.

متن اطراف مکان نما را ویرایش کنید

هنگامی که ویرایش متن موجود را انجام می دهید، برخی از روش های مفید در BaseInputConnection به شرح زیر است:

getTextBeforeCursor()
یک CharSequence حاوی تعداد نویسه‌های درخواستی قبل از موقعیت مکان‌نمای فعلی را برمی‌گرداند.
getTextAfterCursor()
یک CharSequence حاوی تعداد کاراکترهای درخواستی را به دنبال موقعیت مکان نما برمی‌گرداند.
deleteSurroundingText()
تعداد مشخص شده نویسه را قبل و بعد از موقعیت مکان نما فعلی حذف می کند.
commitText()
یک CharSequence به فیلد متنی متعهد می کند و یک مکان مکان نما جدید تعیین می کند.

به عنوان مثال، قطعه زیر نشان می دهد که چگونه چهار کاراکتر سمت چپ مکان نما را با متن "Hello!" جایگزین کنید:

کاتلین

currentInputConnection.also { ic: InputConnection ->
    ic.deleteSurroundingText(4, 0)
    ic.commitText("Hello", 1)
    ic.commitText("!", 1)
}

جاوا

InputConnection ic = getCurrentInputConnection();
ic.deleteSurroundingText(4, 0);
ic.commitText("Hello", 1);
ic.commitText("!", 1);

از نوشتن متن قبل از ارتکاب پشتیبانی کنید

اگر IME شما متن را پیش‌بینی می‌کند یا برای نوشتن یک علامت یا کلمه به چندین مرحله نیاز دارد، می‌توانید پیشرفت را در قسمت متن نشان دهید تا زمانی که کاربر کلمه را متعهد کند و سپس می‌توانید ترکیب جزئی را با متن تکمیل‌شده جایگزین کنید. وقتی متن را به setComposingText() می‌فرستید، می‌توانید با افزودن یک span به متن، رفتار خاصی را به آن بدهید.

قطعه زیر نحوه نمایش پیشرفت در یک فیلد متنی را نشان می دهد:

کاتلین

currentInputConnection.also { ic: InputConnection ->
    ic.setComposingText("Composi", 1)
    ic.setComposingText("Composin", 1)
    ic.commitText("Composing ", 1)
}

جاوا

InputConnection ic = getCurrentInputConnection();
ic.setComposingText("Composi", 1);
ic.setComposingText("Composin", 1);
ic.commitText("Composing ", 1);

رهگیری رویدادهای کلیدی سخت افزاری

اگرچه پنجره روش ورودی فوکوس واضحی ندارد، ابتدا رویدادهای کلیدی سخت افزاری را دریافت می کند و می تواند آنها را مصرف کند یا به برنامه ارسال کند. به عنوان مثال، ممکن است بخواهید از کلیدهای جهت دار برای پیمایش در UI خود برای انتخاب نامزد در طول ترکیب استفاده کنید. همچنین ممکن است بخواهید کلید بازگشت را به دام بیاندازید تا هر گفتگوی منشأ گرفته از پنجره روش ورودی را رد کنید.

برای رهگیری کلیدهای سخت افزاری، onKeyDown() و onKeyUp() را لغو کنید.

متد super() را برای کلیدهایی که نمی خواهید خودتان کنترل کنید، فراخوانی کنید.

یک زیرنوع IME ایجاد کنید

زیرگروه‌ها به IME اجازه می‌دهند حالت‌ها و زبان‌های ورودی متعددی را که توسط یک IME پشتیبانی می‌شوند، نمایش دهد. یک زیرگروه می تواند نشان دهنده موارد زیر باشد:

  • محلی، مانند en_US یا fr_FR
  • یک حالت ورودی، مانند صدا، صفحه کلید، یا دست خط
  • سایر سبک‌های ورودی، فرم‌ها یا ویژگی‌های خاص IME، مانند طرح‌بندی صفحه‌کلید 10 کلیدی یا QWERTY

حالت می تواند هر متنی باشد، مانند "صفحه کلید" یا "صدا". یک زیرمجموعه همچنین می‌تواند ترکیبی از این موارد را نشان دهد.

اطلاعات نوع فرعی برای گفتگوی تعویض کننده IME که از نوار اعلان و تنظیمات IME در دسترس است استفاده می شود. این اطلاعات همچنین به چارچوب اجازه می‌دهد تا زیرنوع خاصی از یک IME را مستقیماً بیاورد. هنگامی که یک IME می سازید، از تسهیلات subtype استفاده کنید، زیرا به کاربر کمک می کند زبان ها و حالت های مختلف IME را شناسایی کرده و بین آنها سوئیچ کند.

با استفاده از عنصر <subtype> ، انواع فرعی را در یکی از فایل های منبع XML روش ورودی تعریف کنید. قطعه کد زیر یک IME را با دو نوع فرعی تعریف می‌کند: یک زیرگروه صفحه کلید برای زبان انگلیسی ایالات متحده و یک زیرنوع صفحه کلید دیگر برای زبان فرانسه برای زبان فرانسه:

<input-method xmlns:android="http://schemas.android.com/apk/res/android"
        android:settingsActivity="com.example.softkeyboard.Settings"
        android:icon="@drawable/ime_icon">
    <subtype android:name="@string/display_name_english_keyboard_ime"
            android:icon="@drawable/subtype_icon_english_keyboard_ime"
            android:languageTag="en-US"
            android:imeSubtypeMode="keyboard"
            android:imeSubtypeExtraValue="somePrivateOption=true" />
    <subtype android:name="@string/display_name_french_keyboard_ime"
            android:icon="@drawable/subtype_icon_french_keyboard_ime"
            android:languageTag="fr-FR"
            android:imeSubtypeMode="keyboard"
            android:imeSubtypeExtraValue="someVariable=30,someInternalOption=false" />
    <subtype android:name="@string/display_name_german_keyboard_ime" ... />
</input-method>

برای اطمینان از اینکه زیرگروه‌های شما به درستی در UI برچسب‌گذاری شده‌اند، از «%s» استفاده کنید تا یک برچسب فرعی که همان برچسب محلی نوع فرعی است، دریافت کنید. این در دو قطعه کد بعدی نشان داده شده است. اولین قطعه بخشی از فایل XML روش ورودی را نشان می دهد:

<subtype
    android:label="@string/label_subtype_generic"
    android:imeSubtypeLocale="en_US"
    android:icon="@drawable/icon_en_us"
    android:imeSubtypeMode="keyboard" />

قطعه بعدی بخشی از فایل strings.xml IME است. منبع رشته label_subtype_generic ، که توسط تعریف UI روش ورودی برای تنظیم برچسب نوع فرعی استفاده می‌شود، به صورت زیر تعریف می‌شود:

<string name="label_subtype_generic">%s</string>

این تنظیم باعث می شود که نام نمایشی نوع فرعی با تنظیمات محلی مطابقت داشته باشد. به عنوان مثال، در هر زبان انگلیسی، نام نمایشی "English (ایالات متحده آمریکا)" است.

زیر انواع IME را از نوار اعلان انتخاب کنید

سیستم اندروید همه زیرشاخه‌های افشا شده توسط همه IMEها را مدیریت می‌کند. زیرگروه های IME به عنوان حالت های IME که به آن تعلق دارند در نظر گرفته می شوند. همانطور که در شکل زیر نشان داده شده است، کاربر می تواند از نوار اعلان یا برنامه تنظیمات به منوی زیرگروه های IME موجود پیمایش کند:

تصویری که منوی زبان‌ها و ورودی سیستم را نشان می‌دهد
شکل 4. منوی زبان ها و سیستم ورودی .

زیر انواع IME را از تنظیمات سیستم انتخاب کنید

کاربر همچنین می‌تواند نحوه استفاده از زیرگروه‌ها را در پانل تنظیمات زبان و ورودی در تنظیمات سیستم کنترل کند:

تصویری که منوی انتخاب زبان ها را نشان می دهد
شکل 5. منوی سیستم زبان ها

جابه‌جایی بین زیرگروه‌های IME

می‌توانید با ارائه یک کلید جابجایی، مانند نماد زبان کره‌ای روی صفحه‌کلید، به کاربران اجازه دهید به راحتی بین انواع فرعی IME جابجا شوند. این قابلیت استفاده از صفحه کلید را بهبود می بخشد و برای کاربر راحت است. برای فعال کردن این تغییر، مراحل زیر را انجام دهید:

  1. در فایل های منبع XML روش ورودی supportsSwitchingToNextInputMethod = "true" را اعلام کنید. اعلان شما باید شبیه قطعه کد زیر باشد:
    <input-method xmlns:android="http://schemas.android.com/apk/res/android"
            android:settingsActivity="com.example.softkeyboard.Settings"
            android:icon="@drawable/ime_icon"
            android:supportsSwitchingToNextInputMethod="true">
    
  2. متد shouldOfferSwitchingToNextInputMethod() را فراخوانی کنید.
  3. اگر روش true را برگرداند، یک کلید سوئیچینگ نمایش دهید.
  4. هنگامی که کاربر روی کلید سوئیچینگ ضربه می‌زند، switchToNextInputMethod() را فراخوانی می‌کند که false است. مقدار false به سیستم می‌گوید که همه زیرگروه‌ها را بدون در نظر گرفتن اینکه به کدام IME تعلق دارند، یکسان رفتار کند. تعیین true مستلزم چرخش سیستم در میان انواع فرعی در IME فعلی است.

ملاحظات عمومی IME

در اینجا موارد دیگری وجود دارد که باید هنگام پیاده سازی IME خود در نظر بگیرید:

  • راهی برای کاربران فراهم کنید تا گزینه‌ها را مستقیماً از رابط کاربری IME تنظیم کنند.
  • راهی را برای کاربران فراهم کنید تا مستقیماً از رابط کاربری روش ورودی به IME دیگری تغییر کنند، زیرا ممکن است چندین IME روی دستگاه نصب شده باشد.
  • رابط کاربری IME را به سرعت مطرح کنید. هر منبع بزرگی را از قبل بارگیری یا بارگیری کنید تا کاربران به محض ضربه زدن روی یک فیلد متن، IME را ببینند. منابع و نماهای کش برای فراخوانی های بعدی روش ورودی.
  • بلافاصله پس از پنهان شدن پنجره روش ورودی، تخصیص حافظه بزرگ را آزاد کنید تا برنامه ها حافظه کافی برای اجرا داشته باشند. اگر IME برای چند ثانیه مخفی شد، از پیام تاخیری برای انتشار منابع استفاده کنید.
  • اطمینان حاصل کنید که کاربران می‌توانند تا حد ممکن نویسه‌ها را برای زبان یا محلی مرتبط با IME وارد کنند. کاربران ممکن است از علائم نگارشی در گذرواژه‌ها یا نام‌های کاربری استفاده کنند، بنابراین IME شما باید کاراکترهای مختلفی را ارائه کند تا به کاربران اجازه دهد رمز عبور را وارد کرده و به دستگاه دسترسی داشته باشند.