পণ্যের খবর

Jetpack Compose-এর আগস্ট '২৬ সংস্করণে নতুন কী আছে

৫ মিনিটের পাঠ
নিক বুচারের প্রোফাইল দেখুন
Nick Butcher প্রোডাক্ট ম্যানেজার

আজ, Jetpack Compose-এর আগস্ট '২৬ রিলিজটি স্থিতিশীল হয়েছে! এই রিলিজে কোর কম্পোজ মডিউলগুলোতে ভার্সন ১.১২ আনা হয়েছে (সম্পূর্ণ BOM ম্যাপিং দেখুন), এবং এর সাথে যুক্ত হয়েছে মেশ গ্রেডিয়েন্ট ও ওয়াইড কালার গ্যামুট (WCG) সাপোর্টের মতো সমৃদ্ধ ভিজ্যুয়াল এপিআই, Grid নেমড এরিয়ার মতো স্ট্রাকচারাল লেআউট ফিচার, অ্যান্ড্রয়েডের ক্রেডেনশিয়াল ম্যানেজারের সাথে নির্বিঘ্ন ইন্টিগ্রেশন, এবং টেস্টিং ও পারফরম্যান্সে উল্লেখযোগ্য উন্নতি।

আপনার প্রজেক্টকে আজকের রিলিজে আপডেট করতে, আপনার Compose BOM ভার্সনটি 2026.08.00 -এ আপগ্রেড করুন:

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

ব্রেকিং পরিবর্তন

  • এজিপি ও কম্পাইল এসডিকে : কম্পোজ ১.১২ সংস্করণে কম্পাইলএসডিকে এপিআই ৩৭-এ আপডেট করা হয়েছে, যার জন্য ন্যূনতম এজিপি ৯.১.২ প্রয়োজন। মনে রাখবেন, কম্পোজ সর্বদা সর্বশেষ কম্পাইলএসডিকে টার্গেট করবে। এই পরিবর্তন সম্পর্কে আরও জানতে এখানে ক্লিক করুন।
  • Modifier.onFirstVisible() এখন আর ব্যবহার করা হয় না : এর পরিবর্তে Modifier.onVisibilityChanged() ব্যবহার করুন, যা ভিজিবিলিটি থ্রেশহোল্ড আরও নির্ভুলভাবে ট্র্যাক করে।

গ্রাফিক্স

মেশ গ্রেডিয়েন্ট

Compose 1.12-এ MeshGradientPainter যুক্ত করা হয়েছে, যা আপনাকে বহু-বিন্দুবিশিষ্ট ও জৈব রঙের গ্রেডিয়েন্ট তৈরি করতে সাহায্য করবে।

meshGradient.gif
val rows = 1
val columns = 1

val gradientPainter = remember {
    MeshGradientPainter(rows, columns) {
        // Parameters: row, column, position, color
        setVertex(0, 0, Offset(0f, 0f), Color.Red)     // Top-Left
        setVertex(0, 1, Offset(1f, 0f), Color.Blue)    // Top-Right
        setVertex(1, 0, Offset(0f, 1f), Color.Green)   // Bottom-Left
        setVertex(1, 1, Offset(1f, 1f), Color.Yellow)  // Bottom-Right
    }
}

Box(
    modifier = modifier
        .aspectRatio(16/9f)
        .fillMaxWidth()
        .paint(gradientPainter)
)

আরও তথ্য ও উদাহরণের জন্য ডকুমেন্টেশন দেখুন।

প্রশস্ত রঙের গামুট এবং HDR সমর্থন

আধুনিক ডিসপ্লেগুলো বর্ধিত কালার ফিডেলিটি এবং উচ্চতর ডাইনামিক রেঞ্জ প্রদান করে। Compose 1.12-এ, Compose গ্রাফিক্স, পেইন্ট এবং শেডার জুড়ে ওয়াইড কালার গ্যামুট (P3) এবং HDR রেন্ডারিংয়ের জন্য সম্পূর্ণ পাইপলাইন সাপোর্ট সক্রিয় করা হয়েছে। নন-sRGB কালার স্পেসে (যেমন ডিসপ্লে P3) সংজ্ঞায়িত রঙগুলো কালার ক্ল্যাম্পিং ছাড়াই প্ল্যাটফর্ম রেন্ডারিং পর্যন্ত সংরক্ষিত থাকে। যদি রঙগুলো কোনো অসমর্থিত কালার স্পেস (যেমন CieXyz, CieLab, বা Oklab) ব্যবহার করে, কোনো অসমর্থিত অ্যান্ড্রয়েড সংস্করণের (যেমন অ্যান্ড্রয়েড ১৩ এবং তার নিচের সংস্করণে Bt2020Hlg) কালার স্পেসের উপর নির্ভর করে, অথবা অ্যাপটি অ্যান্ড্রয়েড ৯ (API 28) এবং তার নিচের সংস্করণে চলে, তবে রঙগুলো নিরাপদে sRGB-তে ফিরে আসবে।

অন্যান্য উল্লেখযোগ্য পরিবর্তন:

  • GraphicsLayerModifier.graphicsLayerLayerOutsets যোগ করা হয়েছে, যা ব্যবহার করে আপনি লেয়ারের পরিমাপকৃত আকারের বাইরে এর দৃশ্যমান সীমানা বাড়াতে পারেন। যখন লেয়ারটিকে একটি অফস্ক্রিন বাফারে উন্নীত করা হয়, তখন এর অন্তর্নিহিত clipToBounds আচরণ এড়াতে LayerOutsets প্রয়োগ করুন।

শৈলী

Google I/O-তে, আমরা Compose Styles API-এর জন্য আমাদের প্রাথমিক রূপকল্প তুলে ধরেছিলাম—যা কম্পোনেন্ট স্টাইল করার একটি সমন্বিত ও উচ্চ কার্যক্ষমতাসম্পন্ন উপায়। তখন থেকে, আমরা এর অন্তর্নিহিত আর্কিটেকচারটি তৈরি করে চলেছি, যা কঠোর টাইপ সেফটি ও অনুমানযোগ্য সঠিকতা নিশ্চিত করে এবং কাস্টম ডিজাইন সিস্টেম তৈরিতে সহায়তা করে।

এই ভিত্তিস্তরটি সঠিকভাবে তৈরি করা নিশ্চিত করতে, এপিআইটি পরীক্ষামূলক পর্যায়ে থাকবে এবং এতে বড় ধরনের পরিবর্তন আসতে পারে।

রানটাইম অপ্টিমাইজেশন

কীড সাইডইফেক্ট ওভারলোড

SideEffect এখন কী আর্গুমেন্ট সমর্থন করে, যা আপনাকে নির্দিষ্ট কী পরিবর্তন হলেই এককালীন সাইড এফেক্ট চালু করার সুযোগ দেয়। যখন আপনার কো-রুটিন বা ডিসপোজ ব্লকের প্রয়োজন হয় না, তখন LaunchedEffect বা DisposableEffect ব্যবহারের তুলনায় এটি আরও ভালো পারফরম্যান্স দিতে পারে। SideEffect LaunchedEffect চেয়ে ৯০% পর্যন্ত এবং DisposableEffect চেয়ে প্রায় ২০% দ্রুততর। মনে রাখবেন যে, SideEffect তার এফেক্টটি DisposableEffect এবং LaunchedEffect আগে চালায়, তাই বিদ্যমান এফেক্টগুলোকে এই API-তে স্থানান্তর করার সময় সতর্কতা অবলম্বন করুন, বিশেষ করে LaunchedEffects ক্ষেত্রে যেগুলো বর্তমান ফ্রেম শেষ হওয়ার পর ডিসপ্যাচ হওয়ার উপর নির্ভর করে।

@Composable
fun AnalyticsTracker(userId: String, screenName: String) {
    SideEffect(key1 = userId, key2 = screenName) {
        analytics.logScreenView(userId, screenName)
    }
}

অ্যানিমেশন

  • DeferredTargetAnimation পরীক্ষামূলক পর্যায় থেকে উত্তীর্ণ হয়েছে।

ইন্টারেক্টিভ দ্বি-পর্যায়ের রূপান্তর

  • নতুন কম্পোজেবল ফাংশন DeferredAnimatedContent এবং DeferredAnimatedVisibility মাধ্যমে চমৎকার দ্বি-স্তরীয় ট্রানজিশন তৈরি করা যায়, যেমন—প্রেডিক্টিভ ব্যাক জেসচার ট্র্যাকিং-এর জন্য।
  • ম্যানুয়াল অ্যানিমেশন নিয়ন্ত্রণ : একটি ট্রানজিশনের বিলম্বিত পর্যায়ে, অ্যানিমেটেড বৈশিষ্ট্যগুলি (যেমন স্কেল বা অফসেট) এখন রিয়েল-টাইমে ম্যানুয়ালি নিয়ন্ত্রণ করা যাবে (উদাহরণস্বরূপ, একটি সোয়াইপ জেসচার ট্র্যাক করা)।
  • নির্বিঘ্ন হস্তান্তর : বিলম্বিত পর্যায় শেষ হয়ে গেলে, ট্রানজিশন ইঞ্জিন দায়িত্ব গ্রহণ করে এবং বেগ স্থানান্তর সহ স্বয়ংক্রিয় ট্রানজিশনে একটি নির্বিঘ্ন হস্তান্তর সম্পন্ন করে।
  • শেয়ার্ড এলিমেন্ট সাপোর্ট : SharedContentConfig এর একটি নতুন permitTransformDuringDeferredTransition ফ্ল্যাগ নিয়ন্ত্রণ করে যে, ডিফার্ড ট্রানজিশন পর্যায়ে শেয়ার্ড এলিমেন্টগুলো তাদের প্যারেন্ট কন্টেইনারের সাথে দৃশ্যত রূপান্তরিত হবে কি না।
val state = remember { DeferredTransitionState(initialScreen) }
val transition = rememberDeferredTransition(state)

if (predictiveBackInProgress) {
    state.defer(targetScreen)
} else {
    state.animateTo(targetScreen)
}

transition.DeferredAnimatedContent(
    targetState = targetScreen,
    mutableTransformSpec = {
       MutableContentTransform {
           // Manually manipulate properties during the deferred phase
           initialContentTransform { scale = swipeProgress }
       }
    }
) { screen ->
    ScreenContent(screen)
}

নিচে এমন দুটি ব্যবহারের উদাহরণ দেওয়া হলো যেখানে একটি জেসচার-চালিত অ্যানিমেশনকে একটি ট্রিগারড অ্যানিমেশনে হস্তান্তর করা হয়:

colorCards.gif

টেক্সট, ইনপুট এবং প্ল্যাটফর্ম ইন্টিগ্রেশন

সম্পাদনাযোগ্য টেক্সট ফরম্যাটিং

নতুন API-গুলো BasicTextField এর সম্পাদনাযোগ্য টেক্সটের জন্য রিচ-টেক্সট ফরম্যাটিং-এর সুবিধা দেয়। এখন আপনি TextFieldBuffer স্কোপের (যেমন textFieldState.edit { ... } বা একটি InputTransformation ভিতরে) নতুন addStyle() মেথডের মাধ্যমে SpanStyle এবং ParagraphStyle ব্যবহার করে প্রোগ্রাম্যাটিকভাবে ইনলাইন ক্যারেক্টার এবং প্যারাগ্রাফ ফরম্যাটিং প্রয়োগ ও পরিবর্তন করতে পারবেন। এছাড়াও, TextFieldBuffer getSpanStyles() এবং getParagraphStyles() API রয়েছে যা TrackedRange অবজেক্ট রিটার্ন করে, যার ফলে আপনি প্রয়োগ করা স্টাইলগুলো পড়তে, আপডেট করতে বা মুছে ফেলতে পারবেন। ফরম্যাটিং তৈরির পরিপূরক হিসেবে, TextFieldState এখন রেঞ্জ জুড়ে সক্রিয় স্টাইলগুলো কোয়েরি করার জন্য একটি রিড-অনলি textStyles প্রপার্টি প্রদান করে, অন্যদিকে TextFieldBuffer সম্পাদনার আগে ফরম্যাটিং-এর অবস্থা পরীক্ষা করার জন্য originalTextStyles প্রদান করে। কনফিগারেশন পরিবর্তনের পরেও টেক্সট ফরম্যাটিং এবং কাস্টম অ্যানোটেশনগুলো সংরক্ষিত থাকে।

val state = rememberTextFieldState("Formatted text in Compose 1.12")

// Apply bold and color styles to a range of text
state.edit {
    addStyle(
        SpanStyle(fontWeight = FontWeight.Bold, color = Color.Blue),
        start = 0,
        end = 9
    )
}

// Query active styles from TextFieldState
val currentStyles = state.textStyles

পাঠ্য নির্বাচন

একটি নতুন SelectionState API, SelectionContainer মধ্যে টেক্সট সিলেকশনের উপর প্রোগ্রাম্যাটিক নিয়ন্ত্রণ এবং পর্যবেক্ষণযোগ্যতা প্রদান করে। rememberSelectionState() এর মাধ্যমে একটি SelectionState অবজেক্ট হোইস্ট করে SelectionContainer এ পাস করলে, selectedTexts AnnotatedStrings এর একটি রিঅ্যাক্টিভ লিস্ট হিসেবে প্রকাশ করা যায় এবং selectAll() , clear() , select(TextRange) , ও extendSelectionByWord() এর মতো মেথডগুলো পাওয়া যায়।

এছাড়াও, লেআউট ক্রমানুসারে সমস্ত নির্বাচনযোগ্য টেক্সট আইটেম পুনরুদ্ধার করতে getSelectableTexts() ব্যবহার করুন এবং একটি গ্লোবাল রেঞ্জ ব্যবহার করে SelectionContainer এর কম্পোজেবলগুলো জুড়ে টেক্সট নির্বাচন করুন।

@Composable
fun ProgrammaticSelectionExample() {
    val selectionState = rememberSelectionState()

    Column {
        Button(
            onClick = { selectionState.selectAll() },
            modifier = Modifier.disableSelectionClearOnTap()
        ) {
            Text("Select All")
        }

        SelectionContainer(state = selectionState) {
            Text("Text content to be selected programmatically.")
        }
    }
}

ক্রেডেনশিয়াল ম্যানেজার ইন্টিগ্রেশন

কম্পোজ টেক্সট ফিল্ডগুলো এখন অটোফিল ফ্রেমওয়ার্কের মাধ্যমে অ্যান্ড্রয়েডের ক্রেডেনশিয়াল ম্যানেজারের (API 34+) সাথে নেটিভভাবে ইন্টিগ্রেট করে (API 34-এর নিচের ভার্সন androidx.credentials library দ্বারা পরিচালিত হয়)। CredentialRequestData সাথে নতুন credentialRequest সিম্যান্টিকস প্রপার্টিটি যুক্ত করার মাধ্যমে, টেক্সট ইনপুটগুলো ব্যবহারকারীর ইনপুট ফ্লো-এর মধ্যেই সরাসরি পাসকি, সংরক্ষিত ক্রেডেনশিয়াল বা সাইন-ইন অনুরোধ করতে পারে।

@Composable
fun LoginField(textFieldState: TextFieldState) {
    val credentialData = remember {
        CredentialRequestData(
            // Specify Credential Manager request options
        )
    }

    BasicTextField(
        state = textFieldState,
        modifier = Modifier.semantics {
            credentialRequest = credentialData
        }
    )
}

অন্যান্য উল্লেখযোগ্য পরিবর্তন:

  • ডাউনলোডযোগ্য ফন্টগুলিতে ফন্ট ভ্যারিয়েশন সেটিংসের জন্য সমর্থন।
  • SelectionContainer এ টেক্সট সিলেকশনকে ভিউপোর্টের বাইরে ড্র্যাগ করার সময় অটো-স্ক্রোলিং সক্রিয় করা হয়েছে।
  • কম্পোজ কম্পোনেন্টগুলিতে স্বয়ংক্রিয় ইন্টারঅ্যাকশন সাউন্ড (ক্লিক এবং ফোকাস নেভিগেশন) এর জন্য সমর্থন যোগ করা হয়েছে, এবং এটি থেকে অপ্ট-আউট করার সুযোগ দেওয়ার জন্য একটি নতুন SoundEffectOnInteraction কম্পোজেবল যুক্ত করা হয়েছে। উল্লেখ্য যে, এই পরিবর্তনের ফলস্বরূপ, সেম্যান্টিকস ক্লিক লিসেনারগুলিকে এখন থেকে মেইন থ্রেড থেকে কল করতে হবে, যা অল্প কিছু টেস্ট কেসকে প্রভাবিত করতে পারে।
  • KeyboardType মধ্যে এখন Date , Time , DateTime এবং SignedDecimal অন্তর্ভুক্ত রয়েছে।
  • BasicSecureTextField এখন ডিফল্টরূপে TextObfuscationMode.System ব্যবহার করে, অপরদিকে RevealLastTyped একটি অ্যাবসোলিউট ওভাররাইড হিসেবে কাজ করে।

লেআউট উন্নয়ন

গ্রিড লেআউটে নামযুক্ত এলাকা

@Experimental Grid কম্পোনেন্টের নেমড এরিয়ার মাধ্যমে জটিল 2D লেআউট তৈরি করা এখন আরও সহজ। আইটেম জুড়ে সংখ্যাসূচক কলাম এবং সারি সূচক পরিচালনা করার পরিবর্তে, আপনি আপনার GridConfigurationScope এ সিমান্টিক অঞ্চল সংজ্ঞায়িত করতে পারেন এবং এরিয়ার নাম অনুসারে কম্পোজেবলগুলির অবস্থান নির্ধারণ করতে পারেন।

@OptIn(ExperimentalGridApi::class)
@Composable
fun DashboardLayout() {
    Grid(
        config = {
            area("header", row = 0, column = 0, rowSpan = 1, columnSpan = 2)
            area("sidebar", row = 1, column = 0)
            area("content", row = 1, column = 1)
            gap(16.dp)
        }
    ) {
        HeaderSection(modifier = Modifier.gridItem(areaId = "header"))
        NavigationSidebar(modifier = Modifier.gridItem(areaId = "sidebar"))
        MainContentView(modifier = Modifier.gridItem(areaId = "content"))
    }
}

আরও তথ্যের জন্য, ডকুমেন্টেশন দেখুন।

কর্মক্ষমতা

প্রতিটি রিলিজের মতোই, আমরা Compose-এর পারফরম্যান্সে বিনিয়োগ অব্যাহত রেখেছি, যাতে এই ফ্রেমওয়ার্কটি আপনাকে সুন্দর ও উন্নত পারফরম্যান্সের অ্যাপ তৈরি করতে সাহায্য করে। এই রিলিজে আমরা স্টার্টআপ পারফরম্যান্স উন্নত করার উপর মনোযোগ দিয়েছি এবং এখন আমাদের বেঞ্চমার্কে Time to Initial Display (একটি অ্যাপের প্রথম ফ্রেম তৈরি করতে যে সময় লাগে) Views-এর সাথে তুলনীয় দেখতে পাচ্ছি।

timetoinitialdisplay@2x _v2.png

পরীক্ষা ও সরঞ্জাম আপগ্রেড

পরীক্ষা সিঙ্ক্রোনাইজেশন

Compose 1.12 নতুন টেস্ট এপিআই চালু করেছে, যা টেস্ট সম্পাদনের সময় কমাতে এবং স্টেট স্যাম্পলিং চলাকালীন অস্থিরতা দূর করার জন্য ডিজাইন করা হয়েছে:

  • hasPendingWork : ঘড়ির সময় না বাড়িয়ে নিষ্ক্রিয়ভাবে পরীক্ষা করে দেখে যে UI-তে কোনো অসমাপ্ত কাজ আছে কিনা, যা ম্যানুয়াল অ্যানিমেশন লুপের জন্য আদর্শ।
  • runWithoutImplicitWait : ম্যানুয়াল ক্লক ফ্রেমগুলো ধাপে ধাপে দেখার সময় (যেমন অ্যানিমেশন পরীক্ষা) এটি সাময়িকভাবে অন্তর্নিহিত সিঙ্ক্রোনাইজেশন নিষ্ক্রিয় করে।
@Test
fun testAnimationStateFast() {

composeTestRule.mainClock.autoAdvance = false
    
    while (composeTestRule.hasPendingWork()) {
        composeTestRule.mainClock.advanceTimeByFrame()
        composeTestRule.waitForIdle()
        
        composeTestRule.runOnUiThread {
            composeTestRule.runWithoutImplicitWait {
                // This is most effective when querying multiple nodes in a single frame. 
                // It prevents the redundant synchronization overhead that would 
                // otherwise occur on every individual query.
                val box1 = composeTestRule.onNodeWithTag("Box1").fetchSemanticsNode()
                val box2 = composeTestRule.onNodeWithTag("Box2").fetchSemanticsNode()
                
                assertThat(box1.boundsInRoot.right).isAtMost(box2.boundsInRoot.left)
            }
        }
    }
}

অন্যান্য উল্লেখযোগ্য পরিবর্তন:

  • captureToImage API এখন আপনাকে একটি পপআপ বা ডায়ালগকে তার অ্যাঙ্করসহ একটি একক বিটম্যাপে ক্যাপচার করার সুযোগ দেয়।
  • নির্দিষ্ট অ্যান্ড্রয়েড ভিউতে কম্পোজ সিমান্টিক সার্চ করার জন্য onRootWithViewInteraction স্কোপে যুক্ত করা হয়েছে। এর ফলে প্রোডাকশন কোডে স্বতন্ত্র টেস্ট ট্যাগের প্রয়োজন ছাড়াই RecyclerViews মতো হাইব্রিড UI পরীক্ষা করা সহজ হয়।
  • এখন কাস্টম @MultiPreview ক্লাসগুলিতে @PreviewWrapper অ্যানোটেশন প্রয়োগ করা যাবে, যার ফলে একাধিক কম্পোনেন্ট জুড়ে পুনঃব্যবহারযোগ্য প্রিভিউ সেটআপ (যেমন কাস্টম থিম) তৈরি করা সম্ভব হয়।

রচনা করা আনন্দদায়ক হোক!

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

লিখেছেন:
পড়তে থাকুন