안드로이드 기능을 구현하기 위해 기본 작업을 트리거하는 원형 버튼인 플로팅액션버튼을 추가해 줄 것이다.
xml에 아래의 코드를 추가해주면 된다.
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btn_write"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="32dp"
android:layout_marginBottom="32dp"
android:clickable="true"
android:elevation="10dp"
android:backgroundTint="#448AFF"
app:tint="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="@drawable/img_write" />
android:elevation="10dp"
위 코드는 아이콘이 살짝 떠보이게해서 입체감을 준다.
app:tint="@color/white"
android:backgroundTint="#448AFF"
위 코드는 이미지의 색 디자인을 변경하기 위한 코드이다.
Dialog 커스텀을 하기 위한 위젯은 TextInputLayout이다.
이것은 EditText를 기반으로 유연한 동작을 보여주는 구글의 레이아웃이다.
TextInputLayout의 스타일은 기본적으로 두가지로 FilledBox, OutlinedBox 스타일이 있다.
TextInputLayout 안에는 TextInputEditText를 사용할 수 있다.
예제는 아래와 같다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:counterEnabled="true"
app:counterMaxLength="20">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/et_memo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="@font/kotra_hope"
android:singleLine="true"
android:maxLines="1"
android:maxLength="20"
android:hint="메모를 남겨주세요 !"/>
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
android:singleLine="true"
android:maxLines="1"
위 코드는 1줄로 제한하기 위한 코드이다. -> 엔터를 눌러도 두번째 줄로 넘어가지 않는다.
android:maxLength="20"
위 코드는 최대 길이를 20으로 제한한다.
android:hint="메모를 남겨주세요 !"
위 코드는 힌트를 생성하는데 클릭시 스타일에 맞게 위치하게 된다.
binding.btnWrite.setOnClickListener {
val bindingDialog = DialogEditBinding.inflate(LayoutInflater.from(binding.root.context), binding.root, false)
AlertDialog.Builder(this)
.setTitle("오늘의 할 일은 ?")
.setView(bindingDialog.root)
.setPositiveButton("작성", DialogInterface.OnClickListener { dialog, i ->
// 작성 버튼 이벤트 처리
val todoItem = ListInfo()
todoItem.listContent = bindingDialog.etMemo.text.toString()
// pattern은 이러한 형식을 유지하겠다는 구문이고, format(Date()) 메서드가 현재 시간을 가져와준다.
todoItem.listDate = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())
listAdapter.addListItem(todoItem) // 어댑터의 전역변수의 arraylist 쪽에 아이템 추가하기위한 메소드 호출
listAdapter.notifyDataSetChanged() // 리스트 새로고침 -> 어댑터가 한 사이클 돌게 됨. 고로 아이템이 표출됨.
})
.setNegativeButton("취소", DialogInterface.OnClickListener { dialog, i ->
// 취소 버튼 이벤트 처리
})
.show()
}
위 코드는 AlertDialog를 통해 작성한 코드로 setTitle은 제목을 설정, setView는 커스텀한 뷰를 보여준다.
ListInfo()를 todoItem으로 객체를 생성해서 listContent와 listDate를 사용하였다.
addListItem은 사용자 정의 함수로 어댑터 안에서 구현하였다.
fun addListItem(listItem: ListInfo) {
// 배열은 0,1,2,3..으로 쌓이는데 최신 add 정보가 가장 위에 나오게 해야한.다
// 최신순으로 보이게 하려면 0번째 인덱스의 위치로 add해주면 된다.
lstTodo.add(0, listItem)
}
위 코드를 통해서 아이템을 가장 위에 보이게 추가할 수 있다.
// TodoViewHolder는 그저 같은 클래스 내부에 작성된 별도의 클래스이므로 inner을 붙임으로써 lstTodo를 사용할 수 있다.
inner class TodoViewHolder(private val binding: ListItemBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(listItem : ListInfo) {
// 리스트 뷰 데이터를 UI에 연동
binding.tvContent.setText(listItem.listContent)
binding.tvDate.setText(listItem.listDate)
// 리스트 삭제 버튼 클릭 연동
binding.btnRemove.setOnClickListener {
// 쓰레기통 이미지 클릭 시 이벤트 처리
AlertDialog.Builder(binding.root.context)
.setTitle("[경고]")
.setMessage("제거하시면 데이터는 복구되지 않습니다.\n정말 제거하시겠습니까?")
.setPositiveButton("제거", DialogInterface.OnClickListener { dialog, i ->
lstTodo.remove(listItem)
notifyDataSetChanged()
Toast.makeText(binding.root.context, "제거되었습니다.", Toast.LENGTH_SHORT).show()
})
.setNegativeButton("취소", DialogInterface.OnClickListener { dialog, i ->
})
.show()
}
// 리스트 수정
binding.root.setOnClickListener {
val bindingDialog = DialogEditBinding.inflate(LayoutInflater.from(binding.root.context), binding.root, false)
bindingDialog.etMemo.setText(listItem.listContent)
androidx.appcompat.app.AlertDialog.Builder(binding.root.context)
.setTitle("오늘의 할 일은 ?")
.setView(bindingDialog.root)
.setPositiveButton("작성", DialogInterface.OnClickListener { dialog, i ->
// 작성 버튼 이벤트 처리
listItem.listContent = bindingDialog.etMemo.text.toString()
listItem.listDate = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())
// arraylist 수정
lstTodo.set(adapterPosition, listItem)
notifyDataSetChanged()
})
.setNegativeButton("취소", DialogInterface.OnClickListener { dialog, i ->
// 취소 버튼 이벤트 처리
})
.show()
}
}
}
작성하기 버튼 구현과 맥락이 비슷하여 비교적 쉽게 이해하려할 수 있을 것이다.