কাস্টম মডিফায়ার তৈরি করুন

রচনা বাক্সের বাইরে সাধারণ আচরণের জন্য অনেকগুলি সংশোধক সরবরাহ করে, তবে আপনি আপনার নিজস্ব কাস্টম সংশোধকও তৈরি করতে পারেন।

সংশোধকদের একাধিক অংশ রয়েছে:

  • একটি মডিফায়ার কারখানা
    • এটি Modifier একটি এক্সটেনশন ফাংশন, যা আপনার মডিফায়ারের জন্য একটি ইডিওম্যাটিক এপিআই প্রদান করে এবং মডিফায়ারকে সহজে একত্রে বেঁধে রাখার অনুমতি দেয়। সংশোধক কারখানাটি আপনার UI পরিবর্তন করতে রচনা দ্বারা ব্যবহৃত সংশোধক উপাদানগুলি তৈরি করে৷
  • একটি পরিবর্তনকারী উপাদান
    • এখানে আপনি আপনার সংশোধকের আচরণ বাস্তবায়ন করতে পারেন।

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

বিদ্যমান মডিফায়ারকে একসাথে চেইন করুন

শুধুমাত্র বিদ্যমান মডিফায়ার ব্যবহার করে কাস্টম মডিফায়ার তৈরি করা প্রায়ই সম্ভব। উদাহরণস্বরূপ, Modifier.clip() graphicsLayer modifier ব্যবহার করে প্রয়োগ করা হয়। এই কৌশলটি বিদ্যমান সংশোধক উপাদানগুলি ব্যবহার করে এবং আপনি আপনার নিজস্ব কাস্টম সংশোধক কারখানা সরবরাহ করেন।

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

fun Modifier.clip(shape: Shape) = graphicsLayer(shape = shape, clip = true)

অথবা, যদি আপনি দেখতে পান যে আপনি প্রায়শই একই গোষ্ঠীর সংশোধক পুনরাবৃত্তি করছেন, আপনি সেগুলিকে আপনার নিজস্ব সংশোধকের মধ্যে মোড়ানো করতে পারেন:

fun Modifier.myBackground(color: Color) = padding(16.dp)
    .clip(RoundedCornerShape(8.dp))
    .background(color)

একটি কম্পোজেবল মডিফায়ার ফ্যাক্টরি ব্যবহার করে একটি কাস্টম মডিফায়ার তৈরি করুন

আপনি একটি বিদ্যমান মডিফায়ারে মান পাস করার জন্য একটি সংমিশ্রণযোগ্য ফাংশন ব্যবহার করে একটি কাস্টম সংশোধক তৈরি করতে পারেন। এটি একটি সংমিশ্রণযোগ্য মডিফায়ার কারখানা হিসাবে পরিচিত।

একটি সংশোধক তৈরি করার জন্য একটি সংমিশ্রণযোগ্য সংশোধক কারখানা ব্যবহার করা উচ্চ স্তরের রচনা APIগুলি ব্যবহার করার অনুমতি দেয়, যেমন animate*AsState এবং অন্যান্য কম্পোজ স্টেট ব্যাকড অ্যানিমেশন APIগুলি ৷ উদাহরণস্বরূপ, নিম্নলিখিত স্নিপেটটি একটি পরিবর্তনকারীকে দেখায় যা সক্রিয়/অক্ষম করার সময় একটি আলফা পরিবর্তনকে অ্যানিমেট করে:

@Composable
fun Modifier.fade(enable: Boolean): Modifier {
    val alpha by animateFloatAsState(if (enable) 0.5f else 1.0f)
    return this then Modifier.graphicsLayer { this.alpha = alpha }
}

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

@Composable
fun Modifier.fadedBackground(): Modifier {
    val color = LocalContentColor.current
    return this then Modifier.background(color.copy(alpha = 0.5f))
}

এই পদ্ধতির নিচে বিস্তারিত কিছু সতর্কতা রয়েছে।

CompositionLocal মানগুলি সংশোধনকারী কারখানার কল সাইটে সমাধান করা হয়

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

@Composable
fun Modifier.myBackground(): Modifier {
    val color = LocalContentColor.current
    return this then Modifier.background(color.copy(alpha = 0.5f))
}

@Composable
fun MyScreen() {
    CompositionLocalProvider(LocalContentColor provides Color.Green) {
        // Background modifier created with green background
        val backgroundModifier = Modifier.myBackground()

        // LocalContentColor updated to red
        CompositionLocalProvider(LocalContentColor provides Color.Red) {

            // Box will have green background, not red as expected.
            Box(modifier = backgroundModifier)
        }
    }
}

যদি আপনি আপনার সংশোধকের কাজ করার আশা না করেন তবে পরিবর্তে একটি কাস্টম Modifier.Node ব্যবহার করুন।

কম্পোজেবল ফাংশন মডিফায়ারগুলি কখনই এড়িয়ে যায় না

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

কম্পোজেবল ফাংশন মডিফায়ারকে অবশ্যই একটি কম্পোজেবল ফাংশনের মধ্যে কল করতে হবে

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

val extractedModifier = Modifier.background(Color.Red) // Hoisted to save allocations

@Composable
fun Modifier.composableModifier(): Modifier {
    val color = LocalContentColor.current.copy(alpha = 0.5f)
    return this then Modifier.background(color)
}

@Composable
fun MyComposable() {
    val composedModifier = Modifier.composableModifier() // Cannot be extracted any higher
}

Modifier.Node ব্যবহার করে কাস্টম মডিফায়ার আচরণ প্রয়োগ করুন

কম্পোজে মডিফায়ার তৈরি করার জন্য Modifier.Node একটি নিম্ন স্তরের API। এটি একই API যা কম্পোজ তার নিজস্ব সংশোধক প্রয়োগ করে এবং কাস্টম মডিফায়ার তৈরি করার সবচেয়ে কার্যকর উপায়।

Modifier.Node ব্যবহার করে একটি কাস্টম মডিফায়ার প্রয়োগ করুন

Modifier.Node ব্যবহার করে একটি কাস্টম মডিফায়ার বাস্তবায়নের তিনটি অংশ রয়েছে:

  • একটি Modifier.Node নোড বাস্তবায়ন যা আপনার সংশোধকের যুক্তি এবং অবস্থা ধারণ করে।
  • একটি ModifierNodeElement যা মডিফায়ার নোড ইন্সট্যান্স তৈরি এবং আপডেট করে।
  • উপরে বিস্তারিত হিসাবে একটি ঐচ্ছিক সংশোধক কারখানা.

ModifierNodeElement ক্লাসগুলি স্টেটলেস এবং প্রতিটি পুনর্গঠনের জন্য নতুন উদাহরণগুলি বরাদ্দ করা হয়, যেখানে Modifier.Node ক্লাসগুলি স্টেটফুল হতে পারে এবং একাধিক পুনর্গঠন জুড়ে টিকে থাকবে এবং এমনকি পুনরায় ব্যবহার করা যেতে পারে।

নিম্নলিখিত বিভাগ প্রতিটি অংশ বর্ণনা করে এবং একটি বৃত্ত আঁকার জন্য একটি কাস্টম সংশোধক নির্মাণের একটি উদাহরণ দেখায়।

Modifier.Node

Modifier.Node বাস্তবায়ন (এই উদাহরণে, CircleNode ) আপনার কাস্টম মডিফায়ারের কার্যকারিতা প্রয়োগ করে।

// Modifier.Node
private class CircleNode(var color: Color) : DrawModifierNode, Modifier.Node() {
    override fun ContentDrawScope.draw() {
        drawCircle(color)
    }
}

এই উদাহরণে, এটি মডিফায়ার ফাংশনে পাস করা রঙের সাথে বৃত্তটি আঁকে।

একটি নোড Modifier.Node প্রয়োগ করে। নোডের পাশাপাশি শূন্য বা তার বেশি নোড প্রকার। আপনার মডিফায়ারের প্রয়োজনীয় কার্যকারিতার উপর ভিত্তি করে বিভিন্ন নোডের ধরন রয়েছে। উপরের উদাহরণটি আঁকতে সক্ষম হওয়া প্রয়োজন, তাই এটি DrawModifierNode প্রয়োগ করে, যা এটিকে ড্র পদ্ধতি ওভাররাইড করতে দেয়।

উপলব্ধ প্রকারগুলি নিম্নরূপ:

নোড

ব্যবহার

নমুনা লিঙ্ক

LayoutModifierNode

একটি Modifier.Node যা পরিবর্তন করে কিভাবে এর মোড়ানো বিষয়বস্তু পরিমাপ করা হয় এবং সাজানো হয়।

নমুনা

DrawModifierNode

একটি Modifier.Node নোড যা লেআউটের স্পেসে আঁকে।

নমুনা

CompositionLocalConsumerModifierNode

এই ইন্টারফেসটি প্রয়োগ করা আপনার Modifier.Node কম্পোজিশন স্থানীয় পড়ার অনুমতি দেয়।

নমুনা

SemanticsModifierNode

একটি Modifier.Node যা পরীক্ষা, অ্যাক্সেসযোগ্যতা এবং অনুরূপ ব্যবহারের ক্ষেত্রে ব্যবহারের জন্য শব্দার্থবিদ্যা কী/মান যোগ করে।

নমুনা

PointerInputModifierNode

একটি Modifier.Node নোড যা পয়েন্টারইনপুট পরিবর্তনগুলি গ্রহণ করে।

নমুনা

ParentDataModifierNode

একটি Modifier.Node যা প্যারেন্ট লেআউটে ডেটা প্রদান করে।

নমুনা

LayoutAwareModifierNode

একটি Modifier.Node নোড যা onMeasured এবং onPlaced কলব্যাক গ্রহণ করে।

নমুনা

GlobalPositionAwareModifierNode

একটি Modifier.Node যা বিষয়বস্তুর বৈশ্বিক অবস্থান পরিবর্তিত হলে লেআউটের চূড়ান্ত LayoutCoordinates সহ একটি onGloballyPositioned কলব্যাক পায়।

নমুনা

ObserverModifierNode

ObserverNode প্রয়োগকারী Modifier.Node গুলি onObservedReadsChanged এর নিজস্ব বাস্তবায়ন প্রদান করতে পারে যা একটি observeReads ব্লকের মধ্যে পড়া স্ন্যাপশট অবজেক্টের পরিবর্তনের প্রতিক্রিয়া হিসাবে বলা হবে।

নমুনা

DelegatingNode

একটি Modifier.Node যা অন্য Modifier.Node উদাহরণে কাজ অর্পণ করতে সক্ষম।

এটি একটিতে একাধিক নোড বাস্তবায়ন রচনা করতে কার্যকর হতে পারে।

নমুনা

TraversableNode

Modifier.Node ক্লাসগুলিকে একই ধরণের ক্লাসের জন্য বা একটি নির্দিষ্ট কী-এর জন্য নোড ট্রিকে উপরে/নিচে যেতে দেয়৷

নমুনা

নোডগুলি স্বয়ংক্রিয়ভাবে অবৈধ হয়ে যায় যখন আপডেটগুলি তাদের সংশ্লিষ্ট উপাদানগুলিতে কল করা হয়। কারণ আমাদের উদাহরণ হল একটি DrawModifierNode , যেকোন সময় এলিমেন্টে আপডেট কল করা হলে, নোডটি পুনরায় ড্র ট্রিগার করে এবং এর রঙ সঠিকভাবে আপডেট হয়। নীচে বিস্তারিত হিসাবে স্বয়ংক্রিয়-অবৈধতা অপ্ট আউট করা সম্ভব৷

ModifierNodeElement

একটি ModifierNodeElement হল একটি অপরিবর্তনীয় শ্রেণী যা আপনার কাস্টম মডিফায়ার তৈরি বা আপডেট করার জন্য ডেটা ধারণ করে:

// ModifierNodeElement
private data class CircleElement(val color: Color) : ModifierNodeElement<CircleNode>() {
    override fun create() = CircleNode(color)

    override fun update(node: CircleNode) {
        node.color = color
    }
}

ModifierNodeElement বাস্তবায়নের জন্য নিম্নলিখিত পদ্ধতিগুলিকে ওভাররাইড করতে হবে:

  1. create : এটি সেই ফাংশন যা আপনার মডিফায়ার নোডকে ইনস্ট্যান্টিয়েট করে। যখন আপনার মডিফায়ারটি প্রথম প্রয়োগ করা হয় তখন এটি নোড তৈরি করতে বলা হয়। সাধারণত, এটি নোড নির্মাণ এবং পরিবর্তক কারখানায় পাস করা পরামিতিগুলির সাথে এটি কনফিগার করার পরিমাণ।
  2. update : এই ফাংশনটিকে বলা হয় যখনই এই মডিফায়ারটি একই জায়গায় প্রদান করা হয় এই নোডটি ইতিমধ্যেই বিদ্যমান, কিন্তু একটি বৈশিষ্ট্য পরিবর্তিত হয়েছে। এটি ক্লাসের equals পদ্ধতি দ্বারা নির্ধারিত হয়। পূর্বে তৈরি করা সংশোধক নোডটি update কলে একটি প্যারামিটার হিসাবে পাঠানো হয়। এই মুহুর্তে, আপনাকে আপডেট করা পরামিতিগুলির সাথে সঙ্গতিপূর্ণ করতে নোডের বৈশিষ্ট্যগুলি আপডেট করতে হবে। নোডের জন্য এইভাবে পুনঃব্যবহারের ক্ষমতা হ'ল Modifier.Node যে পারফরম্যান্স লাভের চাবিকাঠি; অতএব, আপনাকে update পদ্ধতিতে একটি নতুন তৈরি করার পরিবর্তে বিদ্যমান নোড আপডেট করতে হবে। আমাদের বৃত্তের উদাহরণে, নোডের রঙ আপডেট করা হয়েছে।

উপরন্তু, ModifierNodeElement বাস্তবায়নের জন্য equals এবং hashCode প্রয়োগ করতে হবে। update শুধুমাত্র তখনই কল করা হবে যদি পূর্ববর্তী উপাদানের সাথে একটি সমান তুলনা মিথ্যা রিটার্ন করে।

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

মডিফায়ার কারখানা

এটি আপনার সংশোধকের সর্বজনীন API পৃষ্ঠ। বেশিরভাগ বাস্তবায়ন কেবল সংশোধক উপাদান তৈরি করে এবং এটি সংশোধক চেইনে যুক্ত করে:

// Modifier factory
fun Modifier.circle(color: Color) = this then CircleElement(color)

সম্পূর্ণ উদাহরণ

Modifier.Node এপিআই ব্যবহার করে একটি বৃত্ত আঁকার জন্য কাস্টম মডিফায়ার তৈরি করতে এই তিনটি অংশ একত্রিত হয়:

// Modifier factory
fun Modifier.circle(color: Color) = this then CircleElement(color)

// ModifierNodeElement
private data class CircleElement(val color: Color) : ModifierNodeElement<CircleNode>() {
    override fun create() = CircleNode(color)

    override fun update(node: CircleNode) {
        node.color = color
    }
}

// Modifier.Node
private class CircleNode(var color: Color) : DrawModifierNode, Modifier.Node() {
    override fun ContentDrawScope.draw() {
        drawCircle(color)
    }
}

Modifier.Node ব্যবহার করে সাধারণ পরিস্থিতি

Modifier.Node দিয়ে কাস্টম মডিফায়ার তৈরি করার সময়, এখানে কিছু সাধারণ পরিস্থিতি রয়েছে যা আপনি সম্মুখীন হতে পারেন।

শূন্য পরামিতি

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

fun Modifier.fixedPadding() = this then FixedPaddingElement

data object FixedPaddingElement : ModifierNodeElement<FixedPaddingNode>() {
    override fun create() = FixedPaddingNode()
    override fun update(node: FixedPaddingNode) {}
}

class FixedPaddingNode : LayoutModifierNode, Modifier.Node() {
    private val PADDING = 16.dp

    override fun MeasureScope.measure(
        measurable: Measurable,
        constraints: Constraints
    ): MeasureResult {
        val paddingPx = PADDING.roundToPx()
        val horizontal = paddingPx * 2
        val vertical = paddingPx * 2

        val placeable = measurable.measure(constraints.offset(-horizontal, -vertical))

        val width = constraints.constrainWidth(placeable.width + horizontal)
        val height = constraints.constrainHeight(placeable.height + vertical)
        return layout(width, height) {
            placeable.place(paddingPx, paddingPx)
        }
    }
}

রেফারেন্সিং রচনা স্থানীয়দের

Modifier.Node নোড মডিফায়াররা স্বয়ংক্রিয়ভাবে কম্পোজ স্টেট অবজেক্টের পরিবর্তনগুলি পর্যবেক্ষণ করে না, যেমন CompositionLocalModifier.Node modifiers-এর সুবিধা হল ওভার মডিফায়ার যা শুধুমাত্র একটি কম্পোজেবল ফ্যাক্টরি দিয়ে তৈরি করা হয়েছে তা হল তারা কম্পোজিশনের মান পড়তে পারে যেখান থেকে আপনার UI ট্রিতে মডিফায়ার ব্যবহার করা হয়েছে, যেখানে মডিফায়ার বরাদ্দ করা হয়েছে, currentValueOf ব্যবহার করে।

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

এই উদাহরণটি LocalContentColor এর রঙের উপর ভিত্তি করে একটি পটভূমি আঁকার মান পর্যবেক্ষণ করে। যেহেতু ContentDrawScope স্ন্যাপশট পরিবর্তনগুলি পর্যবেক্ষণ করে, এটি স্বয়ংক্রিয়ভাবে পুনরায় আঁকা হয় যখন LocalContentColor এর মান পরিবর্তন হয়:

class BackgroundColorConsumerNode :
    Modifier.Node(),
    DrawModifierNode,
    CompositionLocalConsumerModifierNode {
    override fun ContentDrawScope.draw() {
        val currentColor = currentValueOf(LocalContentColor)
        drawRect(color = currentColor)
        drawContent()
    }
}

একটি সুযোগের বাইরে রাষ্ট্রীয় পরিবর্তনগুলিতে প্রতিক্রিয়া জানাতে এবং আপনার সংশোধককে স্বয়ংক্রিয়ভাবে আপডেট করতে, একটি ObserverModifierNode ব্যবহার করুন।

উদাহরণস্বরূপ, Modifier.scrollable এই কৌশলটি LocalDensity পরিবর্তনগুলি পর্যবেক্ষণ করতে ব্যবহার করে। একটি সরলীকৃত উদাহরণ নীচে দেখানো হয়েছে:

class ScrollableNode :
    Modifier.Node(),
    ObserverModifierNode,
    CompositionLocalConsumerModifierNode {

    // Place holder fling behavior, we'll initialize it when the density is available.
    val defaultFlingBehavior = DefaultFlingBehavior(splineBasedDecay(UnityDensity))

    override fun onAttach() {
        updateDefaultFlingBehavior()
        observeReads { currentValueOf(LocalDensity) } // monitor change in Density
    }

    override fun onObservedReadsChanged() {
        // if density changes, update the default fling behavior.
        updateDefaultFlingBehavior()
    }

    private fun updateDefaultFlingBehavior() {
        val density = currentValueOf(LocalDensity)
        defaultFlingBehavior.flingDecay = splineBasedDecay(density)
    }
}

অ্যানিমেটিং মডিফায়ার

Modifier.Node বাস্তবায়নের একটি coroutineScope এ অ্যাক্সেস আছে। এটি কম্পোজ অ্যানিমেটেবল API ব্যবহার করার অনুমতি দেয়। উদাহরণ স্বরূপ, এই স্নিপেটটি CircleNode উপরে থেকে পরিবর্তন করে এবং বারবার বিবর্ণ হতে পারে:

class CircleNode(var color: Color) : Modifier.Node(), DrawModifierNode {
    private val alpha = Animatable(1f)

    override fun ContentDrawScope.draw() {
        drawCircle(color = color, alpha = alpha.value)
        drawContent()
    }

    override fun onAttach() {
        coroutineScope.launch {
            alpha.animateTo(
                0f,
                infiniteRepeatable(tween(1000), RepeatMode.Reverse)
            ) {
            }
        }
    }
}

প্রতিনিধিদল ব্যবহার করে সংশোধকদের মধ্যে ভাগ করা অবস্থা

Modifier.Node নোড মডিফায়াররা অন্য নোডগুলিতে অর্পণ করতে পারে৷ এটির জন্য অনেকগুলি ব্যবহারের ক্ষেত্রে রয়েছে, যেমন বিভিন্ন সংশোধক জুড়ে সাধারণ প্রয়োগগুলি বের করা, তবে এটি মডিফায়ার জুড়ে সাধারণ অবস্থা ভাগ করতেও ব্যবহার করা যেতে পারে।

উদাহরণস্বরূপ, একটি ক্লিকযোগ্য মডিফায়ার নোডের একটি মৌলিক বাস্তবায়ন যা ইন্টারঅ্যাকশন ডেটা ভাগ করে:

class ClickableNode : DelegatingNode() {
    val interactionData = InteractionData()
    val focusableNode = delegate(
        FocusableNode(interactionData)
    )
    val indicationNode = delegate(
        IndicationNode(interactionData)
    )
}

নোড স্বয়ংক্রিয়-অবৈধতা নির্বাচন করা

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

এটি বিশেষভাবে কার্যকর হতে পারে যদি আপনার কাস্টম সংশোধক বিন্যাস এবং অঙ্কন উভয়ই পরিবর্তন করে। স্বয়ংক্রিয়-অবৈধতা থেকে অপ্ট আউট করা আপনাকে শুধুমাত্র অঙ্কন-সম্পর্কিত বৈশিষ্ট্যগুলিকে অকার্যকর করতে দেয়, যেমন color , পরিবর্তন, এবং বিন্যাসকে অবৈধ না করে৷ এটি আপনার মডিফায়ারের কর্মক্ষমতা উন্নত করতে পারে।

এর একটি অনুমানমূলক উদাহরণ নীচে একটি মডিফায়ার সহ দেখানো হয়েছে যার বৈশিষ্ট্য হিসাবে একটি color , size এবং onClick lambda রয়েছে। এই সংশোধকটি শুধুমাত্র যা প্রয়োজন তা বাতিল করে, এবং যেটি নয় তা এড়িয়ে যায়:

class SampleInvalidatingNode(
    var color: Color,
    var size: IntSize,
    var onClick: () -> Unit
) : DelegatingNode(), LayoutModifierNode, DrawModifierNode {
    override val shouldAutoInvalidate: Boolean
        get() = false

    private val clickableNode = delegate(
        ClickablePointerInputNode(onClick)
    )

    fun update(color: Color, size: IntSize, onClick: () -> Unit) {
        if (this.color != color) {
            this.color = color
            // Only invalidate draw when color changes
            invalidateDraw()
        }

        if (this.size != size) {
            this.size = size
            // Only invalidate layout when size changes
            invalidateMeasurement()
        }

        // If only onClick changes, we don't need to invalidate anything
        clickableNode.update(onClick)
    }

    override fun ContentDrawScope.draw() {
        drawRect(color)
    }

    override fun MeasureScope.measure(
        measurable: Measurable,
        constraints: Constraints
    ): MeasureResult {
        val size = constraints.constrain(size)
        val placeable = measurable.measure(constraints)
        return layout(size.width, size.height) {
            placeable.place(0, 0)
        }
    }
}