[Android] 비밀 다이어리

2022. 10. 28. 01:18·🍞 FrontEnd/Android

오늘은 비밀번호를 저장하는 기능과 변경하는 기능을 구현해볼 것이다.

또한, 다이어리 내용을 앱이 종료되더라도 기기에 저장하는 기능을 구현할 것이다.

 

SharedPreference의 속성들과 사용하는 법

Custom Font 사용하기

Handler 사용하기

Theme 사용하기

AlertDialog 사용하기

 

📌 알게 된 점

1. ActionBar를 없애려면 theme 파일에 테마 설정을 해주고, manifast 파일에 표시해줘야 한다.

theme
Manifast

2. Custom Font 사용하는 법

font 이름을 가진 디렉터리를 만들어준다.

원하는 폰트를 다운 받은 다음, font 디렉터리에 넣어주고 fontFamily를 설정해준다.

참고로, 폰트 파일 이름은 첫문자가 소문자로 시작되어야 한다!

3. handler라는 것은 thread와 thread 간에 통신을 엮어주는 안드로이드에서 제공하는 기능이다.

 

📌 최종 코드

- Activity

MainActivity.kt

package com.example.secretdiary

import android.content.Context
import android.content.Intent
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.NumberPicker
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.AppCompatButton
import androidx.core.content.edit

class MainActivity : AppCompatActivity() {

    private val numberPicker1: NumberPicker by lazy {
        findViewById<NumberPicker>(R.id.numberPicker1)
            .apply {
                minValue = 0
                maxValue = 9
            }
    }

    private val numberPicker2: NumberPicker by lazy {
        findViewById<NumberPicker>(R.id.numberPicker2)
            .apply {
                minValue = 0
                maxValue = 9
            }
    }

    private val numberPicker3: NumberPicker by lazy {
        findViewById<NumberPicker>(R.id.numberPicker3)
            .apply {
                minValue = 0
                maxValue = 9
            }
    }

    private val openButton: AppCompatButton by lazy {
        findViewById<AppCompatButton>(R.id.openButton)
    }

    private val changePasswordButton: AppCompatButton by lazy {
        findViewById<AppCompatButton>(R.id.changePasswordButton)
    }

    private var changePasswordMode = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        numberPicker1
        numberPicker2
        numberPicker3

        openButton.setOnClickListener {
            if (changePasswordMode) {
                Toast.makeText(this, "비밀번호 변경 중입니다.", Toast.LENGTH_SHORT).show()
                return@setOnClickListener
            }

            val passwordPreferences = getSharedPreferences("password", MODE_PRIVATE)
            val passwordFromUser =
                "${numberPicker1.value}${numberPicker2.value}${numberPicker3.value}"
            // 초기 비밀번호
            if (passwordPreferences.getString("password", "000").equals(passwordFromUser)) {
                startActivity(Intent(this, DiaryActivity::class.java))
            } else {
                showErrorAlertDialog()
            }
        }

        changePasswordButton.setOnClickListener {
            val passwordPreferences = getSharedPreferences("password", MODE_PRIVATE)
            val passwordFromUser =
                "${numberPicker1.value}${numberPicker2.value}${numberPicker3.value}"

            if (changePasswordMode) { //번호를 저장하는 기능
                passwordPreferences.edit(true) {
                    putString("password", passwordFromUser)
                }
                changePasswordButton.setBackgroundColor(Color.BLACK)
                changePasswordMode = false

            } else { // changePassWordMode 가 활성화 :: 비밀번호가 맞는지 체크
                // 초기 비밀번호
                if (passwordPreferences.getString("password", "000").equals(passwordFromUser)) {
                    changePasswordMode = true
                    Toast.makeText(this, "변경할 패스워드를 입력해주세요", Toast.LENGTH_SHORT).show()
                    changePasswordButton.setBackgroundColor(Color.RED)
                } else {
                    showErrorAlertDialog()
                }
            }
        }
    }

    private fun showErrorAlertDialog() {
        AlertDialog.Builder(this)
            .setTitle("실패")
            .setMessage("비밀번호가 잘못되었습니다.")
            .setPositiveButton("확인") { dialog, which -> }
            .create()
            .show()
    }
}

 

DiaryActivity.kt

package com.example.secretdiary

import android.content.Context
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.edit
import androidx.core.widget.addTextChangedListener

class DiaryActivity : AppCompatActivity() {

    private val handler = Handler(Looper.getMainLooper())

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_diary)

        val diaryEditText = findViewById<EditText>(R.id.diaryEditText)
        val detailPreferences = getSharedPreferences("diary", Context.MODE_PRIVATE)

        diaryEditText.setText(detailPreferences.getString("detail", ""))

        val runnable = Runnable {
            getSharedPreferences("diary", Context.MODE_PRIVATE).edit {
                putString("detail", diaryEditText.text.toString())
            }
            Log.d("DiaryActivity", "SAVE!!!! ${diaryEditText.text.toString()}")
        }

        diaryEditText.addTextChangedListener {
            Log.d("DiaryActivity", "TextChanged :: $it")
            handler.removeCallbacks(runnable) // 이전 값 지우기
            handler.postDelayed(runnable, 500) // 0.5초 뒤에 실행
        }
    }
}

 

- Layout

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#3f51b5"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="50dp"
        android:fontFamily="@font/poor_story"
        android:text="The Secret Garden"
        android:textSize="30sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toTopOf="@id/passwordLayout"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/passwordLayout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#cdcdcd"
        android:padding="15dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.45">

        <androidx.appcompat.widget.AppCompatButton
            android:id="@+id/openButton"
            android:layout_width="40dp"
            android:layout_height="60dp"
            android:layout_marginEnd="10dp"
            android:background="#a3a3a3"
            app:layout_constraintBottom_toBottomOf="@id/numberPicker1"
            app:layout_constraintEnd_toStartOf="@id/numberPicker1"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@id/numberPicker1" />

        <androidx.appcompat.widget.AppCompatButton
            android:id="@+id/changePasswordButton"
            android:layout_width="10dp"
            android:layout_height="10dp"
            android:layout_marginTop="10dp"
            android:background="@color/black"
            app:layout_constraintEnd_toEndOf="@id/openButton"
            app:layout_constraintStart_toStartOf="@+id/openButton"
            app:layout_constraintTop_toBottomOf="@id/openButton" />

        <NumberPicker
            android:id="@+id/numberPicker1"
            android:layout_width="30dp"
            android:layout_height="120dp"
            android:background="#a3a3a3"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/numberPicker2"
            app:layout_constraintHorizontal_chainStyle="packed"
            app:layout_constraintStart_toEndOf="@id/openButton"
            app:layout_constraintTop_toTopOf="parent" />

        <NumberPicker
            android:id="@+id/numberPicker2"
            android:layout_width="30dp"
            android:layout_height="120dp"
            android:background="#a3a3a3"
            app:layout_constraintEnd_toStartOf="@id/numberPicker3"
            app:layout_constraintStart_toEndOf="@id/numberPicker1"
            app:layout_constraintTop_toTopOf="@id/numberPicker1" />

        <NumberPicker
            android:id="@+id/numberPicker3"
            android:layout_width="30dp"
            android:layout_height="120dp"
            android:background="#a3a3a3"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@id/numberPicker2"
            app:layout_constraintTop_toTopOf="@id/numberPicker1" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

 

activity_diary.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#3f51b5"
    android:padding="24dp">

    <EditText
        android:id="@+id/diaryEditText"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@color/white"
        android:gravity="start|top"
        android:padding="10dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

저작자표시 (새창열림)

'🍞 FrontEnd > Android' 카테고리의 다른 글

[Android] 계산기 RoomDB  (0) 2022.10.31
[Android] 에뮬레이터에서 Toast 메세지가 안 보일 때  (0) 2022.10.31
[Android] 로또 번호 추첨기  (2) 2022.10.27
[Android] BMI 계산기  (0) 2022.10.27
[Android] 안드로이드 리사이클러뷰(RecyclerView)  (0) 2022.10.23
'🍞 FrontEnd/Android' 카테고리의 다른 글
  • [Android] 계산기 RoomDB
  • [Android] 에뮬레이터에서 Toast 메세지가 안 보일 때
  • [Android] 로또 번호 추첨기
  • [Android] BMI 계산기
박빵이
박빵이
2025년에도 갓생살기
  • 박빵이
    기억보다 기록
    박빵이
  • 전체
    오늘
    어제
    • 분류 전체보기 (337)
      • 🍞 FrontEnd (97)
        • HTML+CSS (4)
        • JavaScript (17)
        • TypeScript (4)
        • React (52)
        • Next.js (2)
        • Android (15)
      • 🍞 BackEnd (24)
        • Java (15)
        • Node.js (6)
        • Spring (1)
      • 🍞 Cloud & Infra (0)
        • AWS SAA (0)
        • Microsoft Azure (0)
      • 🍞 Algorithm (147)
        • C++ (4)
        • Baekjoon (41)
        • Programmers (97)
      • 🍞 Computer Science (18)
        • 운영체제 (1)
        • 데이터 통신 (6)
        • 네트워크 (6)
        • 데이터베이스 (1)
      • 🍞 대외활동 & 부트캠프 (42)
        • 삼성 청년 SW 아카데미 (1)
        • LG유플러스 유레카 (0)
        • 한국대학생IT경영학회 (1)
        • IT연합동아리 UMC (17)
        • 길벗 블로깅 멘토 (18)
        • IT연합동아리 피로그래밍 (3)
        • 개발 컨퍼런스 (2)
  • 블로그 메뉴

    • Admin
  • 링크

    • GitHub
  • 인기 글

  • 태그

    코틀린
    코딩자율학습
    level2
    umc
    level1
    위상정렬
    프로그래머스
    길벗 블로깅 멘토링
    길벗 블로깅 멘토
    Front
    Android
    JavaScript
    react
    알고리즘
    C++
    Java
    안드로이드
    map
    유니온파인드
    백준
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
박빵이
[Android] 비밀 다이어리
상단으로

티스토리툴바