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

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

ধরন

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

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

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

  • 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's trailingIcon প্যারামিটারের আর্গুমেন্ট হিসেবে কাজ করে।
    • showDatePicker স্টেট ভেরিয়েবল ডক করা তারিখ বেছে নেওয়ার টুলের দৃশ্যমানতা কন্ট্রোল করে।
  • ডেট পিকারের কন্টেনার হল একটি Popup কম্পোজ করা যায় এমন আইটেম, যা অন্যান্য এলিমেন্টের লেআউটকে প্রভাবিত না করেই কন্টেন্টকে ওভারলে করে।
  • selectedDate অবজেক্ট থেকে বেছে নেওয়া তারিখের ভ্যালু ক্যাপচার করে এবং convertMillisToDate ফাংশন ব্যবহার করে সেটি ফর্ম্যাট করে। DatePickerState
  • বেছে নেওয়া তারিখটি টেক্সট ফিল্ডে দেখা যাবে।
  • ডক করা ডেট পিকারটি offset modifier ব্যবহার করে টেক্সট ফিল্ডের নিচে পজিশন করা হয়।
  • টেক্সট ফিল্ড ও তারিখ বাছাইকারীকে সঠিকভাবে লেয়ার করার অনুমতি দিতে, রুট কন্টেনার হিসেবে 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?> বা ডেটা ক্লাস ব্যবহার করতে হবে।

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