সংশোধক রচনা করুন

মডিফায়ার আপনাকে একটি কম্পোজেবল সাজাতে বা বৃদ্ধি করতে দেয়। মডিফায়ার আপনাকে এই ধরণের কাজ করতে দেয়:

  • কম্পোজেবলের আকার, বিন্যাস, আচরণ এবং চেহারা পরিবর্তন করুন
  • অ্যাক্সেসিবিলিটি লেবেলের মতো তথ্য যোগ করুন
  • ব্যবহারকারীর ইনপুট প্রক্রিয়া করুন
  • উচ্চ-স্তরের ইন্টারঅ্যাকশন যোগ করুন, যেমন কোনও উপাদানকে ক্লিকযোগ্য, স্ক্রোলযোগ্য, টেনে আনার যোগ্য বা জুমযোগ্য করা

মডিফায়ার হল স্ট্যান্ডার্ড কোটলিন অবজেক্ট। Modifier ক্লাস ফাংশনগুলির একটি কল করে একটি মডিফায়ার তৈরি করুন:

@Composable
private fun Greeting(name: String) {
    Column(modifier = Modifier.padding(24.dp)) {
        Text(text = "Hello,")
        Text(text = name)
    }
}

রঙিন পটভূমিতে দুটি লাইন লেখা, লেখার চারপাশে প্যাডিং সহ।

আপনি এই ফাংশনগুলিকে একসাথে চেইন করে রচনা করতে পারেন:

@Composable
private fun Greeting(name: String) {
    Column(
        modifier = Modifier
            .padding(24.dp)
            .fillMaxWidth()
    ) {
        Text(text = "Hello,")
        Text(text = name)
    }
}

টেক্সটের পিছনের রঙিন ব্যাকগ্রাউন্ডটি এখন ডিভাইসের পুরো প্রস্থকে প্রসারিত করে।

উপরের কোডে, একসাথে ব্যবহৃত বিভিন্ন মডিফায়ার ফাংশন লক্ষ্য করুন।

  • padding একটি উপাদানের চারপাশে স্থান রাখে।
  • fillMaxWidth কম্পোজেবল ফিলকে তার প্যারেন্ট থেকে প্রদত্ত সর্বোচ্চ প্রস্থে পরিণত করে।

আপনার সমস্ত কম্পোজেবল একটি modifier প্যারামিটার গ্রহণ করে এবং সেই মডিফায়ারটিকে তার প্রথম চাইল্ডে পাস করে যা UI নির্গত করে, এটি করা আপনার কোডকে আরও পুনঃব্যবহারযোগ্য করে তোলে এবং এর আচরণকে আরও অনুমানযোগ্য এবং স্বজ্ঞাত করে তোলে। আরও তথ্যের জন্য, Compose API নির্দেশিকা দেখুন, Elements একটি Modifier প্যারামিটার গ্রহণ করে এবং সম্মান করে

সংশোধকগুলির ক্রম গুরুত্বপূর্ণ

মডিফায়ার ফাংশনের ক্রম উল্লেখযোগ্য । যেহেতু প্রতিটি ফাংশন পূর্ববর্তী ফাংশন দ্বারা প্রদত্ত Modifier পরিবর্তন করে, তাই ক্রমটি চূড়ান্ত ফলাফলকে প্রভাবিত করে। আসুন এর একটি উদাহরণ দেখি:

@Composable
fun ArtistCard(/*...*/) {
    val padding = 16.dp
    Column(
        Modifier
            .clickable(onClick = onClick)
            .padding(padding)
            .fillMaxWidth()
    ) {
        // rest of the implementation
    }
}

প্রান্তের চারপাশের প্যাডিং সহ পুরো এলাকাটি ক্লিকের প্রতিক্রিয়া জানায়

উপরের কোডে, পুরো এলাকাটি ক্লিকযোগ্য, আশেপাশের প্যাডিং সহ, কারণ padding মডিফায়ারটি clickable মডিফায়ারের পরে প্রয়োগ করা হয়েছে। যদি মডিফায়ারের ক্রম বিপরীত করা হয়, তাহলে padding দ্বারা যোগ করা স্থানটি ব্যবহারকারীর ইনপুটের প্রতি প্রতিক্রিয়া দেখায় না:

@Composable
fun ArtistCard(/*...*/) {
    val padding = 16.dp
    Column(
        Modifier
            .padding(padding)
            .clickable(onClick = onClick)
            .fillMaxWidth()
    ) {
        // rest of the implementation
    }
}

লেআউটের প্রান্তের চারপাশের প্যাডিং আর ক্লিকের প্রতিক্রিয়া দেখায় না।

অন্তর্নির্মিত সংশোধক

জেটপ্যাক কম্পোজ আপনাকে একটি কম্পোজেবল সাজাতে বা উন্নত করতে সাহায্য করার জন্য বিল্ট-ইন মডিফায়ারের একটি তালিকা প্রদান করে। এখানে কিছু সাধারণ মডিফায়ার দেওয়া হল যা আপনি আপনার লেআউট সামঞ্জস্য করতে ব্যবহার করবেন।

padding এবং size

ডিফল্টরূপে, কম্পোজে প্রদত্ত লেআউটগুলি তাদের সন্তানদের জন্য প্রযোজ্য। তবে, আপনি size পরিবর্তনকারী ব্যবহার করে একটি আকার সেট করতে পারেন:

@Composable
fun ArtistCard(/*...*/) {
    Row(
        modifier = Modifier.size(width = 400.dp, height = 100.dp)
    ) {
        Image(/*...*/)
        Column { /*...*/ }
    }
}

মনে রাখবেন যে আপনার নির্দিষ্ট আকারটি যদি লেআউটের প্যারেন্ট থেকে আসা সীমাবদ্ধতাগুলি পূরণ না করে তবে তা সম্মানিত নাও হতে পারে। যদি আপনি আগত সীমাবদ্ধতাগুলি নির্বিশেষে কম্পোজেবল আকারটি ঠিক করতে চান, তাহলে requiredSize মডিফায়ার ব্যবহার করুন:

@Composable
fun ArtistCard(/*...*/) {
    Row(
        modifier = Modifier.size(width = 400.dp, height = 100.dp)
    ) {
        Image(
            /*...*/
            modifier = Modifier.requiredSize(150.dp)
        )
        Column { /*...*/ }
    }
}

সন্তানের ভাবমূর্তি তার পিতামাতার কাছ থেকে আসা সীমাবদ্ধতার চেয়েও বড়।

এই উদাহরণে, এমনকি প্যারেন্ট height 100.dp তে সেট করা থাকলেও, Image উচ্চতা 150.dp হবে, কারণ requiredSize মডিফায়ারটি প্রাধান্য পাবে।

যদি আপনি চান যে একটি চাইল্ড লেআউটে প্যারেন্ট কর্তৃক অনুমোদিত সমস্ত উচ্চতা পূরণ করা হোক, তাহলে fillMaxHeight মডিফায়ার যোগ করুন (Compose এছাড়াও fillMaxSize এবং fillMaxWidth প্রদান করে):

@Composable
fun ArtistCard(/*...*/) {
    Row(
        modifier = Modifier.size(width = 400.dp, height = 100.dp)
    ) {
        Image(
            /*...*/
            modifier = Modifier.fillMaxHeight()
        )
        Column { /*...*/ }
    }
}

ছবির উচ্চতা তার মূল উচ্চতার সমান।

একটি এলিমেন্টের চারপাশে প্যাডিং যোগ করতে, একটি padding মডিফায়ার সেট করুন।

যদি আপনি একটি টেক্সট বেসলাইনের উপরে প্যাডিং যোগ করতে চান যাতে লেআউটের শীর্ষ থেকে বেসলাইন পর্যন্ত একটি নির্দিষ্ট দূরত্ব অর্জন করা যায়, তাহলে paddingFromBaseline মডিফায়ার ব্যবহার করুন:

@Composable
fun ArtistCard(artist: Artist) {
    Row(/*...*/) {
        Column {
            Text(
                text = artist.name,
                modifier = Modifier.paddingFromBaseline(top = 50.dp)
            )
            Text(artist.lastSeenOnline)
        }
    }
}

উপরে প্যাডিং সহ টেক্সট

অফসেট

একটি লেআউটকে তার মূল অবস্থানের সাথে সাপেক্ষে স্থাপন করতে, offset মডিফায়ার যোগ করুন এবং x এবং y অক্ষে অফসেট সেট করুন। অফসেটগুলি ধনাত্মক এবং অ-ধনাত্মক উভয়ই হতে পারে। padding এবং offset মধ্যে পার্থক্য হল যে একটি কম্পোজেবলে একটি offset যোগ করলে এর পরিমাপ পরিবর্তন হয় না:

@Composable
fun ArtistCard(artist: Artist) {
    Row(/*...*/) {
        Column {
            Text(artist.name)
            Text(
                text = artist.lastSeenOnline,
                modifier = Modifier.offset(x = 4.dp)
            )
        }
    }
}

টেক্সটটি তার মূল কন্টেইনারের ডান দিকে স্থানান্তরিত হয়েছে

offset মডিফায়ারটি লেআউটের দিক অনুসারে অনুভূমিকভাবে প্রয়োগ করা হয়। বাম থেকে ডান প্রসঙ্গে, একটি ধনাত্মক offset উপাদানটিকে ডানে স্থানান্তর করে, যখন ডান থেকে বাম প্রসঙ্গে, এটি উপাদানটিকে বাম দিকে স্থানান্তর করে। যদি আপনার লেআউটের দিক বিবেচনা না করে একটি অফসেট সেট করার প্রয়োজন হয়, তাহলে absoluteOffset মডিফায়ারটি দেখুন, যেখানে একটি ধনাত্মক অফসেট মান সর্বদা উপাদানটিকে ডানে স্থানান্তর করে।

offset মডিফায়ার দুটি ওভারলোড প্রদান করে - offset যা অফসেটগুলিকে প্যারামিটার হিসেবে গ্রহণ করে এবং offset যা ল্যাম্বডাকে গ্রহণ করে। এই প্রতিটি কখন ব্যবহার করতে হবে এবং কীভাবে পারফরম্যান্সের জন্য অপ্টিমাইজ করতে হবে সে সম্পর্কে আরও বিস্তারিত তথ্যের জন্য, "Compose performance - Defer যতটা সম্ভব দীর্ঘতর পড়ুন" বিভাগটি পড়ুন।

কম্পোজে স্কোপ নিরাপত্তা

কম্পোজে, এমন কিছু মডিফায়ার রয়েছে যা শুধুমাত্র নির্দিষ্ট কম্পোজেবলের শিশুদের ক্ষেত্রে প্রয়োগ করা হলেই ব্যবহার করা যেতে পারে। কম্পোজ কাস্টম স্কোপের মাধ্যমে এটি প্রয়োগ করে।

উদাহরণস্বরূপ, যদি আপনি Box আকারকে প্রভাবিত না করে একটি শিশুকে প্যারেন্ট Box মতো বড় করতে চান, তাহলে matchParentSize মডিফায়ার ব্যবহার করুন। matchParentSize শুধুমাত্র BoxScope এ উপলব্ধ। অতএব, এটি শুধুমাত্র একটি Box প্যারেন্টের মধ্যে থাকা একটি শিশুতে ব্যবহার করা যেতে পারে।

স্কোপ সেফটি আপনাকে এমন মডিফায়ার যোগ করতে বাধা দেয় যা অন্যান্য কম্পোজেবল এবং স্কোপে কাজ করবে না এবং ট্রায়াল এবং এরর থেকে সময় বাঁচায়।

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

Box matchParentSize

উপরে উল্লিখিত হিসাবে, যদি আপনি চান যে একটি চাইল্ড লেআউট প্যারেন্ট Box সমান আকারের হোক এবং Box আকার প্রভাবিত না করে, তাহলে matchParentSize মডিফায়ার ব্যবহার করুন।

মনে রাখবেন যে matchParentSize শুধুমাত্র একটি Box স্কোপের মধ্যেই উপলব্ধ, অর্থাৎ এটি শুধুমাত্র Box composables এর সরাসরি শিশুদের ক্ষেত্রে প্রযোজ্য।

নিচের উদাহরণে, চাইল্ড Spacer তার প্যারেন্ট Box থেকে তার আকার নেয়, যা পরবর্তীতে সবচেয়ে বড় বাচ্চাদের, এই ক্ষেত্রে ArtistCard থেকে তার আকার নেয়।

@Composable
fun MatchParentSizeComposable() {
    Box {
        Spacer(
            Modifier
                .matchParentSize()
                .background(Color.LightGray)
        )
        ArtistCard()
    }
}

পাত্রটি ভরা ধূসর পটভূমি

যদি matchParentSize এর পরিবর্তে fillMaxSize ব্যবহার করা হয়, তাহলে Spacer সমস্ত উপলব্ধ স্থান প্যারেন্টের কাছে নিয়ে যাবে, যার ফলে প্যারেন্ট প্রসারিত হবে এবং সমস্ত উপলব্ধ স্থান পূরণ করবে।

স্ক্রিনে ধূসর পটভূমি

Row এবং Column weight

যেমনটি আপনি পূর্ববর্তী প্যাডিং এবং আকার বিভাগে দেখেছেন, ডিফল্টরূপে, একটি কম্পোজেবল আকার এটি মোড়ানো বিষয়বস্তু দ্বারা সংজ্ঞায়িত করা হয়। আপনি weight Modifier ব্যবহার করে একটি কম্পোজেবল আকারকে তার মূল অংশের মধ্যে নমনীয় করার জন্য সেট করতে পারেন যা শুধুমাত্র RowScope এবং ColumnScope এ উপলব্ধ।

ধরা যাক এমন একটি Row যাতে দুটি Box composable আছে। প্রথম বাক্সটির weight দ্বিতীয়টির দ্বিগুণ, তাই এটির প্রস্থ দ্বিগুণ। যেহেতু Row 210.dp প্রস্থ, প্রথম Box 140.dp প্রস্থ এবং দ্বিতীয়টি 70.dp :

@Composable
fun ArtistCard(/*...*/) {
    Row(
        modifier = Modifier.fillMaxWidth()
    ) {
        Image(
            /*...*/
            modifier = Modifier.weight(2f)
        )
        Column(
            modifier = Modifier.weight(1f)
        ) {
            /*...*/
        }
    }
}

ছবির প্রস্থ টেক্সট প্রস্থের দ্বিগুণ।

সংশোধক নিষ্কাশন এবং পুনঃব্যবহার

একাধিক মডিফায়ারকে একসাথে চেইন করে একটি কম্পোজেবলকে সাজাতে বা বৃদ্ধি করতে পারে। এই চেইনটি Modifier ইন্টারফেসের মাধ্যমে তৈরি করা হয় যা একক Modifier.Elements একটি ক্রমযুক্ত, অপরিবর্তনীয় তালিকা উপস্থাপন করে।

প্রতিটি Modifier.Element একটি পৃথক আচরণের প্রতিনিধিত্ব করে, যেমন লেআউট, অঙ্কন এবং গ্রাফিক্স আচরণ, সমস্ত অঙ্গভঙ্গি-সম্পর্কিত, ফোকাস এবং শব্দার্থবিদ্যা আচরণ, সেইসাথে ডিভাইস ইনপুট ইভেন্ট। তাদের ক্রম গুরুত্বপূর্ণ: প্রথমে যোগ করা সংশোধক উপাদানগুলি প্রথমে প্রয়োগ করা হবে।

কখনও কখনও একই মডিফায়ার চেইন ইনস্ট্যান্সগুলিকে একাধিক কম্পোজেবলে পুনঃব্যবহার করা উপকারী হতে পারে, সেগুলিকে ভেরিয়েবলে এক্সট্র্যাক্ট করে এবং উচ্চতর স্কোপে উত্তোলন করে। এটি কোড পঠনযোগ্যতা উন্নত করতে পারে অথবা কয়েকটি কারণে আপনার অ্যাপের কর্মক্ষমতা উন্নত করতে সাহায্য করতে পারে:

  • সংশোধক ব্যবহার করে এমন কম্পোজেবলের জন্য পুনর্গঠন ঘটলে সংশোধকগুলির পুনঃবণ্টন পুনরাবৃত্তি হবে না।
  • মডিফায়ার চেইনগুলি সম্ভবত খুব দীর্ঘ এবং জটিল হতে পারে, তাই একই চেইনের উদাহরণ পুনঃব্যবহার করলে তুলনা করার সময় কম্পোজ রানটাইমের কাজের চাপ কমানো যেতে পারে।
  • এই এক্সট্রাকশন কোডবেস জুড়ে কোডের পরিচ্ছন্নতা, ধারাবাহিকতা এবং রক্ষণাবেক্ষণের সুবিধা প্রদান করে।

মডিফায়ার পুনঃব্যবহারের জন্য সর্বোত্তম অনুশীলন

আপনার নিজস্ব Modifier চেইন তৈরি করুন এবং একাধিক কম্পোজেবল কম্পোনেন্টে পুনঃব্যবহারের জন্য সেগুলি এক্সট্র্যাক্ট করুন। শুধুমাত্র একটি মডিফায়ার সংরক্ষণ করা সম্পূর্ণ ঠিক আছে, কারণ এগুলি ডেটা-সদৃশ অবজেক্ট:

val reusableModifier = Modifier
    .fillMaxWidth()
    .background(Color.Red)
    .padding(12.dp)

ঘন ঘন পরিবর্তনশীল অবস্থা পর্যবেক্ষণ করার সময় মডিফায়ারগুলি বের করা এবং পুনঃব্যবহার করা

অ্যানিমেশন অবস্থা বা scrollState মতো কম্পোজেবলের ভিতরে ঘন ঘন পরিবর্তিত অবস্থা পর্যবেক্ষণ করার সময়, উল্লেখযোগ্য পরিমাণে পুনর্গঠন করা হতে পারে। এই ক্ষেত্রে, আপনার মডিফায়ারগুলি প্রতিটি পুনর্গঠনের জন্য বরাদ্দ করা হবে এবং সম্ভাব্যভাবে প্রতিটি ফ্রেমের জন্য:

@Composable
fun LoadingWheelAnimation() {
    val animatedState = animateFloatAsState(/*...*/)

    LoadingWheel(
        // Creation and allocation of this modifier will happen on every frame of the animation!
        modifier = Modifier
            .padding(12.dp)
            .background(Color.Gray),
        animatedState = animatedState
    )
}

পরিবর্তে, আপনি মডিফায়ারের একই উদাহরণ তৈরি, এক্সট্র্যাক্ট এবং পুনঃব্যবহার করতে পারেন এবং এটি কম্পোজেবলে এভাবে পাস করতে পারেন:

// Now, the allocation of the modifier happens here:
val reusableModifier = Modifier
    .padding(12.dp)
    .background(Color.Gray)

@Composable
fun LoadingWheelAnimation() {
    val animatedState = animateFloatAsState(/*...*/)

    LoadingWheel(
        // No allocation, as we're just reusing the same instance
        modifier = reusableModifier,
        animatedState = animatedState
    )
}

আনস্কোপড মডিফায়ারগুলি বের করা এবং পুনঃব্যবহার করা

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

val reusableModifier = Modifier
    .fillMaxWidth()
    .background(Color.Red)
    .padding(12.dp)

@Composable
fun AuthorField() {
    HeaderText(
        // ...
        modifier = reusableModifier
    )
    SubtitleText(
        // ...
        modifier = reusableModifier
    )
}

Lazy লেআউটের সাথে মিলিত হলে এটি বিশেষভাবে উপকারী হতে পারে। বেশিরভাগ ক্ষেত্রে, আপনি চাইবেন যে আপনার সমস্ত, সম্ভাব্য উল্লেখযোগ্য, পরিমাণ আইটেমের একই রকম মডিফায়ার থাকুক:

val reusableItemModifier = Modifier
    .padding(bottom = 12.dp)
    .size(216.dp)
    .clip(CircleShape)

@Composable
private fun AuthorList(authors: List<Author>) {
    LazyColumn {
        items(authors) {
            AsyncImage(
                // ...
                modifier = reusableItemModifier,
            )
        }
    }
}

স্কোপড মডিফায়ার নিষ্কাশন এবং পুনঃব্যবহার

নির্দিষ্ট কম্পোজেবলের সাথে সংযুক্ত মডিফায়ারগুলির সাথে কাজ করার সময়, আপনি সেগুলিকে সর্বোচ্চ সম্ভাব্য স্তরে বের করতে পারেন এবং যেখানে উপযুক্ত সেখানে পুনরায় ব্যবহার করতে পারেন:

Column(/*...*/) {
    val reusableItemModifier = Modifier
        .padding(bottom = 12.dp)
        // Align Modifier.Element requires a ColumnScope
        .align(Alignment.CenterHorizontally)
        .weight(1f)
    Text1(
        modifier = reusableItemModifier,
        // ...
    )
    Text2(
        modifier = reusableItemModifier
        // ...
    )
    // ...
}

আপনার কেবল এক্সট্র্যাক্ট করা, স্কোপড মডিফায়ারগুলি একই-স্কোপড, সরাসরি শিশুদের কাছে পাঠানো উচিত। এটি কেন গুরুত্বপূর্ণ তা আরও তথ্যের জন্য কম্পোজে স্কোপ সেফটি বিভাগটি দেখুন:

Column(modifier = Modifier.fillMaxWidth()) {
    // Weight modifier is scoped to the Column composable
    val reusableItemModifier = Modifier.weight(1f)

    // Weight will be properly assigned here since this Text is a direct child of Column
    Text1(
        modifier = reusableItemModifier
        // ...
    )

    Box {
        Text2(
            // Weight won't do anything here since the Text composable is not a direct child of Column
            modifier = reusableItemModifier
            // ...
        )
    }
}

নিষ্কাশিত সংশোধকগুলির আরও শৃঙ্খলিতকরণ

আপনি .then() ফাংশনটি কল করে আপনার এক্সট্র্যাক্ট করা মডিফায়ার চেইনগুলিকে আরও চেইন বা সংযোজন করতে পারেন:

val reusableModifier = Modifier
    .fillMaxWidth()
    .background(Color.Red)
    .padding(12.dp)

// Append to your reusableModifier
reusableModifier.clickable { /*...*/ }

// Append your reusableModifier
otherModifier.then(reusableModifier)

শুধু মনে রাখবেন যে মডিফায়ারের ক্রম গুরুত্বপূর্ণ!

আরও জানুন

আমরা মডিফায়ারগুলির একটি সম্পূর্ণ তালিকা প্রদান করি, তাদের প্যারামিটার এবং সুযোগ সহ।

মডিফায়ার ব্যবহার সম্পর্কে আরও অনুশীলনের জন্য, আপনি Compose codelab-এর বেসিক লেআউটগুলি দেখতে পারেন অথবা Now in Android রিপোজিটরিটি দেখতে পারেন।

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

{% অক্ষরে অক্ষরে %} {% এন্ডভারব্যাটিম %} {% অক্ষরে অক্ষরে %} {% এন্ডভারব্যাটিম %}