- 레이아웃 & 사용자 인터페이스를 구현합니다.
InputMethodService
를 활용하여 어느 앱에서나 작동하는 두벌식 한글 키보드를 구현합니다.- 키보드에 클립보드와 단축키 기능을 구현합니다.
{behavior}/issue-{number}-{something}
- e.g. :
feature/issue-007-data-module
[{behavior}] {something}
- e.g. :
[FEATURE] 프로젝트 세팅
[ISSUE-{number}] {something}
- e.g. :
[ISSUE-007] 데이터 모듈 추가
- 문장 단위가 아닌, 단어 단위로 제목을 작성합니다.
feat - {something}
: 새로운 기능을 추가했을 때fix - {something}
: 기능 중 버그를 수정했을 때design - {something}
: 디자인 일부를 변경했을 때refactor - {something}
: 코드를 재정비 하였을 때chore - {something}
: 빌드 관련 업무를 수정하거나 패키지 매니저를 수정했을 때docs - {something}
: README와 같은 문서를 변경했을 때- 문장 단위가 아닌, 단어 단위로 제목을 작성합니다.
- android-style-guide의 코딩 컨벤션과 동일하게 진행합니다.
Clean Architecture
, Multi-Module
, MVVM
, Kotlin
, Hilt
, Coroutine
, Room
, Lifecycle
, Databinding
, Livedata
, Timber
Clean Architecture
를 주요 아키텍처 패턴으로 채택 및 구현, 레이어별 모듈 구성Presentation
모듈의 경우MVVM
패턴에 따라 베이스 구현Hilt
모듈 구현Room
데이터베이스 설계 및 구축- 규격화된 폰트 적용을 위해 폰트 리소스 구현
- 제공된 디자인 시스템에 따라 UI 구현
- 버튼 클릭 시
ripple
이펙트가 나타나도록 구현 - 반응형으로 모든 기기에서 동일하게 보여지도록 구현
- 다이얼로그 UI 구현
KakaoTalk_20221013_234717532.mp4
- 기본적인 키보드 ui
private lateinit var qwertyKeyboardLayout: LinearLayout
private val qwertyMainKeyboardText = arrayOf(
arrayOf("1", "2", "3", "4", "5", "6", "7", "8", "9", "0"),
arrayOf("ㅂ", "ㅈ", "ㄷ", "ㄱ", "ㅅ", "ㅛ", "ㅕ", "ㅑ", "ㅐ", "ㅔ"),
arrayOf("ㅁ", "ㄴ", "ㅇ", "ㄹ", "ㅎ", "ㅗ", "ㅓ", "ㅏ", "ㅣ"),
arrayOf(context.getString(R.string.key_shift), "ㅋ", "ㅌ", "ㅊ", "ㅍ", "ㅠ", "ㅜ", "ㅡ", context.getString(R.string.key_back)),
arrayOf(
context.getString(R.string.key_special),
context.getString(R.string.key_short),
",",
context.getString(R.string.key_space),
".",
context.getString(R.string.key_enter)
)
)
private val qwertySubKeyboardText = arrayOf(
arrayOf("ㅃ", "ㅉ", "ㄸ", "ㄲ", "ㅆ", "/", "<", ">", "ㅒ", "ㅖ"),
arrayOf("!", "@", "#", "%", "^", "&", "*", "(", ")"),
arrayOf("", "-", "\'", "\"", ":", ";", ",", "?")
)
- 모든앱에 사용하게 만들기
manifest
<service
android:name=".presentation.keyboard.KeyBoardService"
android:enabled="true"
android:exported="true"
android:label="MyKeyboard"
android:permission="android.permission.BIND_INPUT_METHOD">
<meta-data
android:name="android.view.im"
android:resource="@xml/xml"/>
<intent-filter>
<action android:name="android.view.InputMethod"/>
</intent-filter>
</service>
- 쉬프트 키 눌럿을 때 구현
private fun changeCaps() {
for (keyNum in qwertyMainKeyboardText[SHIFT_CHANGE_LINE].indices) {
val layout = layoutLines[SHIFT_CHANGE_LINE].children.toList()
val mainKeyText = layout[keyNum].findViewById<TextView>(R.id.main_key_text)
if (isCaps) {
...
}
isCaps = !isCaps
}
- 해당 ui에서 글씨를 바꾸게 했습니다.
- CustomKeyboard 앱에서 작동 시연
android-wanted-CustomKeyboardApp_2022-10-14-00-55-19.mp4
- 다른 앱에서 작동 시연
NAVER_2022-10-14-00-55-39.mp4
- 이중 자음, 모음 판별을 위한 확장 함수
DoubleEnableExtension.kt
// 이중 모음 판별
fun Char.isDoubleVowelEnable(c: Char): Char {
when(this) {
'ㅗ' -> {
if (c == 'ㅏ') return 'ㅘ'
if (c == 'ㅐ') return 'ㅙ'
if (c == 'ㅣ') return 'ㅚ'
return ' '
}
'ㅜ' -> {
if (c == 'ㅓ') return 'ㅝ'
if (c == 'ㅔ') return 'ㅞ'
if (c == 'ㅣ') return 'ㅟ'
return ' '
}
'ㅡ' -> {
if (c == 'ㅣ') return 'ㅢ'
return ' '
}
else -> return ' '
}
}
// 이중 자음 판별
fun Char.isDoubleConsonantEnable(c: Char): Char {
// 생략
}
- 한글 키보드 입력 상태 분류
InputState.kt
enum class InputState {
NULL,
CHO,
CHOJUNG,
CHOJUNGJONG
}
- Custom Keyboard으로 입력받은 한글을 조합
- InputMethodService로 사용자가 텍스트를 입력하면 InputConnection 인스턴스를 사용하여 텍스트를 전달
KoreaLanguageMaker.kt
private var choSung: Char = MIN_VALUE
private var jungSung: Char = MIN_VALUE
private var jongSung: Char = MIN_VALUE
private val choSungList: List<Int> = listOf(0x3131, 0x3132, 0x3134, 0x3137, 0x3138, 0x3139, 0x3141,0x3142, 0x3143, 0x3145, 0x3146, 0x3147, 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e)
private val jungSungList:List<Int> = listOf(0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160, 0x3161, 0x3162, 0x3163)
private val jongSungList:List<Int> = listOf(0x0000, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f, 0x3140, 0x3141, 0x3142, 0x3144, 0x3145, 0x3146, 0x3147, 0x3148, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e)
fun makeHangul(): Char { // 한 글자 완성
if (inputState == InputState.NULL) {
return MIN_VALUE
}
if (inputState == InputState.CHO) {
return choSung
}
val choIndex = choSungList.indexOf(choSung.code)
val junIndex = jungSungList.indexOf(jungSung.code)
val jonIndex = jongSungList.indexOf(jongSung.code)
val makeResult = 0xAC00 + 28 * ((21 * choIndex) + junIndex) + jonIndex
return makeResult.toChar()
}
실행영상