사이드프로젝트(withPet) #5 - 커스텀 위젯 [select]

김민태·2024년 9월 24일

withPet

목록 보기
5/6
post-thumbnail

CustomOption 이란?

HTML의 <select> 태그처럼 목록에서 원하는 값을 선택할 수 있는 기능을 제공하기 위해 구현된 클래스입니다.

CustomOption 소스 먼저 보기


CustomSelect Example 1
CustomSelect Example 2

주요 요구 사항:

  • 포커스 및 에러 상태에 따라 변하는 밑줄 디자인.
  • 옵션 목록을 사용자가 볼 수 있도록 노출하는 기능.

디자인 구조는 이전의 CustomInput과 유사하므로, 이번에는 옵션 목록 노출 구현을 중심으로 설명하겠습니다.

1. SelectItem 데이터 클래스 및 옵션 설정

선택 가능한 옵션 목록을 처리하기 위해 HTML의 <option> 태그처럼 SelectItem 데이터 클래스를 만들어 관리합니다.

data class SelectItem(
  val label: String, 
  val value: String, 
  var checked: Boolean = false
)

CustomSelectAppCompatEditText를 상속받아, 옵션 선택 기능을 제공하고, 이를 관리하기 위해 options 배열을 사용합니다.

class CustomSelect @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : AppCompatEditText(context, attrs, defStyleAttr) {

  private var options: Array<SelectItem> = arrayOf()
  private var value: String = ""
  
  // 옵션을 설정하는 메서드
  fun setOptions(options: Array<SelectItem>) {
      this.options = options
      options.find { it.checked }?.label.let {
          setText(it)
      }
  }
  
  // 선택된 옵션의 값에 접근하기 위한 메서드
  fun getValue(): String? {
      return value
  }
}

1-1. setOptions 예시

옵션 목록을 설정하고, 기본 선택된 값을 화면에 표시하기 위해 setOptions() 메서드를 사용합니다.

binding.selectPetSize.setOptions(
    arrayOf(
        SelectItem("소형", "Small"),
        SelectItem("중형", "Medium"),
        SelectItem("대형", "Large"),
    )
)

이 메서드를 통해 선택 가능한 옵션을 CustomSelect에 전달하고, 선택된 옵션을 화면에 노출시킵니다.


2. 선택된 옵션의 값에 접근하기 위한 메서드

선택된 옵션을 사용해야 하는 상황을 처리하기 위해 getValue() 메서드를 추가하여 선택된 옵션의 값에 접근할 수 있도록 합니다.

value 변수에는 사용자가 선택한 옵션의 실제 값이 저장되며, 이 값을 필요할 때 가져올 수 있어야 합니다. getValue() 메서드는 이를 간편하게 접근할 수 있도록 도와줍니다.

// 선택된 옵션의 값에 접근하기 위한 메서드
fun getValue(): String? {
    return value
}

이 메서드를 통해 선택된 옵션의 값을 아래와 같이 다른 작업이나 프로세스에서 활용할 수 있습니다.

val value = binding.select.getValue()

3. 옵션 목록 노출: showOptions

옵션을 선택할 수 있는 UI를 제공하기 위해, showOptions() 메서드를 사용해 Bottom Sheet 다이얼로그를 띄웁니다.

var type: String = "list"

fun showOptions() {
        val bottomSheetView =
            LayoutInflater.from(context).inflate(R.layout.custom_bottom_sheet_container, null)
        val contentFrame: FrameLayout = bottomSheetView.findViewById(R.id.content_frame)

        // type에 따라 다른 UI 구성
        when (type) {
            "list" -> inflateListOptionsView(contentFrame)
            "gender" -> inflateGenderOptionsView(contentFrame)
            else -> {
                text = null
                value = ""
            }
        }

        setupBottomSheetDialog(bottomSheetView)
    }

type 값에 따라 다른 옵션 UI를 띄우며, 이번에는 옵션 리스트를 보여주는 inflateListOptionsView()를 중점적으로 설명하겠습니다.

3-1. inflateListOptionsView

옵션 리스트를 화면에 표시하기 위해, inflateListOptionsView()를 통해 리스트 UI를 생성합니다.

private fun inflateListOptionsView(contentFrame: FrameLayout) {
      // 1. 리스트를 담을 커스텀 뷰를 인플레이트하고 추가
      val customView = LayoutInflater.from(context).inflate(R.layout.custom_select_list, null)
      contentFrame.addView(customView)
	  
      // 2. RecyclerView 설정
      val recyclerView: RecyclerView = customView.findViewById(R.id.recyclerView)
      recyclerView.layoutManager = LinearLayoutManager(context)

      // 3. 어댑터 설정
      recyclerView.adapter = OptionAdapter(options) { selectedOption ->
          // 선택된 옵션에 따라 checked 상태와 텍스트, 값 업데이트
          options.forEach { it.checked = it == selectedOption }
          setText(selectedOption.label)
          value = selectedOption.value
          hidePopup()
      }
  }
  1. 옵션 리스트 UI를 인플레이트하고, FrameLayout에 추가합니다.
  2. RecyclerView를 설정해 스크롤 가능한 옵션 목록을 표시합니다.
  3. 선택한 옵션에 따라 텍스트와 값을 업데이트하고, 선택 UI를 닫습니다.

3-2. OptionAdapter

옵션 목록을 리스트 형태로 표시하고, 선택된 옵션을 처리하는 어댑터입니다.

private inner class OptionAdapter(
        private val options: Array<SelectItem>,
        private val itemClickListener: (SelectItem) -> Unit
    ) : RecyclerView.Adapter<OptionAdapter.OptionViewHolder>() 

OptionAdapteroptions 배열과 선택 리스너를 받아, 옵션을 선택하면 해당 옵션의 상태를 업데이트합니다. 이를 통해 사용자가 선택한 값이 반영되도록 합니다.

3-3. setupBottomSheetDialog

Bottom Sheet 다이얼로그를 초기화하고 설정된 UI를 화면에 띄우는 메서드입니다.

private fun setupBottomSheetDialog(bottomSheetView: View) {
    bottomSheetDialog = BottomSheetDialog(context).apply {
        setContentView(bottomSheetView)
        setOnShowListener {
            val parentLayout = bottomSheetView.parent as ViewGroup
            parentLayout.setBackgroundResource(android.R.color.transparent)
        }
        setOnCancelListener {
            setUnderlineColor(R.color.disable)
        }
    }

    setupBottomSheetBehavior(bottomSheetView)
    bottomSheetDialog.show()
}

showOptions() 메서드에서 인플레이트한 bottomSheetView다이얼로그의 콘텐츠로 설정하고, 화면에 노출합니다. 이를 통해 사용자가 옵션을 선택할 수 있는 인터페이스가 제공됩니다.


3줄 요약

  1. SelectItem 데이터 클래스와 CustomSelect옵션 목록선택 상태를 관리합니다.
  2. getValue() 메서드를 통해 선택된 옵션의 값을 쉽게 가져와 다른 프로세스에서 활용할 수 있습니다.
  3. Bottom Sheet 다이얼로그를 사용해 옵션 목록을 선택 UI로 제공하며, 선택된 값은 CustomSelect에 반영됩니다.

0개의 댓글