입력 방법 만들기

입력 방식 편집기 (IME)는 사용자가 텍스트를 입력할 수 있는 사용자 컨트롤입니다. Android는 애플리케이션이 사용자에게 터치 키보드나 음성 입력과 같은 대체 입력 방법을 제공할 수 있도록 확장 가능한 입력 방식 프레임워크를 제공합니다. IME를 설치한 후 사용자는 시스템 설정에서 IME를 선택하고 전체 시스템에서 사용할 수 있습니다. 한 번에 하나의 IME만 사용 설정할 수 있습니다.

Android 시스템에 IME를 추가하려면 InputMethodService를 확장하는 클래스가 포함된 Android 애플리케이션을 만듭니다. 또한 일반적으로 옵션을 IME 서비스에 전달하는 '설정' 활동을 만듭니다. 시스템 설정의 일부로 표시되는 설정 UI를 정의할 수도 있습니다.

이 페이지에서는 다음 주제에 대해 설명합니다.

IME를 사용해 본 적이 없다면 먼저 입문용 도움말인 화면 입력 방식을 읽어보세요.

IME 수명 주기

다음 다이어그램은 IME의 수명 주기를 보여줍니다.

IME의 수명 주기를 보여주는 이미지
그림 1. IME의 수명 주기

다음 섹션에서는 이 수명 주기를 따르는 IME와 연결된 UI 및 코드를 구현하는 방법을 설명합니다.

매니페스트에서 IME 구성요소 선언

Android 시스템에서 IME는 특수 IME 서비스가 포함된 Android 애플리케이션입니다. 애플리케이션의 매니페스트 파일은 서비스를 선언하고, 필요한 권한을 요청하고, action.view.InputMethod 작업과 일치하는 인텐트 필터를 제공하고, IME의 특성을 정의하는 메타데이터를 제공해야 합니다. 또한 사용자가 IME의 동작을 수정할 수 있는 설정 인터페이스를 제공하기 위해 시스템 설정에서 실행할 수 있는 '설정' 활동을 정의할 수 있습니다.

다음 스니펫은 IME 서비스를 선언합니다. 서비스가 IME를 시스템에 연결할 수 있도록 BIND_INPUT_METHOD 권한을 요청하고, 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의 설정 활동을 선언합니다. 이 활동이 IME 애플리케이션의 기본 진입점임을 나타내는 ACTION_MAIN의 인텐트 필터가 있습니다.

<!-- 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>

UI에서 직접 IME 설정에 대한 액세스 권한을 제공할 수도 있습니다.

입력 방법 API

IME 관련 클래스는 android.inputmethodservice 및 android.view.inputmethod 패키지에 있습니다. KeyEvent 클래스는 키보드 문자를 처리하는 데 중요합니다.

IME의 핵심 부분은 서비스 구성요소, 즉 InputMethodService를 확장하는 클래스입니다. 이 클래스는 일반적인 서비스 수명 주기를 구현하는 것 외에도 IME의 UI를 제공하고 사용자 입력을 처리하며 포커스가 있는 필드에 텍스트를 전달하는 콜백을 포함합니다. 기본적으로 InputMethodService 클래스는 IME의 상태와 공개 상태를 관리하고 현재 입력란과 통신하는 대부분의 구현을 제공합니다.

다음 클래스도 중요합니다.

BaseInputConnection
InputMethod에서 입력을 수신하는 애플리케이션으로의 통신 채널을 정의합니다. 커서 주위의 텍스트를 읽고 텍스트 상자에 텍스트를 커밋하며 원시 키 이벤트를 애플리케이션에 전송하는 데 사용합니다. 애플리케이션은 기본 인터페이스 InputConnection를 구현하는 대신 이 클래스를 확장해야 합니다.
KeyboardView
키보드를 렌더링하고 사용자 입력 이벤트에 응답하는 View의 확장 프로그램입니다. 키보드 레이아웃은 XML 파일에서 정의할 수 있는 Keyboard 인스턴스로 지정됩니다.

입력 방법 UI 디자인

IME에는 입력 뷰와 후보 뷰라는 두 가지 주요 시각적 요소가 있습니다. 설계 중인 입력 방식과 관련된 요소만 구현하면 됩니다.

입력 뷰

입력 뷰는 사용자가 키 클릭, 필기 입력, 동작 등의 형태로 텍스트를 입력하는 UI입니다. IME가 처음 표시되면 시스템은 onCreateInputView() 콜백을 호출합니다. 이 메서드를 구현할 때 IME 창에 표시할 레이아웃을 만들고 레이아웃을 시스템에 반환합니다. 다음 스니펫은 onCreateInputView() 메서드를 구현하는 예시를 보여줍니다.

Kotlin

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는 Keyboard를 렌더링하는 KeyboardView의 커스텀 구현 인스턴스입니다.

후보군 뷰

후보 뷰는 IME가 사용자가 선택할 수 있는 잠재적인 단어 수정 또는 추천을 표시하는 UI입니다. IME 수명 주기에서 시스템은 추천 단어 뷰를 표시할 준비가 되면 onCreateCandidatesView()를 호출합니다. 이 메서드를 구현할 때 단어 추천을 표시하는 레이아웃을 반환하거나 아무것도 표시하지 않으려면 null을 반환합니다. null 응답은 기본 동작이므로 추천을 제공하지 않는 경우 이를 구현할 필요가 없습니다.

UI 디자인 고려사항

이 섹션에서는 IME의 몇 가지 UI 디자인 고려사항을 설명합니다.

여러 화면 크기 처리

IME의 UI는 다양한 화면 크기에 맞게 확장할 수 있어야 하며 가로 모드와 세로 모드 방향을 모두 처리할 수 있어야 합니다. 전체 화면이 아닌 IME 모드에서는 애플리케이션이 텍스트 필드와 관련 컨텍스트를 표시할 수 있도록 충분한 공간을 남겨두어 화면의 절반 이상을 IME가 차지하지 않도록 합니다. 전체 화면 IME 모드에서는 문제가 되지 않습니다.

다양한 입력 유형 처리

Android 텍스트 필드를 사용하면 자유 형식 텍스트, 숫자, URL, 이메일 주소, 검색 문자열과 같은 특정 입력 유형을 설정할 수 있습니다. 새 IME를 구현할 때는 각 필드의 입력 유형을 감지하고 이에 적합한 인터페이스를 제공합니다. 하지만 사용자가 입력 유형에 유효한 텍스트를 입력하는지 확인하도록 IME를 설정할 필요는 없습니다. 이는 텍스트 필드를 소유한 애플리케이션의 책임입니다.

예를 들어 다음은 라틴어 IME가 Android 플랫폼 텍스트 입력에 제공하는 인터페이스입니다.

라틴어 IME의 텍스트 입력을 보여주는 이미지
그림 2. 라틴어 IME 텍스트 입력

다음은 라틴어 IME가 Android 플랫폼 숫자 입력에 제공하는 인터페이스입니다.

라틴어 IME의 숫자 입력을 보여주는 이미지
그림 3. 라틴어 IME 숫자 입력

입력 필드가 포커스를 받고 IME가 시작되면 시스템은 onStartInputView()를 호출하여 입력 유형 및 텍스트 필드의 기타 속성에 관한 세부정보가 포함된 EditorInfo 객체를 전달합니다. 이 객체에서 inputType 필드에는 텍스트 필드의 입력 유형이 포함됩니다.

inputType 필드는 다양한 입력 유형 설정의 비트 패턴을 포함하는 int입니다. 텍스트 필드의 입력 유형을 테스트하려면 다음과 같이 상수 TYPE_MASK_CLASS로 마스킹합니다.

Kotlin

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의 변형입니다. 입력 방식은 실제 텍스트 대신 딩뱃을 표시합니다.
TYPE_TEXT_VARIATION_URI
웹 URL 및 기타 URI (Uniform Resource Identifier)를 입력하기 위한 TYPE_CLASS_TEXT의 변형입니다.
TYPE_TEXT_FLAG_AUTO_COMPLETE
애플리케이션이 사전, 검색 또는 기타 기능에서 자동 완성하는 텍스트를 입력하기 위한 TYPE_CLASS_TEXT의 변형입니다.

이러한 변이를 테스트할 때 적절한 상수로 inputType를 마스킹합니다. 사용 가능한 마스크 상수는 InputType의 참고 문서에 나열되어 있습니다.

애플리케이션에 텍스트 전송

사용자가 IME로 텍스트를 입력하면 개별 키 이벤트를 전송하거나 애플리케이션의 텍스트 필드에서 커서 주변의 텍스트를 수정하여 애플리케이션에 텍스트를 전송할 수 있습니다. 두 경우 모두 InputConnection 인스턴스를 사용하여 텍스트를 전달합니다. 이 인스턴스를 가져오려면 InputMethodService.getCurrentInputConnection()를 호출합니다.

커서 주위 텍스트 수정

기존 텍스트의 수정을 처리할 때 BaseInputConnection의 몇 가지 유용한 메서드는 다음과 같습니다.

getTextBeforeCursor()
현재 커서 위치 앞에 요청된 문자 수가 포함된 CharSequence를 반환합니다.
getTextAfterCursor()
현재 커서 위치 다음에 요청된 문자 수가 포함된 CharSequence를 반환합니다.
deleteSurroundingText()
현재 커서 위치 앞뒤로 지정된 수의 문자를 삭제합니다.
commitText()
CharSequence를 텍스트 필드에 커밋하고 새 커서 위치를 설정합니다.

예를 들어 다음 스니펫은 커서 왼쪽의 문자 4개를 'Hello!' 텍스트로 바꾸는 방법을 보여줍니다.

Kotlin

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을 추가하여 텍스트를 특별하게 처리할 수 있습니다.

다음 스니펫은 텍스트 필드에 진행 상황을 표시하는 방법을 보여줍니다.

Kotlin

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)
  • 입력 모드(예: 음성, 키보드, 필기 입력)
  • 10키 또는 QWERTY 키보드 레이아웃과 같은 IME 관련 기타 입력 스타일, 양식 또는 속성

모드는 '키보드' 또는 '음성'과 같은 텍스트일 수 있습니다. 하위 유형은 이러한 조합을 노출할 수도 있습니다.

하위유형 정보는 알림 표시줄에서 사용할 수 있는 IME 전환기 대화상자와 IME 설정에 사용됩니다. 또한 이 정보를 통해 프레임워크는 IME의 특정 하위유형을 직접 표시할 수 있습니다. IME를 빌드할 때는 하위유형 기능을 사용하세요. 이 기능은 사용자가 다양한 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" />

다음 스니펫은 IME의 strings.xml 파일의 일부입니다. 입력 방법 UI 정의에서 하위유형의 라벨을 설정하는 데 사용하는 문자열 리소스 label_subtype_generic는 다음과 같이 정의됩니다.

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

이 설정으로 인해 하위유형의 표시 이름이 언어 설정과 일치하게 됩니다. 예를 들어 영어 언어에서 표시 이름은 '영어 (미국)'입니다.

알림바에서 IME 하위유형 선택

Android 시스템은 모든 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의 UI에서 직접 옵션을 설정할 수 있는 방법을 제공합니다.
  • 기기에 여러 IME가 설치되어 있을 수 있으므로 사용자가 입력 방식 UI에서 직접 다른 IME로 전환할 수 있는 방법을 제공합니다.
  • IME UI를 빠르게 불러옵니다. 사용자가 텍스트 필드를 탭하는 즉시 IME가 표시되도록 대규모 리소스를 미리 로드하거나 필요에 따라 로드합니다. 입력 방법의 후속 호출을 위한 리소스와 뷰를 캐시합니다.
  • 입력 방식 창이 숨겨진 직후에 대규모 메모리 할당을 해제하여 애플리케이션에 실행할 메모리가 충분하도록 합니다. IME가 몇 초 동안 숨겨져 있으면 지연된 메시지를 사용하여 리소스를 해제합니다.
  • 사용자가 IME와 연결된 언어 또는 언어에 최대한 많은 문자를 입력할 수 있는지 확인합니다. 사용자는 비밀번호나 사용자 이름에 구두점을 사용할 수 있으므로 IME는 사용자가 비밀번호를 입력하고 기기에 액세스할 수 있도록 다양한 문자를 제공해야 합니다.