📱 Android

[Android] Custom Spinner

콩드로이드 2022. 8. 9. 15:42

안녕하세요 오늘은 spinner에 대해 사용해보겠습니다 

보통, 문자 인증 시 통신사 선택할 때 자주 사용되는데

저는 DatePicker 대신 년도+월을 선택할 수 있는 Spinner를 만들고자 합니다 

(화면에 날짜를 선택하는 영역을 최대한 줄이고 싶어서요)


Spinner

드롭다운의 형태로 여러 개의 데이터 중 하나의 데이터를 선택할 수 있는 View입니다 

자주 접하는 모양의 View일 거에요, 문자 인증 시 통신사를 선택하거나 이메일 주소를 선택할 때 등등

 

기본 형태는 위와 같지만, 저는 배경도 바꾸고 싶고 icon도 변경하고 싶어서 Custom을 하겠습니다 🚀

 


 

Spinner 사용하기

 

1. xml에 Spinner 선언

<Spinner
   android:id="@+id/spinner"
   android:layout_width="wrap_content"
   android:layout_height="40dp"
   android:layout_marginTop="20dp"
   android:background="@drawable/spinner_bg"
   app:layout_constraintEnd_toEndOf="parent"
   app:layout_constraintStart_toStartOf="parent"
   app:layout_constraintTop_toTopOf="parent" />

 


 

2. Activity or Fragment에 SpinnerAdapter 연결

 

Spinner에 데이터를 표시하기 위해선 SpinnerAdapter를 연결해줘야하는데, 2가지 형태가 가능합니다 

1️⃣ 선택 항목을 배열에서 사용할 수 있는 경우에는 ArrayAdapter 

2️⃣ 선택 항목을 데이터베이스 쿼리에서 사용할 수 있는 경우에는 CursorAdapter

이번 포스팅에선 1️⃣의 ArrayAdapter를 사용하겠습니다 

 


 

3. ArrayAdapter 생성

ArrayAdapter의 원형은 아래와 같습니다 (Context, Layout, 데이터 배열)

public ArrayAdapter(@NonNull Context context, int resource, @NonNull T[] objects) {
    throw new RuntimeException("Stub!");
}

 

@NonNull T[] objects 을 생성하는데 , 이 방법도 2가지가 있어요 

1️⃣ 리소스파일에 선언된 배열을 사용

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="planets_array">
        <item>Mercury</item>
        <item>Venus</item>
        <item>Earth</item>
        <item>Mars</item>
        <item>Jupiter</item>
        <item>Saturn</item>
        <item>Uranus</item>
        <item>Neptune</item>
    </string-array>
</resources>

 

2️⃣ 소스 내의 데이터를 사용

저는 현재 년도, 월 기준으로 beforeCount의 이전까지만 가져올거라 아래처럼 데이터를 채워주고 

fun getCurrentTimeBefore(beforeCount: Int): Array<String> {
    val simple = SimpleDateFormat("yyyyMM", Locale.KOREA)
    val result = simple.format(Date(System.currentTimeMillis()))

    val calendar = Calendar.getInstance()
    calendar.time = simple.parse(result)!!
    val str = ArrayList<String>()

    repeat(beforeCount) {
        val month: String = simple.format(calendar.time)
        str.add(month.substring(0, 4) + "년 " + month.substring(4, 6) + "월")
        calendar.add(Calendar.MONTH, -1)
    }

    return str.toTypedArray()
}

 


4. Spinner Background 및 레이아웃 생성

 

제가 생성하고 싶은 Spinner Background에 맞춰, 오른쪽에 들어갈 이미지 파일을 넣어줍니다 

icon

 

[spinner_bg.xml]

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <solid android:color="#FBF1FF"/>
            <corners android:radius="10dp" />
        </shape>
    </item>
    <item
        android:width="24dp"
        android:height="24dp"
        android:bottom="10dp"
        android:drawable="@drawable/btn_down"
        android:gravity="right|top"
        android:right="8dp"
        android:start="8dp"
        android:top="8dp"/>
</layer-list>

 

[spinner_txt.xml]

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/tv"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingStart="10dp"
    android:paddingTop="8dp"
    android:paddingEnd="33dp"
    android:paddingBottom="10dp"
    android:text="@+id/tv"
    android:textColor="#000000"
    android:textSize="15dp" />

 


5. Spinner Adapter 연결 및 onItemSelectedListener 생성

val arr = getCurrentTimeBefore(6)
var spinnerAdapter =
    ArrayAdapter(this@MainActivity, R.layout.spinner_txt, arr)
spinner.adapter = spinnerAdapter

spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
     override fun onItemSelected(parent: AdapterView<*>, view: View?, pos: Int, id: Long) {
            Toast.makeText(this@MainActivity, arr[pos], Toast.LENGTH_LONG).show()
     }

     override fun onNothingSelected(p0: AdapterView<*>?) {
                //
     }
}

 

onItemSelected(parent: AdapterView<*>, view: View?, pos: Int, id: Long) 

pos를 사용해 현재 선택된 spinner의 데이터를 가져옵니다