প্রোডাক্ট সংক্রান্ত খবর

Jetpack Compose এপ্রিল '২৬ রিলিজে নতুন কী আছে

৬ মিনিট লাগবে
Meghan Mehta-এর প্রোফাইল দেখুন
Meghan Mehta ডেভেলপার অ্যাডভোকেট, Android

আজ, Jetpack Compose এপ্রিল ‘২৬ রিলিজ স্টেবল। এই রিলিজে মূল Compose মডিউলের ১.১১ ভার্সন (সম্পূর্ণ BOM ম্যাপিং দেখুন), শেয়ার করা এলিমেন্ট ডিবাগ টুল, ট্র্যাকপ্যাড ইভেন্ট এবং আরও অনেক কিছু রয়েছে। এছাড়াও, আমাদের কাছে কিছু পরীক্ষামূলক API আছে যেগুলি আপনি ব্যবহার করে দেখলে এবং সেই সম্পর্কে মতামত দিলে আমরা খুশি হব।

আজকের রিলিজ ব্যবহার করতে, আপনার Compose BOM ভার্সন এতে আপগ্রেড করুন:

implementation(platform("androidx.compose:compose-bom:2026.04.01"))

Compose 1.11.0-এ করা পরিবর্তন

পরীক্ষায় Coroutine এক্সিকিউশন

Compose কীভাবে টেস্ট টাইমিং ম্যানেজ করে সেই বিষয়ে আমরা একটি বড় আপডেট নিয়ে আসছি। Compose 1.10-এ ঘোষণা করা অপ্ট-ইন করার সময়সীমা শেষ হওয়ার পরে, v2 টেস্টিং API এখন ডিফল্ট হিসেবে সেট করা হয়েছে এবং v1 API-এর ব্যবহার বন্ধ করা হয়েছে। মূল পরিবর্তন হল ডিফল্ট টেস্ট ডিসপ্যাচারে পরিবর্তন। v1 API UnconfinedTestDispatcher-এর উপর নির্ভর করে, যা অবিলম্বে coroutines এক্সিকিউট করে, v2 API StandardTestDispatcher ব্যবহার করে। এর অর্থ হল, আপনার টেস্টে কোনও কোরুটিন লঞ্চ করা হলে, সেটি এখন সারিতে থাকে এবং ভার্চুয়াল ঘড়ি এগিয়ে না যাওয়া পর্যন্ত এক্সিকিউট হয় না।

এটি প্রোডাকশন কন্ডিশন আরও ভালোভাবে নকল করে, রেস কন্ডিশন কার্যকরভাবে ফ্ল্যাশ আউট করে এবং আপনার টেস্ট স্যুটকে উল্লেখযোগ্যভাবে আরও শক্তিশালী এবং কম ফ্লেকি করে তোলে।

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

শেয়ার করা এলিমেন্ট সংক্রান্ত উন্নতি ও অ্যানিমেশন টুলিং

এছাড়াও, আমরা শেয়ার করা এলিমেন্ট ও Modifier.animatedBounds-এর জন্য কিছু হ্যান্ডি ভিজ্যুয়াল ডিবাগিং টুল যোগ করেছি। আপনি এখন ঠিক কী ঘটছে তা দেখতে পারবেন—যেমন টার্গেট বাউন্ড, অ্যানিমেশন ট্র্যাজেক্টরি এবং কতগুলি ম্যাচ পাওয়া গেছে—যার ফলে ট্রানজিশন কেন প্রত্যাশিতভাবে কাজ করছে না তা চিহ্নিত করা অনেক সহজ হয়ে যায়। নতুন টুলিং ব্যবহার করতে, আপনার SharedTransitionLayout-এর চারপাশে LookaheadAnimationVisualDebugging কম্পোজেবল ব্যবহার করুন। 

LookaheadAnimationVisualDebugging(
    overlayColor = Color(0x4AE91E63),
    isEnabled = true,
    multipleMatchesColor = Color.Green,
    isShowKeylabelEnabled = false,
    unmatchedElementColor = Color.Red,
) {
    SharedTransitionLayout {
        CompositionLocalProvider(
            LocalSharedTransitionScope provides this,
        ) {
            // your content
        }
    }
}

ট্র্যাকপ্যাড ইভেন্ট

আমরা বিল্ট-ইন ল্যাপটপ ট্র্যাকপ্যাড, ট্যাবলেটের জন্য অ্যাটাচ করা যায় এমন ট্র্যাকপ্যাড বা এক্সটার্নাল/ভার্চুয়াল ট্র্যাকপ্যাডের মতো ট্র্যাকপ্যাডের জন্য Compose সহায়তা নতুন করে সাজিয়েছি। বেসিক ট্র্যাকপ্যাড ইভেন্ট এখন সাধারণত PointerType.Mouse ইভেন্ট হিসেবে বিবেচনা করা হবে, যা ব্যবহারকারীর প্রত্যাশার সাথে আরও ভালভাবে ম্যাচ করার জন্য মাউস এবং ট্র্যাকপ্যাডের আচরণকে সারিবদ্ধ করে। আগে, এইসব ট্র্যাকপ্যাড ইভেন্টকে PointerType.Touch-এর ফেক টাচস্ক্রিন ফিঙ্গার হিসেবে ব্যাখ্যা করা হত, যার ফলে ব্যবহারকারীর অভিজ্ঞতা বিভ্রান্তিকর হয়ে উঠত। যেমন, ট্র্যাকপ্যাড ব্যবহার করে ক্লিক ও টেনে আনার মাধ্যমে বেছে নেওয়ার পরিবর্তে স্ক্রল করা যাবে। Compose-এর লেটেস্ট রিলিজে এই ইভেন্টগুলির পয়েন্টারের ধরন পরিবর্তন করার মাধ্যমে, ট্র্যাকপ্যাড ব্যবহার করে ক্লিক ও টেনে আনার মাধ্যমে আর স্ক্রল করা যাবে না।

এছাড়াও, API 34 থেকে প্ল্যাটফর্মের মাধ্যমে শনাক্ত করা আরও জটিল ট্র্যাকপ্যাড জেসচারের জন্য আমরা সহায়তা যোগ করেছি, যার মধ্যে দুটি আঙুল দিয়ে সোয়াইপ করা এবং পিঞ্চ করা অন্তর্ভুক্ত। ট্র্যাকপ্যাডের সাথে আরও ভালো আচরণ করার জন্য Modifier.scrollable এবং Modifier.transformable-এর মতো কম্পোনেন্টগুলি এই জেসচারগুলি অটোমেটিক শনাক্ত করে।

এইসব পরিবর্তন বিল্ট-ইন কম্পোনেন্ট জুড়ে ট্র্যাকপ্যাডের আচরণ উন্নত করে, যার মধ্যে রয়েছে অপ্রয়োজনীয় টাচ স্লোপ সরিয়ে দেওয়া, আরও স্বজ্ঞাত ড্র্যাগ-অ্যান্ড-ড্রপ শুরুর জেসচার, টেক্সট ফিল্ডে ডবল-ক্লিক ও ট্রিপল-ক্লিক করে বেছে নেওয়া এবং টেক্সট ফিল্ডে ডেস্কটপ-স্টাইল কনটেক্সট মেনু।

ট্র্যাকপ্যাডের আচরণ পরীক্ষা করার জন্য, performTrackpadInput, সহ নতুন টেস্টিং API আছে যা ট্র্যাকপ্যাডের সাথে ব্যবহার করার সময় আপনার অ্যাপের আচরণ যাচাই করার অনুমতি দেয়। আপনার কাছে কাস্টম জেসচার ডিটেক্টর থাকলে, টাচস্ক্রিন, মাউস, ট্র্যাকপ্যাড ও স্টাইলাস সহ ইনপুট ধরন জুড়ে আচরণ যাচাই করুন এবং মাউস স্ক্রল করার হুইল ও ট্র্যাকপ্যাড জেসচারের জন্য সহায়তা নিশ্চিত করুন।

beforeAndAfter.webp

কম্পোজিশন হোস্ট ডিফল্ট (কম্পোজ রানটাইম)

আমরা HostDefaultProvider, LocalHostDefaultProvider, HostDefaultKey এবং ViewTreeHostDefaultKey নিয়ে এসেছি যাতে compose-runtime-এর মাধ্যমে সরাসরি হোস্ট-লেভেল পরিষেবা প্রদান করা যায়। এর ফলে, লুকআপের জন্য লাইব্রেরিকে compose-ui-এর উপর নির্ভর করতে হয় না, যা Kotlin Multiplatform-কে আরও ভালভাবে সাপোর্ট করে। কম্পোজিশন ট্রিতে এইসব ভ্যালু লিঙ্ক করতে, লাইব্রেরি লেখক compositionLocalWithHostDefaultOf ব্যবহার করে CompositionLocal তৈরি করতে পারেন যা হোস্ট থেকে ডিফল্ট সমাধান করে।

প্রিভিউ র‍্যাপার

Android Studio কাস্টম প্রিভিউ হল একটি নতুন ফিচার যা আপনাকে কম্পোজ প্রিভিউয়ের কন্টেন্ট ঠিক কীভাবে দেখানো হবে তা নির্ধারণ করতে দেয়।

PreviewWrapperProvider ইন্টারফেস প্রয়োগ করে এবং নতুন @PreviewWrapper অ্যানোটেশন প্রয়োগ করে, আপনি সহজেই কাস্টম লজিক ইনজেক্ট করতে পারবেন, যেমন নির্দিষ্ট Theme প্রয়োগ করা। অ্যানোটেশনটি @Composable এবং @Preview বা @MultiPreview-এর সাথে অ্যানোটেট করা ফাংশনে প্রয়োগ করা যেতে পারে, যা একটি জেনেরিক, সহজে ব্যবহারযোগ্য সমাধান অফার করে যা প্রিভিউ ফিচার জুড়ে কাজ করে এবং পুনরাবৃত্তিমূলক কোড উল্লেখযোগ্যভাবে কমিয়ে দেয়।

class ThemeWrapper: PreviewWrapperProvider {
    @Composable
    override fun Wrap(content: @Composable (() -> Unit)) {
        JetsnackTheme {
            content()
        }
    }
}


@PreviewWrapper(ThemeWrapper::class)
@Preview
@Composable
private fun ButtonPreview() {
    // JetsnackTheme in effect
    Button(onClick = {}) {
        Text(text = "Demo")
    }
}

বাতিল ও সরিয়ে দেওয়া

  • Compose 1.10 ব্লগ পোস্টে ঘোষণা করা হয়েছে যে, আমরা Modifier.onFirstVisible() বন্ধ করে দিচ্ছি। এর নাম প্রায়ই ভুল ধারণার জন্ম দেয়, বিশেষ করে লেজি লেআউটের ক্ষেত্রে, যেখানে স্ক্রল করার সময় এটি একাধিকবার ট্রিগার হয়। আমরা Modifier.onVisibilityChanged()-এ মাইগ্রেট করার সাজেশন দিই, যা আপনার নির্দিষ্ট ব্যবহারের ক্ষেত্রে প্রয়োজনীয়তা অনুসারে দৃশ্যমানতার স্ট্যাটাস আরও নির্ভুলভাবে ম্যানুয়ালি ট্র্যাক করার সুবিধা দেয়।
  • ComposeFoundationFlags.isTextFieldDpadNavigationEnabled ফ্ল্যাগটি সরিয়ে দেওয়া হয়েছে কারণ TextFields-এর জন্য ডি-প্যাড নেভিগেশন এখন ডিফল্ট হিসেবে সবসময় চালু থাকে। নতুন আচরণ নিশ্চিত করে যে গেমপ্যাড বা টিভি রিমোট থেকে ডি-প্যাড ইভেন্টগুলি প্রথমে কার্সারটিকে প্রদত্ত দিকে নিয়ে যায়। কার্সর টেক্সটের শেষে পৌঁছালে তবেই ফোকাস অন্য এলিমেন্টে সরানো যাবে।

আসন্ন API

আসন্ন Compose 1.12.0 রিলিজে, compileSdk-কে compileSdk 37-এ আপগ্রেড করা হবে, সাথে AGP 9 এবং Compose-এর উপর নির্ভর করে এমন সব অ্যাপ ও লাইব্রেরি এই প্রয়োজনীয়তা ইনহেরিট করবে। আমরা সাজেস্ট করি যে আপনি লেটেস্ট রিলিজ করা ভার্সনের সাথে আপ-টু-ডেট থাকুন, কারণ Compose-এর লক্ষ্য হল লেটেস্ট Android ফিচারে অ্যাক্সেস প্রদান করার জন্য নতুন compileSdks দ্রুত গ্রহণ করা। বিভিন্ন API লেভেলের জন্য AGP-এর কোন ভার্সন কাজ করে সেই সম্পর্কে আরও তথ্য পেতে এখানে ডকুমেন্টেশন চেক করতে ভুলবেন না। 

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

স্টাইল (এক্সপেরিমেন্টাল)

আমরা স্টাইলিং-এর জন্য একটি নতুন পরীক্ষামূলক ফাউন্ডেশন API চালু করছি। স্টাইল API হল কম্পোনেন্টের ভিজ্যুয়াল এলিমেন্ট কাস্টমাইজ করার জন্য একটি নতুন দৃষ্টান্ত, যা ঐতিহ্যগতভাবে মডিফায়ার দিয়ে করা হয়েছে। এটি সহজ স্টেট-ভিত্তিক স্টাইলিং এবং অ্যানিমেটেড ট্রানজিশন সহ স্টাইল করা যায় এমন প্রপার্টির স্ট্যান্ডার্ড সেট প্রকাশ করে আরও গভীর, সহজ কাস্টমাইজেশন আনলক করার জন্য ডিজাইন করা হয়েছে। এই নতুন API-এর মাধ্যমে, আমরা ইতিমধ্যেই আশাব্যঞ্জক পারফর্ম্যান্স সংক্রান্ত সুবিধা দেখতে পাচ্ছি। Style API স্থিতিশীল হয়ে গেলে আমরা মেটেরিয়াল কম্পোনেন্টে স্টাইল গ্রহণ করার পরিকল্পনা করছি।

প্রেস করা স্টেট স্টাইল ব্যাকগ্রাউন্ড ওভাররাইড করার একটি প্রাথমিক উদাহরণ:

@Composable
fun LoginButton(modifier: Modifier = Modifier) {
    Button(
        onClick = {
            // Login logic
        },
        modifier = modifier,
        style = {
            background(
                Brush.linearGradient(
                    listOf(lightPurple, lightBlue)
                )
            )
            width(75.dp)
            height(50.dp)
            textAlign(TextAlign.Center)
            externalPadding(16.dp)

            pressed {
                background(
                    Brush.linearGradient(
                        listOf(Color.Magenta, Color.Red)
                    )
                )
            }
        }
    ){
        Text(
            text = "Login",
        )
    }
}
styles.webp

ডকুমেন্টেশন চেক করুন এবং এখানে কোনও সমস্যা থাকলে তা জানান।

MediaQuery (এক্সপেরিমেন্টাল)

নতুন mediaQuery API, আপনার UI-কে তার পরিবেশের সাথে মানিয়ে নেওয়ার জন্য একটি ঘোষণামূলক এবং পারফর্ম্যান্ট উপায় প্রদান করে। এটি জটিল তথ্য সংগ্রহকে UiMediaScope-এর মধ্যে সহজ শর্তে বিমূর্ত করে, যাতে শুধুমাত্র প্রয়োজন হলেই রিকম্পোজিশন হয়।

কীবোর্ডের ধরন ও পয়েন্টার প্রিসিশনের মতো ডিভাইস সংক্রান্ত ক্ষমতা থেকে শুরু করে উইন্ডোর সাইজ ও পোস্টারের মতো প্রাসঙ্গিক অবস্থা পর্যন্ত বিভিন্ন ধরনের এনভায়রনমেন্টাল সিগন্যালের জন্য সহায়তা প্রদান করার মাধ্যমে আপনি গভীরভাবে রেসপন্সিভ অভিজ্ঞতা তৈরি করতে পারবেন। derivedMediaQuery-এর সাথে পারফর্ম্যান্স যুক্ত করা হয়েছে যাতে হাই-ফ্রিকোয়েন্সি আপডেট ম্যানেজ করা যায়, অন্যদিকে স্কোপ ওভাররাইড করার ক্ষমতা হার্ডওয়্যার কনফিগারেশন জুড়ে টেস্টিং ও প্রিভিউকে নির্বিঘ্ন করে তোলে। আগে, ডিভাইসের নির্দিষ্ট কিছু প্রপার্টি অ্যাক্সেস করতে — যেমন, কোনও ডিভাইস টেবিলটপ মোডে থাকলে — আপনাকে অনেক বয়লারপ্লেট লিখতে হত: 

@Composable
fun isTabletopPosture(
    context: Context = LocalContext.current
): Boolean {
    val windowLayoutInfo by
        WindowInfoTracker
            .getOrCreate(context)
            .windowLayoutInfo(context)
            .collectAsStateWithLifecycle(null)

    return windowLayoutInfo.displayFeatures.any { displayFeature ->
        displayFeature is FoldingFeature &&
            displayFeature.state == FoldingFeature.State.HALF_OPENED &&
            displayFeature.orientation == FoldingFeature.Orientation.HORIZONTAL
    }
}

@Composable
fun VideoPlayer() {
    if(isTabletopPosture()) {
        TabletopLayout()
    } else {
        FlatLayout()
    }
}

এখন, UIMediaQuery-এর সাহায্যে, আপনি ডিভাইসের প্রপার্টি কোয়েরি করতে mediaQuery সিনট্যাক্স যোগ করতে পারেন, যেমন কোনও ডিভাইস টেবিলটপ মোডে আছে কিনা:

@OptIn(ExperimentalMediaQueryApi::class)
@Composable
fun VideoPlayer() {
    if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) {
        TabletopLayout()
    } else {
        FlatLayout()
    }
}

ডকুমেন্টেশন চেক করুন এবং এখানে কোনও সমস্যা থাকলে তা জানান।

গ্রিড (এক্সপেরিমেন্টাল)

Grid হল Jetpack Compose-এ জটিল, দ্বি-মাত্রিক লেআউট তৈরি করার জন্য একটি শক্তিশালী নতুন API। Row এবং Column লিনিয়ার ডিজাইনের জন্য দারুণ হলেও, Grid আপনাকে স্ক্রিন-লেভেল আর্কিটেকচার এবং জটিল কম্পোনেন্টের জন্য প্রয়োজনীয় স্ট্রাকচারাল কন্ট্রোল প্রদান করে, যার জন্য স্ক্রল করা যায় এমন তালিকার ওভারহেড প্রয়োজন হয় না। Grid আপনাকে ট্র্যাক, গ্যাপ ও সেল ব্যবহার করে লেআউট নির্ধারণ করার সুবিধা দেয় এবং Dp, শতাংশ, অন্তর্নিহিত কন্টেন্ট সাইজ ও ফ্লেক্সিবল "Fr" ইউনিটের মতো পরিচিত সাইজ সংক্রান্ত বিকল্প অফার করে। 

@OptIn(ExperimentalGridApi::class)
@Composable
fun GridExample() {
    Grid(
        config = {
            repeat(4) { column(0.25f) }
            repeat(2) { row(0.5f) }
            gap(16.dp)
        }
    ) {
        Card1(modifier = Modifier.gridItem(rowSpan = 2)
        Card2(modifier = Modifier.gridItem(colmnSpan = 3)
        Card3(modifier = Modifier.gridItem(columnSpan = 2)
        Card4()
    }
}

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

Grid.gif

ডকুমেন্টেশন চেক করুন এবং এখানে কোনও সমস্যা থাকলে তা জানান। 

FlexBox (Experimental)

FlexBox হল একটি লেআউট কন্টেনার যা হাই পারফর্ম্যান্স, অ্যাডাপ্টিভ UI-এর জন্য ডিজাইন করা হয়েছে। এটি উপলভ্য কন্টেনার ডাইমেনশনের উপর ভিত্তি করে আইটেমের সাইজ ও স্পেস ডিস্ট্রিবিউশন ম্যানেজ করে।  এটি র‍্যাপিং (wrap) এবং আইটেমের মাল্টি-অ্যাক্সিস অ্যালাইনমেন্টের (justifyContent, alignItems, alignContent) মতো জটিল টাস্ক ম্যানেজ করে। এটি কন্টেনার পূরণ করার জন্য আইটেমকে বড় (grow) বা ছোট (shrink) করার অনুমতি দেয়। 

@OptIn(ExperimentalFlexBoxApi::class)
fun FlexBoxWrapping(){
    FlexBox(
        config = {
            wrap(FlexWrap.Wrap)
            gap(8.dp)
        }
    ) {
        RedRoundedBox()
        BlueRoundedBox()
        GreenRoundedBox(modifier = Modifier.width(350.dp).flex { grow(1.0f) })
        OrangeRoundedBox(modifier = Modifier.width(200.dp).flex { grow(0.7f) })
        PinkRoundedBox(modifier = Modifier.width(200.dp).flex { grow(0.3f) })
    }
}
AnimationGif.gif

ডকুমেন্টেশন চেক করুন এবং এখানে কোনও সমস্যা থাকলে তা জানান।

নতুন SlotTable প্রয়োগ (এক্সপেরিমেন্টাল)

আমরা SlotTable-এর নতুন প্রয়োগ চালু করেছি, যা এই রিলিজে ডিফল্ট হিসেবে বন্ধ করা আছে। SlotTable হল ইন্টার্নাল ডেটা স্ট্রাকচার যা Compose রানটাইম আপনার কম্পোজিশন হায়ারার্কির স্টেট ট্র্যাক করতে, ইনভ্যালিডেশন/রিকম্পোজিশন ট্র্যাক করতে, মনে রাখা ভ্যালু স্টোর করতে এবং রানটাইমে কম্পোজিশনের সব মেটাডেটা ট্র্যাক করতে ব্যবহার করে। এই নতুন প্রয়োগটি পারফর্ম্যান্স উন্নত করার জন্য ডিজাইন করা হয়েছে, প্রাথমিকভাবে র‍্যান্ডম এডিটের ক্ষেত্রে।

নতুন SlotTable ব্যবহার করে দেখতে, ComposeRuntimeFlags.isLinkBufferComposerEnabled চালু করুন। 

আজই কোডিং শুরু করুন!

Jetpack Compose-এ অনেক নতুন API আছে এবং আরও অনেক API আসছে, তাই Jetpack Compose-এ মাইগ্রেট করার এর চেয়ে ভালো সময় আর হয় না।  বরাবরের মতো, আমরা আপনার মতামত এবং ফিচার অনুরোধকে (বিশেষ করে @Experimental ফিচার যা এখনও তৈরি হচ্ছে) গুরুত্ব দিই — সেগুলি এখানে ফাইল করুন। কম্পোজ করার আনন্দ নিন!

লিখেছেন:
পড়া চালিয়ে যান