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

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

ধরন

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

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

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

  • 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", LocalLocale.current.platformLocale).format(date)
            Text("Selected date: $formattedDate")
        } else {
            Text("No date selected")
        }
// ...
        DatePickerModal(
            onDateSelected = {
                selectedDate = it
                showModal = false
            },
            onDismiss = { showModal = false }
        )
    }
// ...

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

এছাড়াও দেখুন