입력 방법 만들기

입력 방식 편집기 (IME)는 사용자가 텍스트를 입력할 수 있는 사용자 컨트롤입니다. Android는 애플리케이션이 터치 키보드나 음성 입력과 같은 대체 입력 방법을 사용자에게 제공할 수 있는 확장 가능한 입력 방법 프레임워크를 제공합니다. 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.inputmethodserviceandroid.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
        }
    }
}

Java

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

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

    return inputView;
}

이 예에서 MyKeyboardViewKeyboard를 렌더링하는 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

Java

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)
}

Java

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

커밋 전 텍스트 작성 지원

IME가 텍스트를 예측하거나 글리프 또는 단어를 작성하는 데 여러 단계가 필요한 경우 사용자가 단어를 커밋할 때까지 텍스트 필드에 진행 상황을 표시한 다음 부분 구성을 완성된 텍스트로 바꿀 수 있습니다. setComposingText()에 텍스트를 전달할 때 스팬을 추가하여 텍스트를 특별하게 처리할 수 있습니다.

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

Kotlin

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

Java

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를 빌드할 때 하위유형 기능을 사용하세요. 사용자가 여러 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 파일의 일부입니다. 문자열 리소스 label_subtype_generic은 입력 방법 UI 정의에서 하위유형의 라벨을 설정하는 데 사용되며 다음과 같이 정의됩니다.

<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는 사용자가 비밀번호를 입력하고 기기에 액세스할 수 있도록 다양한 문자를 제공해야 합니다.