সেভ করা পৃষ্ঠা গুছিয়ে রাখতে 'সংগ্রহ' ব্যবহার করুন
আপনার পছন্দ অনুযায়ী কন্টেন্ট সেভ করুন ও সঠিক বিভাগে রাখুন।
সংলাপ দৃশ্য সজ্জাকার রেসিপি
এই রেসিপিটি একটি ডায়ালগের মধ্যে কোনো দৃশ্য প্রদর্শনের একটি পদ্ধতি তুলে ধরে। উদাহরণস্বরূপ, অ্যাপটি যখন একটি প্রসারিত উইন্ডোতে থাকে তখন একটি তালিকা-বিস্তারিত সেটিংস UI-কে ওভারলে হিসাবে, এবং অন্যথায় পূর্ণ স্ক্রিনের পৃষ্ঠা হিসাবে প্রদর্শন করতে এটি ব্যবহার করা যেতে পারে।
এটি কীভাবে কাজ করে
একটি ডায়ালগের মধ্যে কোনো দৃশ্য প্রদর্শন করতে, আপনাকে নিম্নলিখিত কাজগুলো করতে হবে:
- একটি ডায়ালগ
SceneDecorationStrategy তৈরি করুন : এই রেসিপিটি DialogSceneDecoratorStrategy এবং সেইসাথে DialogDecoratorScene সংজ্ঞায়িত করে, যা একটি ডায়ালগের মধ্যে ইনপুট Scene উপস্থাপন করতে ব্যবহৃত হয়। একটি ডায়ালগ সিন ডেকোরেশন স্ট্র্যাটেজি সংজ্ঞায়িত করার সময়, নিম্নলিখিত বিষয়গুলো বিবেচনা করুন:- একটি ডায়ালগের মধ্যে কখন একটি সিন প্রদর্শন করা যেতে পারে? এই রেসিপিতে, সিনগুলি একটি ডায়ালগে তখনই প্রদর্শিত হয় যখন উইন্ডোর প্রস্থ অন্ততপক্ষে প্রসারিত থাকে।
- কোন মেটাডেটার উপর ভিত্তি করে একটি সিন কোনো ডায়ালগের মধ্যে প্রদর্শিত হবে কিনা তা নির্ধারণ করা উচিত? এই রেসিপিতে, একটি সিন ডায়ালগে প্রদর্শিত হয় যদি সেই সিনের প্রথম এন্ট্রিতে '
DialogSceneMetadataKey মেটাডেটা থাকে। আপনার ব্যবহারের ধরনের উপর নির্ভর করে, অন্য কোনো পদ্ধতি, যেমন সিনের ভেতরের সমস্ত এন্ট্রিতে একই মেটাডেটা থাকা বাধ্যতামূলক করা, আরও উপযুক্ত হতে পারে। - ডায়ালগটি বাতিল করার আচরণ কী? এই রেসিপিতে, ডায়ালগের বাইরে ক্লিক করলে সিন-এর সমস্ত এন্ট্রি মুছে যায়, যেখানে ব্যাক জেসচার বা প্রেস করলে একবারে কেবল একটি করে এন্ট্রি মোছা হয়। রেসিপিটি
DialogDecoratorSceneConfiguration ক্লাসের মাধ্যমে এই আচরণের জন্য কনফিগারেশন প্রদান করে।
- আপনার ডায়ালগ
SceneDecorationStrategy ব্যবহার করুন : আপনার সিন ডেকারেটর স্ট্র্যাটেজি ব্যবহার করতে, এটিকে sceneDecoratorStrategies প্যারামিটারের অংশ হিসেবে NavDisplay তে পাস করুন।- সতর্কতা: যেহেতু
NavDisplay OverlayScene ইনস্ট্যান্সগুলোকে ডেকোরেট করে না, তাই sceneDecoratorStrategies তালিকার মধ্যে আপনার ডায়ালগ সিন ডেকোরেশন স্ট্র্যাটেজির অবস্থানের দিকে আপনাকে মনোযোগ দিতে হতে পারে। এটি দিয়ে কোনো সিন ডেকোরেট করলে, পরবর্তী সিন ডেকোরেশন স্ট্র্যাটেজিগুলোর ডেকোরেশন বাধাগ্রস্ত হবে। - সতর্কতা: বাতিল করার জন্য এন্ট্রিগুলো শনাক্ত করতে
contentKey ব্যবহার করে onDismissAll প্রয়োগ করার সময় মনে রাখবেন যে, ডিফল্টরূপে contentKey key.toString() ব্যবহার করে। এই পদ্ধতিতে আমরা backStack.removeAll { it.toString() in contentKeys } ব্যবহার করেছি, যা সাধারণ অবজেক্ট কী-গুলোর জন্য কাজ করে, কিন্তু আরও জটিল কী বা কাস্টম contentKey ইমপ্লিমেন্টেশনের জন্য এতে পরিবর্তনের প্রয়োজন হতে পারে।

অন্বেষণ করুন
সম্পূর্ণ রেসিপিটি গিটহাবে দেখুন।
arrow_forward package com.example.nav3recipes.dialogscenedecorator
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.SharedTransitionLayout
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.lifecycle.compose.dropUnlessResumed
import androidx.navigation3.runtime.NavKey
import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.runtime.rememberNavBackStack
import androidx.navigation3.ui.NavDisplay
import com.example.nav3recipes.content.ContentBlue
import com.example.nav3recipes.content.ContentGreen
import com.example.nav3recipes.content.ContentYellow
import com.example.nav3recipes.scenes.listdetail.ListDetailScene
import com.example.nav3recipes.scenes.listdetail.rememberListDetailSceneStrategy
import com.example.nav3recipes.ui.setEdgeToEdgeConfig
import kotlinx.serialization.Serializable
@Serializable
private data object Main : NavKey
@Serializable
private data object SettingsList : NavKey
@Serializable
private data object SettingsDetail : NavKey
class DialogSceneDecoratorActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setEdgeToEdgeConfig()
setContent {
val backStack = rememberNavBackStack(Main)
val listDetailSceneStrategy = rememberListDetailSceneStrategy<NavKey>()
val dialogSceneDecoratorStrategy = rememberDialogSceneDecoratorStrategy<NavKey>(
onDismissAll = { entriesToDismiss ->
// Caution: This relies on the default behavior of NavEntry using key.toString()
// to define its contentKey property.
entriesToDismiss.forEach { entry ->
backStack
.indexOfLast { it.toString() == entry.contentKey }
.takeIf { it >= 0 }
?.let { backStack.removeAt(it) }
}
}
)
SharedTransitionLayout {
NavDisplay(
backStack = backStack,
onBack = { backStack.removeLastOrNull() },
sceneStrategies = listOf(listDetailSceneStrategy),
sceneDecoratorStrategies = listOf(dialogSceneDecoratorStrategy),
sharedTransitionScope = this,
entryProvider = entryProvider {
entry<Main> {
ContentGreen("Welcome to Nav3") {
Button(onClick = dropUnlessResumed {
backStack.add(SettingsList)
}) {
Text("Click to open settings")
}
}
}
entry<SettingsList>(
metadata = DialogSceneDecoratorStrategy.sceneDialog(
DialogDecoratorSceneConfiguration(
backDismissalBehavior = DismissalBehavior.Single
)
) + ListDetailScene.listPane()
) {
ContentBlue(
title = "Settings List",
) {
Button(onClick = dropUnlessResumed {
if (backStack.last() !is SettingsDetail) {
backStack.add(SettingsDetail)
}
}) {
Text("Open detail")
}
}
}
entry<SettingsDetail>(
metadata = ListDetailScene.detailPane()
) {
ContentYellow("Settings Detail")
}
}
)
}
}
}
}
package com.example.nav3recipes.dialogscenedecorator
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Surface
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfoV2
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import androidx.compose.ui.window.SecureFlagPolicy
import androidx.navigation3.runtime.NavEntry
import androidx.navigation3.runtime.NavMetadataKey
import androidx.navigation3.runtime.get
import androidx.navigation3.runtime.metadata
import androidx.navigation3.scene.OverlayScene
import androidx.navigation3.scene.Scene
import androidx.navigation3.scene.SceneDecoratorStrategy
import androidx.navigation3.scene.SceneDecoratorStrategyScope
import androidx.window.core.layout.WindowSizeClass
fun DialogProperties.copy(
dismissOnBackPress: Boolean = this.dismissOnBackPress,
dismissOnClickOutside: Boolean = this.dismissOnClickOutside,
securePolicy: SecureFlagPolicy = this.securePolicy,
usePlatformDefaultWidth: Boolean = this.usePlatformDefaultWidth,
decorFitsSystemWindows: Boolean = this.decorFitsSystemWindows,
windowTitle: String = this.windowTitle
): DialogProperties = DialogProperties(
dismissOnBackPress = dismissOnBackPress,
dismissOnClickOutside = dismissOnClickOutside,
securePolicy = securePolicy,
usePlatformDefaultWidth = usePlatformDefaultWidth,
decorFitsSystemWindows = decorFitsSystemWindows,
windowTitle = windowTitle
)
enum class DismissalBehavior {
All, Single
}
/**
* Configuration for the [DialogDecoratorScene].
*
* @property dialogProperties The [DialogProperties] used to configure the dialog.
* @property backDismissalBehavior Whether all entries in the scene should be dismissed when the
* back button is pressed. This configuration only applies if the
* [DialogProperties.dismissOnBackPress] is set to `true`.
*
*/
class DialogDecoratorSceneConfiguration(
val dialogProperties: DialogProperties = DialogProperties(),
val backDismissalBehavior: DismissalBehavior = DismissalBehavior.Single,
val shape: Shape = RoundedCornerShape(16.dp),
) {
fun toDialogProperties(): DialogProperties {
// If the desired behavior is to not dismiss all, the DialogProperties passed to the Dialog
// needs to be configured to not handle the back press itself.
if (dialogProperties.dismissOnBackPress && backDismissalBehavior != DismissalBehavior.All) {
return dialogProperties.copy(dismissOnBackPress = false)
}
return dialogProperties
}
fun shouldDismissSingleOnBackPress() =
dialogProperties.dismissOnBackPress && backDismissalBehavior == DismissalBehavior.Single
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
other as DialogDecoratorSceneConfiguration
return dialogProperties == other.dialogProperties &&
backDismissalBehavior == other.backDismissalBehavior &&
shape == other.shape
}
override fun hashCode(): Int {
return dialogProperties.hashCode() * 31 +
backDismissalBehavior.hashCode() * 31 +
shape.hashCode() * 31
}
}
/**
* [DialogDecoratorScene] is an [OverlayScene] used by [DialogSceneDecoratorStrategy] to present
* another [Scene] within a [Dialog].
*
* @property scene The [Scene] to be displayed within the dialog.
* @property overlaidEntries The [NavEntry]s that are overlaid by the dialog.
* @property dialogDecoratorSceneConfiguration The [DialogDecoratorSceneConfiguration] used to
* configure the dialog scene.
* @property onBack The callback to be invoked when a back event should be handled
* @property onDismissAll The callback to be invoked when the entire dialog stack should be dismissed
**/
data class DialogDecoratorScene<T : Any>(
private val scene: Scene<T>,
override val overlaidEntries: List<NavEntry<T>>,
private val dialogDecoratorSceneConfiguration: DialogDecoratorSceneConfiguration,
private val onBack: () -> Unit,
private val onDismissAll: () -> Unit
) : OverlayScene<T>, Scene<T> by scene {
override val content: @Composable () -> Unit = {
Dialog(
onDismissRequest = onDismissAll,
properties = dialogDecoratorSceneConfiguration.toDialogProperties()
) {
Surface(
shape = dialogDecoratorSceneConfiguration.shape
) {
scene.content()
}
// Because back events are dispatched to the currently focused window, this back handler
// must be contained within the dialog's content to receive the events.
BackHandler(dialogDecoratorSceneConfiguration.shouldDismissSingleOnBackPress()) {
onBack()
}
}
}
}
@Composable
fun <T : Any> rememberDialogSceneDecoratorStrategy(
windowSizeClass: WindowSizeClass = currentWindowAdaptiveInfoV2().windowSizeClass,
onDismissAll: ((List<NavEntry<T>>) -> Unit)
): DialogSceneDecoratorStrategy<T> = remember(windowSizeClass, onDismissAll) {
DialogSceneDecoratorStrategy(windowSizeClass, onDismissAll = onDismissAll)
}
/**
* A [SceneDecoratorStrategy] that wraps a [Scene] in a [DialogDecoratorScene] if the first
* [NavEntry] within it has been marked with the [DialogSceneMetadataKey] and the window width
* is at least [WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND].
*
* If you only need to display a single [NavEntry] in a [Dialog], using
* [androidx.navigation3.scene.DialogSceneStrategy] instead may be preferable.
*
* @property windowSizeClass The current [WindowSizeClass] used to determine if dialogs should be used.
* @property windowWidthDpBreakpoint the width in dp at or above which a dialog should be displayed.
* @property onDismissAll callback invoked to dismiss all dialog entries, receives the entries that
* are currently in the dialog.
*/
class DialogSceneDecoratorStrategy<T : Any>(
private val windowSizeClass: WindowSizeClass,
private val windowWidthDpBreakpoint: Int = WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND,
private val onDismissAll: (List<NavEntry<T>>) -> Unit
) : SceneDecoratorStrategy<T> {
override fun SceneDecoratorStrategyScope<T>.decorateScene(scene: Scene<T>): Scene<T> {
if (!windowSizeClass.isWidthAtLeastBreakpoint(windowWidthDpBreakpoint)) return scene
val dialogDecoratorSceneConfiguration =
scene.entries.firstOrNull()?.metadata[DialogSceneMetadataKey] ?: return scene
// This is critical to ensure that the scenes rendered beneath the dialog don't contain
// any entries that are in the dialog.
val overlaidEntries = scene.previousEntries.dropLastWhile { it in scene.entries }
return DialogDecoratorScene(
scene,
overlaidEntries,
dialogDecoratorSceneConfiguration,
onBack,
onDismissAll = { onDismissAll.invoke(scene.entries) })
}
companion object {
object DialogSceneMetadataKey : NavMetadataKey<DialogDecoratorSceneConfiguration>
fun sceneDialog(dialogDecoratorSceneConfiguration: DialogDecoratorSceneConfiguration = DialogDecoratorSceneConfiguration()): Map<String, Any> =
metadata {
put(DialogSceneMetadataKey, dialogDecoratorSceneConfiguration)
}
}
}
এই পৃষ্ঠার কন্টেন্ট ও কোডের নমুনাগুলি Content License-এ বর্ণিত লাইসেন্সের অধীনস্থ। Java এবং OpenJDK হল Oracle এবং/অথবা তার অ্যাফিলিয়েট সংস্থার রেজিস্টার্ড ট্রেডমার্ক।
2026-05-09 UTC-তে শেষবার আপডেট করা হয়েছে।
[[["সহজে বোঝা যায়","easyToUnderstand","thumb-up"],["আমার সমস্যার সমাধান হয়েছে","solvedMyProblem","thumb-up"],["অন্যান্য","otherUp","thumb-up"]],[["এতে আমার প্রয়োজনীয় তথ্য নেই","missingTheInformationINeed","thumb-down"],["খুব জটিল / অনেক ধাপ","tooComplicatedTooManySteps","thumb-down"],["পুরনো","outOfDate","thumb-down"],["অনুবাদ সংক্রান্ত সমস্যা","translationIssue","thumb-down"],["নমুনা / কোড সংক্রান্ত সমস্যা","samplesCodeIssue","thumb-down"],["অন্যান্য","otherDown","thumb-down"]],["2026-05-09 UTC-তে শেষবার আপডেট করা হয়েছে।"],[],[]]