XR-এর জন্য Jetpack Compose দিয়ে UI ডেভেলপ করুন

জেটপ্যাক কম্পোজ ফর এক্সআর-এর সাহায্যে, আপনি সারি এবং কলামের মতো পরিচিত কম্পোজ ধারণাগুলি ব্যবহার করে আপনার স্থানিক UI এবং লেআউট ঘোষণামূলকভাবে তৈরি করতে পারেন। এটি আপনাকে আপনার বিদ্যমান অ্যান্ড্রয়েড UI কে 3D স্পেসে প্রসারিত করতে বা সম্পূর্ণ নতুন ইমারসিভ 3D অ্যাপ্লিকেশন তৈরি করতে দেয়।

যদি আপনি একটি বিদ্যমান অ্যান্ড্রয়েড ভিউ-ভিত্তিক অ্যাপ স্পেশালাইজ করেন, তাহলে আপনার কাছে বেশ কয়েকটি ডেভেলপমেন্ট অপশন রয়েছে। আপনি ইন্টারঅপারেবিলিটি API ব্যবহার করতে পারেন, কম্পোজ এবং ভিউ একসাথে ব্যবহার করতে পারেন, অথবা সিনকোর লাইব্রেরির সাথে সরাসরি কাজ করতে পারেন। আরও বিস্তারিত জানার জন্য ভিউ নিয়ে কাজ করার জন্য আমাদের গাইড দেখুন।

উপ-স্থান এবং স্থানিক উপাদান সম্পর্কে

যখন আপনি অ্যান্ড্রয়েড এক্সআর-এর জন্য আপনার অ্যাপ লিখছেন, তখন সাবস্পেস এবং স্পেশিয়ালাইজড কম্পোনেন্টের ধারণাগুলি বোঝা গুরুত্বপূর্ণ।

সাবস্পেস সম্পর্কে

Android XR ডেভেলপ করার সময়, আপনার অ্যাপ বা লেআউটে একটি Subspace যোগ করতে হবে। সাবস্পেস হল আপনার অ্যাপের মধ্যে 3D স্পেসের একটি পার্টিশন যেখানে আপনি 3D কন্টেন্ট রাখতে পারেন, 3D লেআউট তৈরি করতে পারেন এবং অন্যথায় 2D কন্টেন্টে গভীরতা যোগ করতে পারেন। স্পেশিয়ালাইজেশন সক্ষম থাকলেই কেবল একটি সাবস্পেস রেন্ডার করা হয়। হোম স্পেস বা নন-এক্সআর ডিভাইসে, সেই সাবস্পেসের মধ্যে থাকা যেকোনো কোড উপেক্ষা করা হয়।

সাবস্পেস তৈরি করার দুটি উপায় আছে:

  • Subspace : এই কম্পোজেবলটি আপনার অ্যাপের UI হায়ারার্কির যেকোনো জায়গায় স্থাপন করা যেতে পারে, যার ফলে আপনি ফাইলের মধ্যে প্রসঙ্গ না হারিয়ে 2D এবং স্থানিক UI এর জন্য লেআউট বজায় রাখতে পারবেন। এটি XR এবং অন্যান্য ফর্ম ফ্যাক্টরের মধ্যে বিদ্যমান অ্যাপ আর্কিটেকচারের মতো জিনিসগুলি ভাগ করে নেওয়া সহজ করে তোলে, আপনার পুরো UI ট্রিতে অবস্থা উত্তোলন না করে বা আপনার অ্যাপটি পুনরায় আর্কিটেক্ট না করে।
  • ApplicationSubspace : এই ফাংশনটি শুধুমাত্র অ্যাপ-লেভেল সাবস্পেস তৈরি করে এবং আপনার অ্যাপ্লিকেশনের স্পেশিয়াল UI হায়ারার্কির সর্বোচ্চ স্তরে স্থাপন করা আবশ্যক। ApplicationSubspace ঐচ্ছিক VolumeConstraints সহ স্পেশিয়াল কন্টেন্ট রেন্ডার করে। Subspace বিপরীতে, ApplicationSubspace অন্য Subspace বা ApplicationSubspace মধ্যে নেস্ট করা যায় না।

আরও তথ্যের জন্য, আপনার অ্যাপে একটি সাবস্পেস যোগ করুন দেখুন।

স্থানিক উপাদান সম্পর্কে

সাবস্পেস কম্পোজেবল : এই উপাদানগুলি শুধুমাত্র একটি সাবস্পেসে রেন্ডার করা যেতে পারে। 2D লেআউটের মধ্যে স্থাপন করার আগে এগুলিকে Subspace মধ্যে আবদ্ধ করতে হবে। একটি SubspaceModifier আপনাকে আপনার সাবস্পেস কম্পোজেবলগুলিতে গভীরতা, অফসেট এবং অবস্থানের মতো বৈশিষ্ট্য যুক্ত করতে দেয়।

অন্যান্য স্থানিক উপাদানগুলিকে সাবস্পেসের ভিতরে ডাকার প্রয়োজন হয় না। এগুলিতে একটি স্থানিক ধারকের মধ্যে মোড়ানো প্রচলিত 2D উপাদান থাকে। এই উপাদানগুলি 2D বা 3D লেআউটের মধ্যে ব্যবহার করা যেতে পারে যদি উভয়ের জন্য সংজ্ঞায়িত করা হয়। যখন স্থানিককরণ সক্ষম করা না থাকে, তখন তাদের স্থানিক বৈশিষ্ট্যগুলি উপেক্ষা করা হবে এবং সেগুলি তাদের 2D প্রতিরূপে ফিরে যাবে।

একটি স্থানিক প্যানেল তৈরি করুন

একটি SpatialPanel হল একটি সাবস্পেস কম্পোজেবল যা আপনাকে অ্যাপের কন্টেন্ট প্রদর্শন করতে দেয় - উদাহরণস্বরূপ, আপনি একটি স্পেশিয়াল প্যানেলে ভিডিও প্লেব্যাক, স্থির চিত্র বা অন্য কোনও কন্টেন্ট প্রদর্শন করতে পারেন।

একটি স্থানিক UI প্যানেলের উদাহরণ

আপনি SubspaceModifier ব্যবহার করে স্থানিক প্যানেলের আকার, আচরণ এবং অবস্থান পরিবর্তন করতে পারেন, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে।

Subspace {
    SpatialPanel(
        SubspaceModifier
            .height(824.dp)
            .width(1400.dp),
        dragPolicy = MovePolicy(),
        resizePolicy = ResizePolicy(),
    ) {
        SpatialPanelContent()
    }
}

@Composable
fun SpatialPanelContent() {
    Box(
        Modifier
            .background(color = Color.Black)
            .height(500.dp)
            .width(500.dp),
        contentAlignment = Alignment.Center
    ) {
        Text(
            text = "Spatial Panel",
            color = Color.White,
            fontSize = 25.sp
        )
    }
}

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

  • যেহেতু SpatialPanel API গুলি সাবস্পেস কম্পোজেবল, তাই আপনাকে অবশ্যই সেগুলিকে Subspace ভিতরে কল করতে হবে। সাবস্পেসের বাইরে কল করলে একটি ব্যতিক্রম দেখা দেয়।
  • SpatialPanel এর আকার SubspaceModifier এর height এবং width স্পেসিফিকেশন ব্যবহার করে সেট করা হয়েছে। এই স্পেসিফিকেশনগুলি বাদ দিলে প্যানেলের আকার এর বিষয়বস্তুর পরিমাপ দ্বারা নির্ধারণ করা যায়।
  • ব্যবহারকারীকে একটি MovePolicy যোগ করে একটি প্যানেল সরানোর অনুমতি দিন।
  • ব্যবহারকারীকে একটি ResizePolicy যোগ করে একটি প্যানেলের আকার পরিবর্তন করার অনুমতি দিন।
  • আকার এবং অবস্থান নির্ধারণের বিশদ বিবরণের জন্য আমাদের স্থানিক প্যানেল নকশা নির্দেশিকা দেখুন। কোড বাস্তবায়নের বিশদ বিবরণের জন্য আমাদের রেফারেন্স ডকুমেন্টেশন দেখুন।

একটি MovePolicy কীভাবে কাজ করে

যখন একজন ব্যবহারকারী একটি প্যানেলকে তাদের থেকে দূরে সরিয়ে দেয়, তখন ডিফল্টরূপে, একটি MovePolicy প্যানেলটিকে হোম স্পেসে সিস্টেম দ্বারা প্যানেলের আকার পরিবর্তনের অনুরূপভাবে স্কেল করে। সমস্ত শিশু সামগ্রী এই আচরণের উত্তরাধিকারী হয়। এটি নিষ্ক্রিয় করতে, shouldScaleWithDistance প্যারামিটারটিকে false এ সেট করুন।

একটি অরবিটার তৈরি করুন

অরবিটার হল একটি স্থানিক UI উপাদান। এটি একটি সংশ্লিষ্ট স্থানিক প্যানেল, লেআউট, বা অন্য সত্তার সাথে সংযুক্ত করার জন্য ডিজাইন করা হয়েছে। একটি অরবিটারে সাধারণত নেভিগেশন এবং প্রাসঙ্গিক ক্রিয়া আইটেম থাকে যা এটি যে সত্তার সাথে সংযুক্ত থাকে তার সাথে সম্পর্কিত। উদাহরণস্বরূপ, যদি আপনি ভিডিও সামগ্রী প্রদর্শনের জন্য একটি স্থানিক প্যানেল তৈরি করে থাকেন, তাহলে আপনি একটি অরবিটারের ভিতরে ভিডিও প্লেব্যাক নিয়ন্ত্রণ যোগ করতে পারেন।

একটি অরবিটারের উদাহরণ

নিচের উদাহরণে যেমন দেখানো হয়েছে, নেভিগেশনের মতো ব্যবহারকারীর নিয়ন্ত্রণগুলি মোড়ানোর জন্য একটি SpatialPanel এর 2D লেআউটের ভিতরে একটি অরবিটার কল করুন। এটি করার ফলে আপনার 2D লেআউট থেকে সেগুলি বের করে আপনার কনফিগারেশন অনুসারে স্থানিক প্যানেলে সংযুক্ত করা হবে।

Subspace {
    SpatialPanel(
        SubspaceModifier
            .height(824.dp)
            .width(1400.dp),
        dragPolicy = MovePolicy(),
        resizePolicy = ResizePolicy(),
    ) {
        SpatialPanelContent()
        OrbiterExample()
    }
}

@Composable
fun OrbiterExample() {
    Orbiter(
        position = ContentEdge.Bottom,
        offset = 96.dp,
        alignment = Alignment.CenterHorizontally
    ) {
        Surface(Modifier.clip(CircleShape)) {
            Row(
                Modifier
                    .background(color = Color.Black)
                    .height(100.dp)
                    .width(600.dp),
                horizontalArrangement = Arrangement.Center,
                verticalAlignment = Alignment.CenterVertically
            ) {
                Text(
                    text = "Orbiter",
                    color = Color.White,
                    fontSize = 50.sp
                )
            }
        }
    }
}

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

  • যেহেতু অরবিটারগুলি স্থানিক UI উপাদান, তাই কোডটি 2D বা 3D লেআউটে পুনঃব্যবহার করা যেতে পারে। একটি 2D লেআউটে, আপনার অ্যাপটি কেবল অরবিটারের ভিতরের বিষয়বস্তু রেন্ডার করে এবং অরবিটারকেই উপেক্ষা করে।
  • অরবিটার কীভাবে ব্যবহার এবং ডিজাইন করবেন সে সম্পর্কে আরও তথ্যের জন্য আমাদের ডিজাইন নির্দেশিকা দেখুন।

একটি স্থানিক বিন্যাসে একাধিক স্থানিক প্যানেল যোগ করুন

আপনি SpatialRow , SpatialColumn , SpatialBox এবং SpatialLayoutSpacer ব্যবহার করে একাধিক স্থানিক প্যানেল তৈরি করতে পারেন এবং একটি স্থানিক বিন্যাসের মধ্যে রাখতে পারেন।

একটি স্থানিক বিন্যাসে একাধিক স্থানিক প্যানেলের উদাহরণ

নিম্নলিখিত কোড উদাহরণটি এটি কীভাবে করবেন তা দেখায়।

Subspace {
    SpatialRow {
        SpatialColumn {
            SpatialPanel(SubspaceModifier.height(250.dp).width(400.dp)) {
                SpatialPanelContent("Top Left")
            }
            SpatialPanel(SubspaceModifier.height(200.dp).width(400.dp)) {
                SpatialPanelContent("Middle Left")
            }
            SpatialPanel(SubspaceModifier.height(250.dp).width(400.dp)) {
                SpatialPanelContent("Bottom Left")
            }
        }
        SpatialColumn {
            SpatialPanel(SubspaceModifier.height(250.dp).width(400.dp)) {
                SpatialPanelContent("Top Right")
            }
            SpatialPanel(SubspaceModifier.height(200.dp).width(400.dp)) {
                SpatialPanelContent("Middle Right")
            }
            SpatialPanel(SubspaceModifier.height(250.dp).width(400.dp)) {
                SpatialPanelContent("Bottom Right")
            }
        }
    }
}

@Composable
fun SpatialPanelContent(text: String) {
    Column(
        Modifier
            .background(color = Color.Black)
            .fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Text(
            text = "Panel",
            color = Color.White,
            fontSize = 15.sp
        )
        Text(
            text = text,
            color = Color.White,
            fontSize = 25.sp,
            fontWeight = FontWeight.Bold
        )
    }
}

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

  • SpatialRow , SpatialColumn , SpatialBox , এবং SpatialLayoutSpacer সবগুলোই সাবস্পেস কম্পোজেবল এবং এগুলোকে অবশ্যই একটি সাবস্পেসের মধ্যে স্থাপন করতে হবে।
  • আপনার লেআউট কাস্টমাইজ করতে SubspaceModifier ব্যবহার করুন।
  • একাধিক প্যানেলের লেআউটের জন্য, আমরা SubspaceModifier ব্যবহার করে 825dp এর বক্ররেখা ব্যাসার্ধ সেট করার পরামর্শ দিচ্ছি যাতে প্যানেলগুলি আপনার ব্যবহারকারীকে ঘিরে থাকে। বিস্তারিত জানার জন্য আমাদের ডিজাইন নির্দেশিকা দেখুন।

ছবি বা ভিডিও কন্টেন্টের জন্য একটি সারফেস যোগ করুন

একটি SpatialExternalSurface হল একটি সাবস্পেস কম্পোজেবল যা এমন একটি Surface তৈরি এবং পরিচালনা করে যেখানে আপনার অ্যাপটি একটি ছবি বা ভিডিওর মতো বিষয়বস্তু আঁকতে পারে। SpatialExternalSurface স্টেরিওস্কোপিক বা মনোস্কোপিক উভয় ধরণের বিষয়বস্তু সমর্থন করে।

এই উদাহরণটি দেখায় যে Media3 Exoplayer এবং SpatialExternalSurface ব্যবহার করে কীভাবে পাশাপাশি স্টেরিওস্কোপিক ভিডিও লোড করতে হয়:

@OptIn(ExperimentalComposeApi::class)
@Composable
fun SpatialExternalSurfaceContent() {
    val context = LocalContext.current
    Subspace {
        SpatialExternalSurface(
            modifier = SubspaceModifier
                .width(1200.dp) // Default width is 400.dp if no width modifier is specified
                .height(676.dp), // Default height is 400.dp if no height modifier is specified
            // Use StereoMode.Mono, StereoMode.SideBySide, or StereoMode.TopBottom, depending
            // upon which type of content you are rendering: monoscopic content, side-by-side stereo
            // content, or top-bottom stereo content
            stereoMode = StereoMode.SideBySide,
        ) {
            val exoPlayer = remember { ExoPlayer.Builder(context).build() }
            val videoUri = Uri.Builder()
                .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
                // Represents a side-by-side stereo video, where each frame contains a pair of
                // video frames arranged side-by-side. The frame on the left represents the left
                // eye view, and the frame on the right represents the right eye view.
                .path("sbs_video.mp4")
                .build()
            val mediaItem = MediaItem.fromUri(videoUri)

            // onSurfaceCreated is invoked only one time, when the Surface is created
            onSurfaceCreated { surface ->
                exoPlayer.setVideoSurface(surface)
                exoPlayer.setMediaItem(mediaItem)
                exoPlayer.prepare()
                exoPlayer.play()
            }
            // onSurfaceDestroyed is invoked when the SpatialExternalSurface composable and its
            // associated Surface are destroyed
            onSurfaceDestroyed { exoPlayer.release() }
        }
    }
}

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

  • আপনি কোন ধরণের কন্টেন্ট রেন্ডার করছেন তার উপর নির্ভর করে StereoMode Mono , SideBySide , অথবা TopBottom এ সেট করুন:
    • Mono : ছবি বা ভিডিও ফ্রেমে একটি একক, অভিন্ন ছবি থাকে যা উভয় চোখে দেখানো হয়।
    • SideBySide : ছবি বা ভিডিও ফ্রেমে পাশাপাশি সাজানো একজোড়া ছবি বা ভিডিও ফ্রেম থাকে, যেখানে বাম দিকের ছবি বা ফ্রেমটি বাম চোখের দৃশ্যকে উপস্থাপন করে এবং ডান দিকের ছবি বা ফ্রেমটি ডান চোখের দৃশ্যকে উপস্থাপন করে।
    • TopBottom : ছবি বা ভিডিও ফ্রেমে উল্লম্বভাবে স্ট্যাক করা একজোড়া ছবি বা ভিডিও ফ্রেম থাকে, যেখানে উপরের ছবি বা ফ্রেমটি বাম চোখের দৃশ্যকে উপস্থাপন করে এবং নীচের ছবি বা ফ্রেমটি ডান চোখের দৃশ্যকে উপস্থাপন করে।
  • SpatialExternalSurface শুধুমাত্র আয়তক্ষেত্রাকার পৃষ্ঠতল সমর্থন করে।
  • এই Surface ইনপুট ইভেন্ট ক্যাপচার করে না।
  • অ্যাপ্লিকেশন রেন্ডারিং বা ভিডিও ডিকোডিংয়ের সাথে StereoMode পরিবর্তনগুলি সিঙ্ক্রোনাইজ করা সম্ভব নয়।
  • এই কম্পোজেবলটি অন্য প্যানেলের সামনে রেন্ডার করতে পারে না, তাই লেআউটে অন্য প্যানেল থাকলে আপনার MovePolicy ব্যবহার করা উচিত নয়।

DRM সুরক্ষিত ভিডিও কন্টেন্টের জন্য একটি সারফেস যোগ করুন

SpatialExternalSurface DRM-সুরক্ষিত ভিডিও স্ট্রিমগুলির প্লেব্যাকও সমর্থন করে। এটি সক্ষম করার জন্য, আপনাকে একটি সুরক্ষিত পৃষ্ঠ তৈরি করতে হবে যা সুরক্ষিত গ্রাফিক্স বাফারগুলিতে রেন্ডার করে। এটি সামগ্রীটিকে স্ক্রিন-রেকর্ড করা বা অ-সুরক্ষিত সিস্টেম উপাদানগুলির দ্বারা অ্যাক্সেস করা থেকে বিরত রাখে।

একটি নিরাপদ পৃষ্ঠ তৈরি করতে, SpatialExternalSurface কম্পোজেবলে surfaceProtection প্যারামিটারটিকে SurfaceProtection.Protected এ সেট করুন। অতিরিক্তভাবে, লাইসেন্স সার্ভার থেকে লাইসেন্স অধিগ্রহণ পরিচালনা করার জন্য আপনাকে Media3 Exoplayer কে উপযুক্ত DRM তথ্য দিয়ে কনফিগার করতে হবে।

নিম্নলিখিত উদাহরণটি দেখায় যে কীভাবে DRM-সুরক্ষিত ভিডিও স্ট্রিম চালানোর জন্য SpatialExternalSurface এবং ExoPlayer কনফিগার করতে হয়:

@OptIn(ExperimentalComposeApi::class)
@Composable
fun DrmSpatialVideoPlayer() {
    val context = LocalContext.current
    Subspace {
        SpatialExternalSurface(
            modifier = SubspaceModifier
                .width(1200.dp)
                .height(676.dp),
            stereoMode = StereoMode.SideBySide,
            surfaceProtection = SurfaceProtection.Protected
        ) {
            val exoPlayer = remember { ExoPlayer.Builder(context).build() }

            // Define the URI for your DRM-protected content and license server.
            val videoUri = "https://your-content-provider.com/video.mpd"
            val drmLicenseUrl = "https://your-license-server.com/license"

            // Build a MediaItem with the necessary DRM configuration.
            val mediaItem = MediaItem.Builder()
                .setUri(videoUri)
                .setDrmConfiguration(
                    MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID)
                        .setLicenseUri(drmLicenseUrl)
                        .build()
                )
                .build()

            onSurfaceCreated { surface ->
                // The created surface is secure and can be used by the player.
                exoPlayer.setVideoSurface(surface)
                exoPlayer.setMediaItem(mediaItem)
                exoPlayer.prepare()
                exoPlayer.play()
            }

            onSurfaceDestroyed { exoPlayer.release() }
        }
    }
}

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

  • সুরক্ষিত পৃষ্ঠ: surfaceProtection = SurfaceProtection.Protected SpatialExternalSurface পৃষ্ঠে সুরক্ষিত থাকা অপরিহার্য যাতে অন্তর্নিহিত Surface DRM সামগ্রীর জন্য উপযুক্ত সুরক্ষিত বাফার দ্বারা সমর্থিত হয়।
  • DRM কনফিগারেশন: আপনাকে অবশ্যই DRM স্কিম (উদাহরণস্বরূপ, C.WIDEVINE_UUID ) এবং আপনার লাইসেন্স সার্ভারের URI দিয়ে MediaItem কনফিগার করতে হবে। ExoPlayer DRM সেশন পরিচালনা করতে এই তথ্য ব্যবহার করে।
  • সুরক্ষিত কন্টেন্ট: যখন কোনও সুরক্ষিত পৃষ্ঠে রেন্ডার করা হয়, তখন ভিডিও কন্টেন্টটি ডিকোড করা হয় এবং একটি সুরক্ষিত পথে প্রদর্শিত হয়, যা কন্টেন্ট লাইসেন্সিং প্রয়োজনীয়তা পূরণ করতে সহায়তা করে। এটি স্ক্রিন ক্যাপচারে কন্টেন্টটি প্রদর্শিত হতেও বাধা দেয়।

অন্যান্য স্থানিক UI উপাদান যোগ করুন

স্থানিক UI উপাদানগুলি আপনার অ্যাপ্লিকেশনের UI অনুক্রমের যেকোনো জায়গায় স্থাপন করা যেতে পারে। এই উপাদানগুলি আপনার 2D UI-তে পুনঃব্যবহার করা যেতে পারে এবং স্থানিক ক্ষমতা সক্ষম করা হলেই কেবল তাদের স্থানিক বৈশিষ্ট্যগুলি দৃশ্যমান হবে। এটি আপনাকে মেনু, ডায়ালগ এবং অন্যান্য উপাদানগুলিতে উচ্চতা যোগ করতে দেয়, আপনার কোড দুবার লেখার প্রয়োজন ছাড়াই। এই উপাদানগুলি কীভাবে ব্যবহার করবেন তা আরও ভালভাবে বুঝতে স্থানিক UI-এর নিম্নলিখিত উদাহরণগুলি দেখুন।

UI কম্পোনেন্ট

যখন স্থানিকীকরণ সক্ষম করা হয়

2D পরিবেশে

SpatialDialog

একটি উন্নত ডায়ালগ প্রদর্শনের জন্য প্যানেলটি z-depth-এ সামান্য পিছনে ঠেলে দেবে।

আবার 2D Dialog ফিরে যাওয়া।

SpatialPopup

একটি উন্নত পপআপ প্রদর্শনের জন্য প্যানেলটি z-depth-এ সামান্য পিছনে ঠেলে দেবে।

আবার 2D Popup ফিরে যায়।

SpatialElevation

উচ্চতা যোগ করার জন্য SpatialElevationLevel সেট করা যেতে পারে।

স্থানিক উচ্চতা ছাড়াই দেখায়।

স্থানিক সংলাপ

এটি একটি ডায়ালগের উদাহরণ যা অল্প বিলম্বের পরে খোলে। যখন SpatialDialog ব্যবহার করা হয়, তখন ডায়ালগটি স্থানিক প্যানেলের মতো একই z-গভীরে প্রদর্শিত হয় এবং স্থানিকীকরণ সক্ষম করা হলে প্যানেলটি 125dp পিছনে ঠেলে দেওয়া হয়। স্থানিকীকরণ সক্ষম না থাকলেও SpatialDialog ব্যবহার করা যেতে পারে, এই ক্ষেত্রে SpatialDialog তার 2D প্রতিরূপ, Dialog এ ফিরে যায়।

@Composable
fun DelayedDialog() {
    var showDialog by remember { mutableStateOf(false) }
    LaunchedEffect(Unit) {
        delay(3000)
        showDialog = true
    }
    if (showDialog) {
        SpatialDialog(
            onDismissRequest = { showDialog = false },
            SpatialDialogProperties(
                dismissOnBackPress = true
            )
        ) {
            Box(
                Modifier
                    .height(150.dp)
                    .width(150.dp)
            ) {
                Button(onClick = { showDialog = false }) {
                    Text("OK")
                }
            }
        }
    }
}

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

কাস্টম প্যানেল এবং লেআউট তৈরি করুন

XR-এর জন্য Compose সমর্থিত নয় এমন কাস্টম প্যানেল তৈরি করতে, আপনি SceneCore API ব্যবহার করে PanelEntity ইনস্ট্যান্স এবং দৃশ্য গ্রাফের সাথে সরাসরি কাজ করতে পারেন।

স্থানিক বিন্যাস এবং অন্যান্য সত্তার সাথে কক্ষপথকে সংযুক্ত করুন

আপনি Compose-এ ঘোষিত যেকোনো সত্তার সাথে একটি অরবিটার অ্যাঙ্কর করতে পারেন। এর মধ্যে রয়েছে SpatialRow , SpatialColumn , অথবা SpatialBox এর মতো UI উপাদানের একটি স্থানিক বিন্যাসে একটি অরবিটার ঘোষণা করা। অরবিটারটি আপনার ঘোষিত স্থানের নিকটতম প্যারেন্ট সত্তার সাথে অ্যাঙ্কর করে।

অরবিটারের আচরণ নির্ধারিত হয় আপনি কোথায় এটি ঘোষণা করেন তার উপর নির্ভর করে:

  • একটি SpatialPanel এ মোড়ানো একটি 2D লেআউটে (যেমনটি পূর্ববর্তী কোড স্নিপেটে দেখানো হয়েছে), অরবিটারটি সেই SpatialPanel এ অ্যাঙ্কর করে।
  • একটি Subspace , অরবিটারটি নিকটতম প্যারেন্ট সত্তার সাথে নোঙ্গর করে, যা হল অরবিটার ঘোষিত স্থানিক বিন্যাস।

নিম্নলিখিত উদাহরণটি দেখায় কিভাবে একটি অরবিটারকে একটি স্থানিক সারিতে নোঙ্গর করতে হয়:

Subspace {
    SpatialRow {
        Orbiter(
            position = ContentEdge.Top,
            offset = 8.dp,
            offsetType = OrbiterOffsetType.InnerEdge,
            shape = SpatialRoundedCornerShape(size = CornerSize(50))
        ) {
            Text(
                "Hello World!",
                style = MaterialTheme.typography.titleMedium,
                modifier = Modifier
                    .background(Color.White)
                    .padding(16.dp)
            )
        }
        SpatialPanel(
            SubspaceModifier
                .height(824.dp)
                .width(1400.dp)
        ) {
            Box(
                modifier = Modifier
                    .background(Color.Red)
            )
        }
        SpatialPanel(
            SubspaceModifier
                .height(824.dp)
                .width(1400.dp)
        ) {
            Box(
                modifier = Modifier
                    .background(Color.Blue)
            )
        }
    }
}

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

  • যখন আপনি একটি 2D লেআউটের বাইরে একটি অরবিটার ঘোষণা করেন, তখন অরবিটারটি তার নিকটতম প্যারেন্ট সত্তার সাথে নোঙ্গর করে। এই ক্ষেত্রে, অরবিটারটি SpatialRow এর শীর্ষে নোঙ্গর করে যেখানে এটি ঘোষিত হয়।
  • স্পেশিয়াল লেআউট যেমন SpatialRow , SpatialColumn , SpatialBox সকলের সাথেই কন্টেন্টলেস এন্টিটি যুক্ত থাকে। অতএব, একটি স্পেশিয়াল লেআউটে ঘোষিত একটি অরবিটার সেই লেআউটের সাথে নোঙ্গর করে।

আরো দেখুন