안드로이드 스튜디오 메모 앱 만들기(8)

윤재환·2024년 11월 23일

제목과 내용 구분

이전에 제목을 추가 했을떄는
제목내용 이렇게 합쳐져있어서 구분이 힘들었습니다.

이제는 제목과 내용을 구분하고 날짜까지 추가해보겠습니다.

우선 item_memo.xml입니다.

<!--제목과 작성일-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <!-- 제목 박스-->
        <TextView
            android:id="@+id/textViewTitle"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="제목"
            android:textSize="18sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/textViewDate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="end"
            android:textSize="12sp"
            android:textColor="#888888"
            android:text="yy.mm.dd"/>
    </LinearLayout>

LinearLayout으로 감싸 제목과 작성일을 한 줄에 배치하고, 내용은 아래에 표시하도록 수정합니다.


Memo데이터 클래스 수정

날짜를 추가하기 위해 데이터 클래스에 date 필드를 추가합니다.

MainActivity.kt를 수정 하겠습니다.

data class Memo(
        val title: String = "제목 없음", // 기본값 설정(전에 있던것도)
        val content: String,
        val date: String = getCurrentDate()
    )

    private fun getCurrentDate(): String {
        val formatter = java.text.SimpleDateFormat("yy.MM.dd", java.util.Locale.getDefault())
        return formatter.format(java.util.Date())
    }
  • date필드 기본값 :
    • 메모 생성시getCurrentDate()를 호출하여 현재 날짜를 자동으로 추가.

에러

위 코드를 작성시 계속 getCurrentDate()읽지 못했습니다.

gpt에게 물어본 결과는

  • MainActivity 내부에서 getCurrentDate()를 사용하려면 함수가 companion object로 정의되어야 합니다.
  • Memo 데이터 클래스의 기본값은 정적 함수(companion object)를 통해 접근해야 합니다.

이라고 합니다...

이후 코드를 수정하겠습니다.

companion object{
        // 클래스 외부에 함수 정의
        fun getCurrentDate(): String {
            val formatter = java.text.SimpleDateFormat("yy.MM.dd", java.util.Locale.getDefault())
            return formatter.format(java.util.Date())
        }
    }

    //데이터 클래스 추가 (제목에 null이 생길 이유가 있기 때문)
    data class Memo(
        val title: String = "제목 없음",
        val content: String,
        val date: String = getCurrentDate() // 외부 함수 호출
    )

이젠 잘들어 갑니다!

추가

  • 아래에 buttonAddMemo.setOnClickListener메서드에서 date를 추가 안하는 이유는 Memo생성자에 date필드는 기본값 getCurrentDate()로 설정되어 있으므로, 명시적으로 값을 전달하지 않아도 현재 날짜가 자동으로 할당됩니다.

이후 새로운 데이터가 추가 되었으니 옛날 데이터들을 가져올떄 오류가 날수 있어 try, catch문도 추가 해 주겠습니다.

private fun loadMemos() {
        val sharedPreferences = getSharedPreferences("memo_prefs", Context.MODE_PRIVATE)
        val gson = Gson()
        val json = sharedPreferences.getString("memo_list", null)
        if (json != null) {
            try {
                val type = object : TypeToken<MutableList<Memo>>() {}.type
                val loadeMemos: MutableList<Memo> = gson.fromJson(json, type)
                memoList.addAll(loadeMemos)
            }catch (e: Exception){
                val oldType = object : TypeToken<MutableList<String>>() {}.type
                val oldMemos: MutableList<String> = gson.fromJson(json, oldType)

                val convertedMemos = oldMemos.map { Memo(title = "제목 없음", content = it) }
                memoList.addAll(convertedMemos)

                saveMemos()
            }
            adapter.notifyDataSetChanged()
        }
    }

위에서도 말했듯이 date는 기본값으로 설정되어 생성자에서 따로 값을 전달하지 않아도 자동으로 생성됩니다


이젠 MemoAdapter.kt를 수정하겠습니다.

class MemoViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val textViewTitle: TextView = itemView.findViewById(R.id.textViewTitle)
        val textViewContent: TextView = itemView.findViewById(R.id.textViewMemo)
        val textViewDate: TextView = itemView.findViewById(R.id.textViewDate) //날짜 추가
        val buttonDeleteMemo: Button = itemView.findViewById(R.id.buttonDeleteMemo)
    }
    
    override fun onBindViewHolder(holder: MemoViewHolder, position: Int) {
        val memo = memoList[position]
        holder.textViewTitle.text = memo.title
        holder.textViewContent.text = memo.content
        holder.textViewDate.text = memo.date

        //삭제 버튼 클릭 이벤트 처리
        holder.buttonDeleteMemo.setOnClickListener{
            onDelete(position) // 삭제 콜백 호출
        }
    }

데이터를 UI에 바인딩하도록 onBindViewHolder 메서드를 수정합니다.


에러


제목과 날짜는 잘나오지만
옛날 데이터 날자와, 내용은 나오지 않습니다..
해당 포스트가 길어저 다음 포스트에서 작성하겠습니다.


삭제버튼 클릭시 팝업창 생성

지금 앱은 삭제버튼 클릭시 바로 삭제가 되기 때문에 원하지 않은 삭제가 될 가능성이 있기에 해당 기능을 추가하도록 하겠습니다.

AlertDialog를 이용한 팝업 추가

우선 MainActivity.kt를 수정하겠습니다.

//메보 삭제 팝업
    private fun showDeleteConfirmationDialog(position: Int){
        // AlertDialog 빌더 생성
        val builder = AlertDialog.Builder(this)
        builder.setTitle("삭제 확인")
        builder.setMessage("정말로 삭제하겠습니까?")

        // "삭제" 버튼 추가
        builder.setPositiveButton("삭제") { dialog, _ ->
            deleteMemo(position) // 메모 삭제
            dialog.dismiss() // 팝업 닫기
        }

        // "취소"버튼 추가
        builder.setNeutralButton("취소"){ dialog, _->
            dialog.dismiss() // 팝업 닫기
        }

        builder.create().show()
    }

해당 코드를 추가해 줍니다.

해당 코드중 builder.setPositiveButton을 클릭시에
deleteMemo를 호출 하기때문에 그 아래의 코드인 deleteMemo코드는 지울 필요가 없습니다.


결과 창

잘나옵니다!


profile
백엔드 개발에 관심있는 1인

0개의 댓글