তারিখ বাছাইকারী

ডেট পিকার ব্যবহারকারীদের একটি তারিখ, একটি তারিখের পরিসর বা উভয়ই নির্বাচন করতে দেয়। তারিখ নির্বাচন করার জন্য এগুলি একটি ক্যালেন্ডার ডায়ালগ বা টেক্সট ইনপুট ব্যবহার করে।

প্রকারভেদ

তিন ধরনের ডেট পিকার আছে:

  • ডকড : লেআউটের মধ্যেই ইনলাইনভাবে প্রদর্শিত হয়। এটি কম্প্যাক্ট লেআউটের জন্য উপযুক্ত, যেখানে একটি ডেডিকেটেড ডায়ালগ বক্সকে অনাকাঙ্ক্ষিত মনে হতে পারে।
  • মোডাল : অ্যাপের কন্টেন্টের উপরে একটি ডায়ালগ বক্স হিসেবে প্রদর্শিত হয়। এর মাধ্যমে তারিখ নির্বাচনের উপর সুস্পষ্টভাবে মনোযোগ দেওয়া যায়।
  • মোডাল ইনপুট : একটি টেক্সট ফিল্ড এবং একটি মোডাল ডেট পিকারের সমন্বয়।

আপনি নিম্নলিখিত কম্পোজেবলগুলো ব্যবহার করে আপনার অ্যাপে এই ডেট পিকারগুলো প্রয়োগ করতে পারেন:

  • DatePicker : একটি ডেটপিকারের জন্য সাধারণ কম্পোজেবল। আপনি যে কন্টেইনারটি ব্যবহার করেন, তা নির্ধারণ করে এটি ডকড হবে নাকি মডেল।
  • DatePickerDialog : মোডাল এবং মোডাল ইনপুট উভয় প্রকার ডেট পিকারের জন্য ধারক।
  • DateRangePicker : যেকোনো ডেট পিকারের জন্য, যেখানে ব্যবহারকারী একটি শুরু এবং শেষ তারিখ সহ একটি পরিসর নির্বাচন করতে পারেন।

রাজ্য

বিভিন্ন ডেট পিকার কম্পোজেবলগুলোর মধ্যে একটি সাধারণ মূল প্যারামিটার হলো state , যা একটি DatePickerState বা DateRangePickerState অবজেক্ট গ্রহণ করে। এদের প্রোপার্টিগুলো ডেট পিকার ব্যবহার করে ব্যবহারকারীর নির্বাচন সম্পর্কিত তথ্য ধারণ করে, যেমন বর্তমানে নির্বাচিত তারিখ।

আপনি কীভাবে নির্বাচিত তারিখটি ব্যবহার করতে পারেন সে সম্পর্কে আরও তথ্যের জন্য, ‘নির্বাচিত তারিখের ব্যবহার’ বিভাগটি দেখুন।

ডক করা তারিখ বাছাইকারী

নিচের উদাহরণটিতে একটি টেক্সট ফিল্ড রয়েছে, যেখানে ব্যবহারকারীকে তার জন্মতারিখ লিখতে বলা হয়েছে। যখন ব্যবহারকারী ফিল্ডটির ক্যালেন্ডার আইকনে ক্লিক করেন, তখন ইনপুট ফিল্ডটির নিচে একটি ডক করা ডেট পিকার খুলে যায়।

@Composable
fun DatePickerDocked() {
    var showDatePicker by remember { mutableStateOf(false) }
    val datePickerState = rememberDatePickerState()
    val selectedDate = datePickerState.selectedDateMillis?.let {
        convertMillisToDate(it)
    } ?: ""

    Box(
        modifier = Modifier.fillMaxWidth()
    ) {
        OutlinedTextField(
            value = selectedDate,
            onValueChange = { },
            label = { Text("DOB") },
            readOnly = true,
            trailingIcon = {
                IconButton(onClick = { showDatePicker = !showDatePicker }) {
                    Icon(
                        imageVector = Icons.Default.DateRange,
                        contentDescription = "Select date"
                    )
                }
            },
            modifier = Modifier
                .fillMaxWidth()
                .height(64.dp)
        )

        if (showDatePicker) {
            Popup(
                onDismissRequest = { showDatePicker = false },
                alignment = Alignment.TopStart
            ) {
                Box(
                    modifier = Modifier
                        .fillMaxWidth()
                        .offset(y = 64.dp)
                        .shadow(elevation = 4.dp)
                        .background(MaterialTheme.colorScheme.surface)
                        .padding(16.dp)
                ) {
                    DatePicker(
                        state = datePickerState,
                        showModeToggle = false
                    )
                }
            }
        }
    }
}

@Composable
fun DatePickerFieldToModal(modifier: Modifier = Modifier) {
    var selectedDate by remember { mutableStateOf<Long?>(null) }
    var showModal by remember { mutableStateOf(false) }

    OutlinedTextField(
        value = selectedDate?.let { convertMillisToDate(it) } ?: "",
        onValueChange = { },
        label = { Text("DOB") },
        placeholder = { Text("MM/DD/YYYY") },
        trailingIcon = {
            Icon(Icons.Default.DateRange, contentDescription = "Select date")
        },
        modifier = modifier
            .fillMaxWidth()
            .pointerInput(selectedDate) {
                awaitEachGesture {
                    // Modifier.clickable doesn't work for text fields, so we use Modifier.pointerInput
                    // in the Initial pass to observe events before the text field consumes them
                    // in the Main pass.
                    awaitFirstDown(pass = PointerEventPass.Initial)
                    val upEvent = waitForUpOrCancellation(pass = PointerEventPass.Initial)
                    if (upEvent != null) {
                        showModal = true
                    }
                }
            }
    )

    if (showModal) {
        DatePickerModal(
            onDateSelected = { selectedDate = it },
            onDismiss = { showModal = false }
        )
    }
}

fun convertMillisToDate(millis: Long): String {
    val formatter = SimpleDateFormat("MM/dd/yyyy", Locale.getDefault())
    return formatter.format(Date(millis))
}

কোড সম্পর্কে মূল বিষয়গুলো

  • ব্যবহারকারী IconButton ক্লিক করলে ডেট পিকারটি প্রদর্শিত হয়।
    • আইকন বাটনটি OutlinedTextField এর trailingIcon প্যারামিটারের আর্গুমেন্ট হিসেবে কাজ করে।
    • showDatePicker স্টেট ভেরিয়েবলটি ডক করা ডেট পিকারের দৃশ্যমানতা নিয়ন্ত্রণ করে।
  • ডেট পিকারের কন্টেইনারটি একটি কম্পোজেবল Popup , যা অন্যান্য এলিমেন্টের লেআউটকে প্রভাবিত না করে কন্টেন্টের উপর স্থাপন করা হয়।
  • selectedDate DatePickerState অবজেক্ট থেকে নির্বাচিত তারিখের মান গ্রহণ করে এবং convertMillisToDate ফাংশন ব্যবহার করে সেটিকে ফরম্যাট করে।
  • নির্বাচিত তারিখটি টেক্সট ফিল্ডে প্রদর্শিত হয়।
  • ডক করা ডেট পিকারটিকে একটি offset মডিফায়ার ব্যবহার করে টেক্সট ফিল্ডের নিচে স্থাপন করা হয়েছে।
  • টেক্সট ফিল্ড এবং ডেট পিকারের যথাযথ স্তরবিন্যাস নিশ্চিত করার জন্য একটি Box রুট কন্টেইনার হিসেবে ব্যবহার করা হয়।

ফলাফল

ক্যালেন্ডার আইকনে ক্লিক করার পর, এই বাস্তবায়নটি নিম্নরূপভাবে প্রদর্শিত হয়:

ডক করা ডেট পিকারের উদাহরণ।
চিত্র ১. একটি ডক করা তারিখ পিকার।

একটি মোডাল ডেট পিকার স্ক্রিনের উপর ভাসমান একটি ডায়ালগ প্রদর্শন করে। এটি বাস্তবায়ন করতে, একটি DatePickerDialog তৈরি করুন এবং এতে একটি DatePicker পাস করুন।

@Composable
fun DatePickerModal(
    onDateSelected: (Long?) -> Unit,
    onDismiss: () -> Unit
) {
    val datePickerState = rememberDatePickerState()

    DatePickerDialog(
        onDismissRequest = onDismiss,
        confirmButton = {
            TextButton(onClick = {
                onDateSelected(datePickerState.selectedDateMillis)
                onDismiss()
            }) {
                Text("OK")
            }
        },
        dismissButton = {
            TextButton(onClick = onDismiss) {
                Text("Cancel")
            }
        }
    ) {
        DatePicker(state = datePickerState)
    }
}

  • DatePickerModal কম্পোজেবল ফাংশনটি একটি মোডাল ডেট পিকার প্রদর্শন করে।
  • ব্যবহারকারী যখন কোনো তারিখ নির্বাচন করেন, তখন onDateSelected ল্যাম্বডা এক্সপ্রেশনটি কার্যকর হয়।
    • এটি নির্বাচিত তারিখটিকে প্যারেন্ট কম্পোজেবলের কাছে প্রকাশ করে।
  • ব্যবহারকারী যখন ডায়ালগটি বাতিল করেন, তখন onDismiss ল্যাম্বডা এক্সপ্রেশনটি কার্যকর হয়।

ফলাফল

এই বাস্তবায়নটি নিম্নরূপ:

মোডাল ডেট পিকারের উদাহরণ।
চিত্র ২. একটি মোডাল ডেট পিকার।

ইনপুট মোডাল ডেট পিকার

ইনপুটসহ একটি মোডাল ডেট পিকার স্ক্রিনের উপর ভাসমান একটি ডায়ালগ প্রদর্শন করে, যা ব্যবহারকারীকে একটি তারিখ ইনপুট করার সুযোগ দেয়।

@Composable
fun DatePickerModalInput(
    onDateSelected: (Long?) -> Unit,
    onDismiss: () -> Unit
) {
    val datePickerState = rememberDatePickerState(initialDisplayMode = DisplayMode.Input)

    DatePickerDialog(
        onDismissRequest = onDismiss,
        confirmButton = {
            TextButton(onClick = {
                onDateSelected(datePickerState.selectedDateMillis)
                onDismiss()
            }) {
                Text("OK")
            }
        },
        dismissButton = {
            TextButton(onClick = onDismiss) {
                Text("Cancel")
            }
        }
    ) {
        DatePicker(state = datePickerState)
    }
}

এটি মোডাল ডেট পিকার উদাহরণটির মতোই। প্রধান পার্থক্যটি হলো নিম্নরূপ:

  • initialDisplayMode প্যারামিটারটি প্রাথমিক ডিসপ্লে মোডকে DisplayMode.Input এ সেট করে।
ইনপুট সহ মোডাল ডেট পিকার।
চিত্র ৩. ইনপুটসহ একটি মোডাল ডেট পিকার।

রেঞ্জ সহ তারিখ বাছাইকারী

আপনি এমন একটি ডেট পিকার তৈরি করতে পারেন যা ব্যবহারকারীকে একটি শুরু এবং শেষ তারিখের মধ্যে একটি পরিসর নির্বাচন করতে দেয়। এটি করার জন্য, DateRangePicker ব্যবহার করুন।

DateRangePicker এর ব্যবহার মূলত DatePicker মতোই। আপনি এটিকে PopUp এর চাইল্ড হিসেবে একটি ডকড পিকার হিসেবে ব্যবহার করতে পারেন, অথবা একটি মোডাল পিকার হিসেবে ব্যবহার করে DatePickerDialog এ পাস করতে পারেন। মূল পার্থক্য হলো, এখানে DatePickerState এর পরিবর্তে DateRangePickerState ব্যবহার করা হয়।

নিম্নলিখিত কোড স্নিপেটটি দেখায় কিভাবে একটি রেঞ্জ সহ মোডাল ডেট পিকার তৈরি করতে হয়:

@Composable
fun DateRangePickerModal(
    onDateRangeSelected: (Pair<Long?, Long?>) -> Unit,
    onDismiss: () -> Unit
) {
    val dateRangePickerState = rememberDateRangePickerState()

    DatePickerDialog(
        onDismissRequest = onDismiss,
        confirmButton = {
            TextButton(
                onClick = {
                    onDateRangeSelected(
                        Pair(
                            dateRangePickerState.selectedStartDateMillis,
                            dateRangePickerState.selectedEndDateMillis
                        )
                    )
                    onDismiss()
                }
            ) {
                Text("OK")
            }
        },
        dismissButton = {
            TextButton(onClick = onDismiss) {
                Text("Cancel")
            }
        }
    ) {
        DateRangePicker(
            state = dateRangePickerState,
            title = {
                Text(
                    text = "Select date range"
                )
            },
            showModeToggle = false,
            modifier = Modifier
                .fillMaxWidth()
                .height(500.dp)
                .padding(16.dp)
        )
    }
}

কোড সম্পর্কে মূল বিষয়গুলো

  • onDateRangeSelected প্যারামিটারটি একটি কলব্যাক, যা নির্বাচিত শুরু এবং শেষের তারিখ নির্দেশকারী একটি Pair<Long?, Long?> গ্রহণ করে। এটি প্যারেন্টকে নির্বাচিত রেঞ্জটিতে কম্পোজেবল অ্যাক্সেস প্রদান করে।
  • rememberDateRangePickerState() ডেট রেঞ্জ পিকারের জন্য স্টেট তৈরি করে।
  • DatePickerDialog একটি মোডাল ডায়ালগ কন্টেইনার তৈরি করে।
  • কনফার্ম বাটনের onClick হ্যান্ডলারে, onDateRangeSelected ফাংশনটি নির্বাচিত রেঞ্জটিকে প্যারেন্ট কম্পোজেবল-এর কাছে পাঠিয়ে দেয়।
  • DateRangePicker কম্পোজেবলটি ডায়ালগের বিষয়বস্তু হিসেবে কাজ করে।

ফলাফল

এই বাস্তবায়নটি নিম্নরূপ:

মোডাল রেঞ্জ ডেট পিকারের উদাহরণ।
চিত্র ৪. নির্বাচিত পরিসরসহ একটি মোডাল ডেট পিকার।

নির্বাচিত তারিখ ব্যবহার করুন

নির্বাচিত তারিখটি গ্রহণ করতে, প্যারেন্ট কম্পোজেবলে এটিকে একটি Long হিসেবে ট্র্যাক করুন এবং onDateSelected এ ভ্যালুটি DatePicker এ পাস করুন। নিচের কোড স্নিপেটটি এটি প্রদর্শন করে, যদিও আপনি অফিসিয়াল স্নিপেটস অ্যাপে এর সম্পূর্ণ বাস্তবায়ন দেখতে পারেন।

// ...
    var selectedDate by remember { mutableStateOf<Long?>(null) }
// ...
        if (selectedDate != null) {
            val date = Date(selectedDate!!)
            val formattedDate = SimpleDateFormat("MMM dd, yyyy", Locale.getDefault()).format(date)
            Text("Selected date: $formattedDate")
        } else {
            Text("No date selected")
        }
// ...
        DatePickerModal(
            onDateSelected = {
                selectedDate = it
                showModal = false
            },
            onDismiss = { showModal = false }
        )
    }
// ...

রেঞ্জ ডেট পিকারের ক্ষেত্রেও মূলত একই নিয়ম প্রযোজ্য, তবে শুরু এবং শেষের মানগুলো নেওয়ার জন্য আপনাকে একটি Pair<Long?, Long?> অথবা একটি ডেটা ক্লাস ব্যবহার করতে হবে।

আরও দেখুন