안드로이드 스튜디오

[안드로이드 스튜디오 코틀린] 약관 동의 (전체, 필수, 선택) 예제

권송미 2023. 9. 24. 23:06
728x90
반응형

 

 

앱에서 회원가입을 할 때, 이용 약관 CheckBox를 많이 볼 수 있다.

사실 예전부터 이용 약관에서 계속 막히고.. 잘 안되고... 뜻대로 수행되지 않아서 계속 해맸었다..!

그러다가, 마침내 성공하게 되어 드디어 이용약관 예제 글을 쓰게 되었다.

(나처럼 ... 헤매던 사람들에게 한 줄기의 빛이 되길.. 바라며... !.. 다들 화이팅입니다)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

우선, 전체 동의를 하는 CheckBox가 존재해야 하고, 필수 동의와, 선택 동의 3가지가 전부 있는 이용 약관을 만들어 보려고 한다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

먼저 체크 전, 후 vector를 생성해준다

 

 

- drawable -> New -> Vector Asset

 

 

 

 

 

그리고 이 둘을 체크 / 비체크 상태로 만들어줄 drawable을 생성해줍니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

- drawable -> New -> Drawable Resource File

 

 

 

 

 

 

 

 

 

 

 

 

이렇게 하고

 

 

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_checked="true" android:drawable="@drawable/baseline_check_circle"/>
    <item android:state_checked="false" android:drawable="@drawable/baseline_check_circle_outline"/>

</selector>

 

true일 때 안에가 색칠되게 만들어주었습니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

그리고 다음 화면으로 넘어갈 Button도 아래처럼 만들어줍니다.

 

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_enabled="true" android:drawable="@drawable/rect_stroke_skyblue"/>
    <item android:state_enabled="false" android:drawable="@drawable/rect_stroke_gray"/>
    
</selector>

 

 

 

 

 

 

 

 

 

 

 

 

다음 전체적인 이용약관 UI를 구성해줍니다.

 

 

 

<?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"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/mainTV"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="100dp"
        android:text="이용 약관"
        android:textSize="32sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <LinearLayout
        android:id="@+id/allCheckLL"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="40dp"
        android:layout_marginTop="50dp"
        android:clickable="true"
        android:focusable="true"
        android:orientation="horizontal"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/mainTV">

        <CheckBox
            android:id="@+id/allCheckBox"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_gravity="center"
            android:layout_marginTop="1dp"
            android:background="@drawable/custom_checkbox_background"
            android:button="@null"
            android:clickable="false" />

        <TextView
            android:id="@+id/allCheckTV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginStart="4dp"
            android:text="이용 약관 전체 "
            android:textSize="18sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/allAgreeTV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="동의"
            android:textSize="18sp"
            android:textStyle="bold" />

    </LinearLayout>

    <LinearLayout
        android:id="@+id/firstCheckLL"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="45dp"
        android:layout_marginTop="35dp"
        android:layout_marginEnd="30dp"
        android:clickable="true"
        android:focusable="true"
        android:orientation="horizontal"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/allCheckLL">

        <CheckBox
            android:id="@+id/firstCheckBox"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_gravity="center"
            android:background="@drawable/custom_checkbox_background"
            android:button="@null"
            android:clickable="false" />

        <TextView
            android:id="@+id/firstCheckTV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginStart="4dp"
            android:text="@string/personInfoAgree"
            android:textSize="14sp" />

        <TextView
            android:id="@+id/firstAgreeTV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginStart="4dp"
            android:text="동의"
            android:textSize="14sp" />

    </LinearLayout>

    <LinearLayout
        android:id="@+id/secondCheckLL"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="45dp"
        android:layout_marginTop="20dp"
        android:layout_marginEnd="30dp"
        android:clickable="true"
        android:focusable="true"
        android:orientation="horizontal"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/firstCheckLL">

        <CheckBox
            android:id="@+id/secondCheckBox"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_gravity="center"
            android:background="@drawable/custom_checkbox_background"
            android:button="@null"
            android:clickable="false" />

        <TextView
            android:id="@+id/secondCheckTV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginStart="4dp"
            android:text="@string/serviceUseAgree"
            android:textSize="14sp" />

        <TextView
            android:id="@+id/secondAgreeTV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginStart="4dp"
            android:text="동의"
            android:textSize="14sp" />

    </LinearLayout>

    <LinearLayout
        android:id="@+id/threeCheckLL"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="45dp"
        android:layout_marginTop="20dp"
        android:layout_marginEnd="30dp"
        android:clickable="true"
        android:focusable="true"
        android:orientation="horizontal"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/secondCheckLL">

        <CheckBox
            android:id="@+id/threeCheckBox"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_gravity="center"
            android:background="@drawable/custom_checkbox_background"
            android:button="@null"
            android:clickable="false" />

        <TextView
            android:id="@+id/threeCheckTV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginStart="4dp"
            android:text="@string/locationInfoAgree"
            android:textSize="14sp" />

        <TextView
            android:id="@+id/threeAgreeTV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginStart="4dp"
            android:text="동의"
            android:textSize="14sp" />

    </LinearLayout>

    <LinearLayout
        android:id="@+id/fourCheckLL"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="45dp"
        android:layout_marginTop="20dp"
        android:layout_marginEnd="30dp"
        android:clickable="true"
        android:focusable="true"
        android:orientation="horizontal"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/threeCheckLL">

        <CheckBox
            android:id="@+id/fourCheckBox"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_gravity="center"
            android:background="@drawable/custom_checkbox_background"
            android:button="@null"
            android:clickable="false" />

        <TextView
            android:id="@+id/fourCheckTV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginStart="4dp"
            android:text="@string/advertiseInfoAgree"
            android:textSize="14sp" />

        <TextView
            android:id="@+id/fourAgreeTV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginStart="4dp"
            android:text="동의"
            android:textSize="14sp" />

    </LinearLayout>

    <androidx.appcompat.widget.AppCompatButton
        android:id="@+id/nextButton"
        android:layout_width="300dp"
        android:layout_height="80dp"
        android:layout_marginBottom="40dp"
        android:background="@drawable/custom_button_background"
        android:clickable="true"
        android:enabled="false"
        android:focusable="true"
        android:paddingEnd="5dp"
        android:paddingBottom="4dp"
        android:text="다음"
        android:textColor="@color/white"
        android:textSize="17sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

 

 

 

 

 

 

저는 LinearLayout 클릭시, CheckBox의 상태를 바꾸고 싶어 LinearLayout에 Clickable을 true로 넣어주고, CheckBox에는 false를 주어 전체적인 선택을 하는 방안으로 해주었습니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

메인 코드는

 

 

 

 

package com.example.checkboxexam

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import androidx.core.content.ContextCompat
import com.example.checkboxexam.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    private var isAllSelected = false
    private var isFirstSelected = false
    private var isSecondSelected = false
    private var isThreeSelected = false
    private var isFourSelected = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        checkClickState()
    }

    private fun checkClickState() {
        // 전체 동의 LinearLayout 클릭 시 checkbox가 check되는 클릭 리스너 설정
        binding.allCheckLL.setOnClickListener {
            val isChecked = !binding.allCheckBox.isChecked
            binding.allCheckBox.isChecked = isChecked
            binding.firstCheckBox.isChecked = isChecked
            binding.secondCheckBox.isChecked = isChecked
            binding.threeCheckBox.isChecked = isChecked
            binding.fourCheckBox.isChecked = isChecked
            binding.nextButton.isEnabled = isChecked
            isAllSelected = isChecked
            isFirstSelected = isChecked
            isSecondSelected = isChecked
            isThreeSelected = isChecked
            isFourSelected = isChecked

            allCheckState()
            firstCheckState()
            secondCheckState()
            threeCheckState()
            fourCheckState()
        }

        binding.firstCheckLL.setOnClickListener {
            binding.firstCheckBox.isChecked = !binding.firstCheckBox.isChecked
            isFirstSelected = binding.firstCheckBox.isChecked
            firstCheckState()
            updateButtonState()
        }

        binding.secondCheckLL.setOnClickListener {
            binding.secondCheckBox.isChecked = !binding.secondCheckBox.isChecked
            isSecondSelected = binding.secondCheckBox.isChecked
            secondCheckState()
            updateButtonState()
        }

        binding.threeCheckLL.setOnClickListener {
            binding.threeCheckBox.isChecked = !binding.threeCheckBox.isChecked
            isThreeSelected = binding.threeCheckBox.isChecked
            threeCheckState()
            updateButtonState()
        }

        binding.fourCheckLL.setOnClickListener {
            binding.fourCheckBox.isChecked = !binding.fourCheckBox.isChecked
            isFourSelected = binding.fourCheckBox.isChecked
            fourCheckState()
            updateButtonState()
        }
    }

    private fun updateButtonState() {
        val mushSelected = isFirstSelected && isSecondSelected && isThreeSelected
        if (mushSelected) {
            binding.nextButton.isEnabled = true
        }

        val fourSelected = isFirstSelected && isSecondSelected && isThreeSelected && isFourSelected
        if (fourSelected) {
            binding.allCheckBox.isChecked = isFourSelected
            allCheckState()
            binding.nextButton.isEnabled = isFourSelected
        } else if (mushSelected) {
            // 필수 동의만 선택되었을 때
            binding.allCheckBox.isChecked = false
            allCheckState()
        }
    }


    private fun allCheckState() {
        if (binding.allCheckBox.isChecked) {
            enabledAgreeText(binding.allCheckTV, binding.allAgreeTV)
        } else {
            disEnabledAgreeText(binding.allCheckTV, binding.allAgreeTV)
        }
    }

    private fun firstCheckState() {
        if (binding.firstCheckBox.isChecked) {
            enabledAgreeText(binding.firstCheckTV, binding.firstAgreeTV)
        } else {
            disEnabledAgreeText(binding.firstCheckTV, binding.firstAgreeTV)
        }
    }

    private fun secondCheckState() {
        if (binding.secondCheckBox.isChecked) {
            enabledAgreeText(binding.secondCheckTV, binding.secondAgreeTV)
        } else {
            disEnabledAgreeText(binding.secondCheckTV, binding.secondAgreeTV)
        }
    }

    private fun threeCheckState() {
        if (binding.threeCheckBox.isChecked ) {
            enabledAgreeText(binding.threeCheckTV, binding.threeAgreeTV)
        } else {
            disEnabledAgreeText(binding.threeCheckTV, binding.threeAgreeTV)
        }
    }

    private fun fourCheckState() {
        if (binding.fourCheckBox.isChecked) {
            enabledAgreeText(binding.fourCheckTV, binding.fourAgreeTV)
        } else {
            disEnabledAgreeText(binding.fourCheckTV, binding.fourAgreeTV)
        }
    }

    private fun enabledAgreeText(textView: TextView, agreeText: TextView) {
        textView.setTextColor(ContextCompat.getColor(this, R.color.skyblue))
        agreeText.setTextColor(ContextCompat.getColor(this, R.color.skyblue))
    }

    private fun disEnabledAgreeText(textView: TextView, agreeText: TextView) {
        textView.setTextColor(ContextCompat.getColor(this, R.color.black))
        agreeText.setTextColor(ContextCompat.getColor(this, R.color.black))
    }
}

 

 

 

 

 

 

 

 

updateButtonState()함수에서 필수 동의를 다 체크 했을 때 버튼을 활성화해주고, 4개의 동의를 다 해주면 버튼을 활성화 해주었는데 여기서 선택 동의를 해제할 시 버튼은 다시 false처리를 하도록 구현하였습니다.

 

 

 

 

 

 

 

 

 

 

 

  

 

 

 

 

 

 

 

 

 

 

 

 

 

구현 화면

 

 

 

 

 

 

 

선택 전                               ->                     전체 동의                        ->                     필수 동의

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

총 코드

 

 

https://github.com/songmik/CheckBoxExam

 

GitHub - songmik/CheckBoxExam

Contribute to songmik/CheckBoxExam development by creating an account on GitHub.

github.com

 

728x90
반응형