[Android/Java] NumberPicker Custom

doooly·2023년 12월 16일
0

Android

목록 보기
2/5

NumberPicker Custom

Android에서 NumberPicker을 custom하는 법에 대해 포스팅하겠습니다
custom한 결과는 아래⬇️와 같습니다

안드로이드에는 DatePicker, TimePicker, NumberPicker 등 다양한 Picker이 존재합니다

TimePicker의 경우, spinnerclock mode가 존재합니다

많이 사용되는 timePicker의 spinner모드를 이용해 cutom을 하려 했으나, 숫자만을 고르는 spinner을 만들기 위해 numberPicker을 이용했습니다




✅ Intro

기획의도는 다음과 같습니다

앞 선 다이얼로그에서 시간을 지정하는 버튼을 누르면, 해당 다이얼로그가 나타납니다
spinner를 통해 숫자를 골라 확인을 누르면, 해당 데이터가 이전 다이얼로그로 전달됩니다



✅ xml 만들기

custom dialog를 만들기 위해 xml을 만들어주었습니다
xml에서는 numberPicker 요소를 추가해주었고, picker에 대한 설정은 class 내부에서 추가할 예정입니다

custom dialog에 대한 추가적인 설명은 https://velog.io/@dooo_it_ly/AndroidJava-Dialog-Custom
을 참고해주세요 ‼️

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:paddingHorizontal="30dp">

    <NumberPicker
        android:id="@+id/makar_alarm_time_picker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:paddingHorizontal="20dp"/>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:layout_gravity="center"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="20dp">

        <Button
            android:id="@+id/close_makar_alarm_time_btn"
            android:layout_width="110dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="15dp"
            android:background="@drawable/custom_button_white"
            android:text="@string/close_button"
            android:textColor="@color/black"
            android:textSize="16sp"
            android:textStyle="bold" />

        <Button
            android:id="@+id/set_makar_alarm_time_btn"
            android:layout_width="110dp"
            android:layout_height="wrap_content"
            android:background="@drawable/custom_button_main"
            android:text="@string/register_button"
            android:textColor="@color/white"
            android:textSize="16sp"
            android:textStyle="bold" />
    </LinearLayout>
</LinearLayout>

xml에 대한 디자인은 다음과 같습니다



✅ dialog class 생성

numberPiceker를 담을 customDialog class를 만들어줍니다

  • Dialog extend
  • xml을 contentView로 설정
  • dialog background custom drawable 리소스 설정
  • 생성자 생성

public class SetGetOffAlarmTimeDialog extends Dialog {
    private Context context;
    private NumberPicker alarmTimePicker;
    private Button positiveBtn, negativeBtn;
    
    private int getOffAlarmTime = MainActivity.user.getGetOffAlarmTime();
    
    public SetGetOffAlarmTimeDialog(@NonNull Context context) {
        super(context);
        this.context = context;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setBackgroundDrawableResource(R.drawable.custom_dialog_background);
        setContentView(R.layout.dialog_set_getoff_alarm_time);
     }
 }




✅ numberPicker 설정

timeArr라는 배열을 만들고, spinner에 담을 수들을 넣어줍니다
numberPicker의 함수들은 String type을 다루기 때문에 위의 배열 타입을 String으로 지정하는 것이 코드 사용에 더 용이합니다 ‼️


setAlarmTimePicker()함수를 만들어 picker에 나타날 값들을 설정한 배열로 설정해줍니다
setMinValue는 spinner의 최소값이고, setMaxValue는 최대값입니다
저는 배열의 0번 인덱스부터 5번 인덱스를 각각 최소, 최대 값으로 지정해주었습니다

 private String[] timeArr = {"10", "20", "30", "40", "50", "60"};
 
     private void setAlarmTimePicker(){
        alarmTimePicker.setDisplayedValues(timeArr);
        alarmTimePicker.setMinValue(0);
        alarmTimePicker.setMaxValue(5);
    }




✅ listener 설정

xml에서 설정해준 positiveBtn, negativeBtn, numberPicker에 대해 listener을 설정해줍니다

‼️ numberPicker은 setOnValueChangedListener라는 값이 변경될 때 호출할 수 있는 리스너를 제공합니다
picker, oldVal, newVal 이라는 3개의 인자가 들어오는데, oldVal은 기존 spinner의 인덱스, newVal은 바뀐 인덱스를 뜻합니다

🔎 제가 스피너의 값을 10에서 40으로 바꿨다면 oldVal은 0, newVal은 3이 들어옵니다 

배열에서 인덱스에 맞는 String을 찾아 Int로 파싱해 사용할 변수에 값을 저장해주었습니다

alarmTimePicker = findViewById(R.id.getoff_alarm_time_picker);
setAlarmTimePicker(); //numberPicker custom
positiveBtn = findViewById(R.id.set_getoff_alarm_time_btn);
negativeBtn = findViewById(R.id.close_getoff_alarm_time_btn);


//alarmpicker에 대한 listener
alarmTimePicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
	@Override
	public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
		getOffAlarmTime = Integer.parseInt(timeArr[newVal]);
      }
});

positiveBtn.setOnClickListener(view -> {
	//분 전달 -> alarmTime 변경
	sendDataToFirstDialog(getOffAlarmTime);
	Toast.makeText(context, "하차 "+getOffAlarmTime+"분 전 알림이 울립니다", Toast.LENGTH_SHORT).show();
	dismiss();
});

negativeBtn.setOnClickListener(view -> {
	dismiss();
});




✅ 결과

아래와 같이 설정한 숫자들을 spin할 수 있는 picker가 완성되었습니다!

40분을 설정한 후 등록 버튼을 누르면 아래와 같이 이전 다이얼로그에 세팅값이 저장되고, 의도한대로 토스트까지 띄워집니다 😊

0개의 댓글