# Android의 부동 창 1개: Jetpack Compose & Room

Facebook Heads와 다른 앱에서 사용하는 부동 창을 어떻게 만드는지 생각해 보셨나요?너는 너의 응용 프로그램에서 같은 기술을 사용할 생각을 했니?이것은 매우 간단하다. 나는 너에게 전체 과정을 완성하도록 지도할 것이다.
나는 Floating Apps의 저자이다.구글플레이에서 동종 앱 최초로 다운로드 800만 뷰를 넘긴 가장 인기 있는 앱이다.6년간의 응용 개발을 거쳐 나는 그것에 대해 어느 정도 알고 있다.때때로 나는 몇 달 동안 문서와 안드로이드 소스 코드를 읽고 실험을 했다.나는 수만 명의 사용자의 피드백을 받았고, 서로 다른 버전의 안드로이드 휴대전화에서 각양각색의 문제를 보았다.
다음은 내가 가는 길에 배운 것이다.
이 문서에서 Jetpack Compose와 Room을 사용하여 간단한 기본 응용 프로그램을 구축하는 방법을 알려드리겠습니다.

생각
우리는 부동 기술을 응용할 생각이 필요하다.빠르게 필기를 할 수 있는 프로그램을 만듭니다.이것은 완벽한 사례다.빨리 필기를 하기 위해서, 너는 보통 현재의 임무를 떠나고 싶지 않다.
우리는 그것을 장기적으로 운영하는 서비스로 실현하고, 필요할 때 서비스를 제공할 준비가 되어 있다는 영구적인 통지를 가지고 있다.사용자는 우리의 알림을 클릭하고 주석을 추가하기 시작합니다.
너의 응용에 대해 너는 이런 행위를 바꿀 수 있다.장기 운행이 필요 없는 서비스.

기본 응용 프로그램
우리는 구걸부터 시작해야 한다.우선 메인 응용 프로그램을 구축합시다.그것은 우리가 실제 장면에서 집적 과정을 보여줄 수 있게 한다.
나는 Kotlin, Jetpack ComposeRoom를 사용하고 매우 간단한 필기 프로그램을 구축하기로 결정했다.
참고로 Jetpack Compose는 현재 안정적인 버전에서는 사용할 수 없기 때문에 Android Studio Canary를 설치해야 합니다.

방.
Room 지속성 라이브러리는 SQLite에 추상적인 층을 제공하여 더욱 건장한 데이터베이스에 접근할 수 있도록 하고 SQLite의 모든 기능을 이용한다.
간단한 솔리드로 시작하겠습니다.
@Entity  
data class Note(  
  @PrimaryKey val id: Int,  
  @ColumnInfo(name = "content") val content: String  
)
및 해당 도:
@Dao  
interface NotesDao {  

  @Query("SELECT * FROM note")  
  fun getAll(): List<Note>  

  @Insert  
  fun insert(note: Note)  

  @Delete  
  fun delete(note: Note)  

}
액세스 데이터의 마지막 부족한 부분은 AppDatabase 클래스입니다.마찬가지로 이것은 매우 간단하다.
@Database(entities = arrayOf(Note::class), version = 1)  
abstract class AppDatabase : RoomDatabase() {  

  abstract fun notes(): NotesDao  

}

뷰 모델
이제 데이터ViewModelMutableState를 통해 Jetpack Compose에 액세스할 수 있습니다.변경notes 변수는 이 변수@Composable를 사용한 재컴파일을 자동으로 실행합니다.
SQLite에 대한 호출을 주 스레드에서 호출할 수 없으므로 Kotlin Coroutines를 사용하여 룸에 액세스할 수 있습니다.그러나 더욱 복잡한 장면이 본고의 범위를 넘어서기 때문에 기본적인 방법만 사용한다.
class NotesViewModel(application: Application) : AndroidViewModel(application) {  

  private val db = Room.databaseBuilder(  
    application.applicationContext,  
    AppDatabase::class.java,  
    "db-notes"  
  ).build()  

  var notes by mutableStateOf(listOf<Note>())  
    private set  

  // Load initial data from Room asynchronously.  
  init {  
    GlobalScope.launch {  
      val items = db.notes().getAll()  
      viewModelScope.launch { notes = items }  
    }  
  }  

  fun addNote(note: String) {  
    // Generate ID in a simple way - from timestamp.  
    val noteObj = Note(
      (System.currentTimeMillis() % Int.MAX_VALUE).toInt(), 
      note
    )  
    notes = notes + listOf(noteObj)  
    GlobalScope.launch { db.notes().insert(noteObj) }  
  }  

  fun removeNote(note: Note) {  
    notes = notes - listOf(note)  
    GlobalScope.launch { db.notes().delete(note) }  
  }  

}

조합 가능
마찬가지로 간단히 유지하면서 두 개의 복잡한 @Composable 만 만들 수 있습니다. 하나는 주석을 추가하는 데 사용되고, 다른 하나는 주석을 열거하고 삭제하는 데 사용됩니다.

AddNote 콤보
플러스 버튼이 있는 텍스트 필드는 하나뿐입니다.다른 건 없어요.
@Composable
fun AddNote(title: String, onNoteAdded: (String) -> Unit) {
  Row {
    val text = remember { mutableStateOf(TextFieldValue("")) }
    TextField(
        value = text.value,
        onValueChange = { text.value = it },
        label = { Text(title) },
        modifier = Modifier
            .weight(1f, true)
            .padding(16.dp, 16.dp, 8.dp, 16.dp)
    )
    Button(
        onClick = {
            val newNote = text.value.text
            if (newNote.isNotBlank()) {
                onNoteAdded(newNote)
                text.value = TextFieldValue("")
            }
        },
        modifier = Modifier
            .padding(8.dp, 16.dp, 16.dp, 16.dp)
            .gravity(Alignment.CenterVertically)
    ) {
      Icon(
          asset = Icons.Filled.Add,
          modifier = Modifier.size(24.dp)
      )
    }
  }
}

ShowNotes 콤보
Composable LazyColumnFor 은 자동으로 우리의 모든 노트를 보여 줍니다. items 보기 모형에서 왔을 때 언제든지 업데이트됩니다.
@Composable
fun ShowNotes(items: List<Note>, onNodeRemoved: (Note) -> Unit) {
  LazyColumnFor(items = items) {
    Row {
      Text(
        text = it.content,
        modifier = Modifier
          .padding(16.dp, 4.dp, 4.dp, 4.dp)
          .weight(1f, true)
          .gravity(Alignment.CenterVertically)
      )
      TextButton(
        onClick = {
          onNodeRemoved(it)
        },
        contentPadding = InnerPadding(0.dp),
        modifier = Modifier
          .padding(4.dp, 4.dp, 16.dp, 4.dp)
          .gravity(Alignment.CenterVertically)
      ) {
        Icon(
          asset = Icons.Filled.Delete,
          modifier = Modifier.size(24.dp)
        )
      }
    }
  }
}

활동-풀
우리 MainActivity 는 위의 모든 코드를 한데 붙여서 두 개의 구성 요소를 보여 줍니다.
class MainActivity : AppCompatActivity() {

  private val notesViewModel by viewModels<NotesViewModel>()

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
      Column {

        AddNote(getString(R.string.add_note)) {
          notesViewModel.addNote(it)
        }

        ShowNotes(notesViewModel.notes) {
          notesViewModel.removeNote(it)
        }

      }
    }
  }

}

현지화
이전 장에서 보듯이 저는 AddNotegetString(...)의 제목을 얻었습니다.이것은 당신의 응용 프로그램을 구걸자로부터 현지화할 수 있는 매우 유용한 실천이다.
나는 체코 공화국, 유럽의 심장부에서 온 작은 나라에서 왔다.우리는 자신의 언어를 가지고 있으며, 이곳의 사람들은 자랑스럽게 그것을 사용한다.그들 중 많은 사람들이 영어를 전혀 할 줄 모른다.
이 때문에, 나는 이미 나의 응용 프로그램을 위해 더 많은 언어를 준비하는 것에 익숙해졌다.겸사겸사 한마디 하자면, Floating Apps 30가지 언어를 선택할 수 있는데, 이것은 내가 그것을 현재의 수준으로 발전시키는 데 도움을 준다.
우리의 예시 프로그램에서 원본 코드에서 내가 사용한 Localazy 는 루트 구축에 다음과 같은 줄을 포함하고 있음을 알 수 있습니다.그레델:
repositories {  
  maven { url "https://maven.localazy.com/repository/release/" }  
}  

dependencies {  
  classpath "com.localazy:gradle:1.5.2"  
}
내 응용 프로그램의 구축 중입니다.그레델:
apply plugin: 'com.localazy.gradle'

localazy {  
  readKey "a8922414862262844150-..."  
  writeKey "a8922414862262844150-..."  
}
이 정도면 됐어.나에게 있어서 Localazy translation management를 사용하여 나의 문자열을 무료로 관리할 필요는 없다.업데이트된 번역은 어플리케이션을 다시 Play Store에 제출하지 않고도 새로운 언어까지 온라인으로 제공됩니다.
이 밖에 Localazy는 공유 번역을 제공합니다. 다른 프로그램과 번역을 공유할 수 있고, 무료로 80개 언어로 번역할 수 있습니다.내가 문자열을 올린 지 1분 후에, 나의 50%의 응용 프로그램은 모두 80개의 언어를 가지고 있다.

결실
다음은 간단하지만 완전히 효과적인 필기 프로그램입니다.

소스 코드
본문의 모든 소스 코드는 available on Github입니다.

기대 많이 해주세요.
안드로이드 개발에 대한 더 많은 정보를 원하십니까?트위터에서 나()와 로컬레이지(Localazy), 혹은 유사한Localazy on Facebook을 팔로우한다.

시리즈
이 문서는 Android 시리즈 부동 창의 일부입니다.
  • Floating Windows on Android 1: Jetpack Compose & Room
  • Floating Windows on Android 2: Foreground Service
  • Floating Windows on Android 3: Permissions
  • Floating Windows on Android 4: Floating Window
  • Floating Windows on Android 5: Moving Window
  • Floating Windows on Android 6: Keyboard Input
  • Floating Windows on Android 7: Boot Receiver
  • Floating Windows on Android 8: The Final App
  • Floating Windows on Android 9: Shortcomings
  • Floating Windows on Android 10: Tips & Tricks
  • 좋은 웹페이지 즐겨찾기