اصلاح کننده ها را بنویسید

اصلاح کننده ها به شما این امکان را می دهند که یک ترکیب بندی را تزئین یا تقویت کنید. اصلاح‌کننده‌ها به شما اجازه می‌دهند این نوع کارها را انجام دهید:

  • اندازه، چیدمان، رفتار و ظاهر کامپوزیشن را تغییر دهید
  • اطلاعاتی مانند برچسب‌های دسترس‌پذیری را اضافه کنید
  • پردازش ورودی کاربر
  • فعل و انفعالات سطح بالا را اضافه کنید، مانند ایجاد یک عنصر قابل کلیک، قابل پیمایش، کشیدن، یا بزرگنمایی

اصلاح کننده ها اشیاء استاندارد Kotlin هستند. با فراخوانی یکی از توابع کلاس 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 باعث می‌شود که composable حداکثر عرضی که از والد به آن داده شده را پر کند.

بهترین روش این است که همه اجزای سازنده شما یک پارامتر modifier بپذیرند و آن اصلاح‌کننده را به اولین فرزند خود که UI منتشر می‌کند، ارسال کنید. انجام این کار کد شما را قابل استفاده مجدد تر می کند و رفتار آن را قابل پیش بینی تر و شهودی می کند. برای اطلاعات بیشتر، به دستورالعمل‌های Compose API مراجعه کنید، عناصر یک پارامتر Modifier را می‌پذیرند و رعایت می‌کنند .

ترتیب اصلاح کننده ها مهم است

ترتیب توابع اصلاح کننده قابل توجه است. از آنجایی که هر تابع تغییراتی را در Modifier برگردانده شده توسط تابع قبلی ایجاد می کند، دنباله روی نتیجه نهایی تأثیر می گذارد. بیایید نمونه ای از این را ببینیم:

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

کل ناحیه، از جمله لایه های اطراف لبه ها، به کلیک ها پاسخ می دهد

در کد بالا کل ناحیه قابل کلیک است، از جمله padding اطراف، زیرا اصلاح کننده padding بعد از اصلاح کننده clickable اعمال شده است. اگر ترتیب اصلاح‌کننده‌ها معکوس شود، فضای اضافه شده با padding به ورودی کاربر واکنش نشان نمی‌دهد:

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

بالشتک اطراف لبه طرح دیگر به کلیک ها پاسخ نمی دهد

اصلاح کننده های داخلی

Jetpack Compose فهرستی از اصلاح‌کننده‌های داخلی را ارائه می‌کند تا به شما کمک کند یک ترکیب‌سازی را تزئین یا تقویت کنید. در اینجا برخی از اصلاح‌کننده‌های رایج وجود دارد که از آنها برای تنظیم طرح‌بندی‌های خود استفاده می‌کنید.

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 در اطراف یک عنصر، یک اصلاح کننده padding تنظیم کنید.

اگر می خواهید 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 اندازه گیری آن را تغییر نمی دهد:

@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 reads را تا زمانی که ممکن است بخوانید.

ایمنی محدوده در Compose

در Compose، اصلاح‌کننده‌هایی وجود دارد که فقط زمانی می‌توان از آن‌ها استفاده کرد که برای فرزندان برخی از اجزای سازنده خاص اعمال شوند. نوشتن این مورد را با استفاده از محدوده های سفارشی اعمال می کند.

به عنوان مثال، اگر می‌خواهید کودکی را به بزرگی Box والد بدون تأثیر بر اندازه Box بسازید، از اصلاح کننده matchParentSize استفاده کنید. matchParentSize فقط در BoxScope موجود است. بنابراین، آن را فقط می توان بر روی یک فرزند در والد Box استفاده کرد.

ایمنی Scope شما را از اضافه کردن اصلاح‌کننده‌هایی که در سایر اجزای سازنده و محدوده‌ها کار نمی‌کنند جلوگیری می‌کند و باعث صرفه‌جویی در زمان از آزمون و خطا می‌شود.

اصلاح‌کننده‌های محدوده، اطلاعاتی را که والدین باید درباره کودک بدانند، به والدین اطلاع می‌دهند. اینها معمولاً به عنوان اصلاح کننده های داده والد نیز شناخته می شوند. داخلی آنها با اصلاح کننده های هدف کلی متفاوت است، اما از منظر استفاده، این تفاوت ها اهمیتی ندارند.

matchParentSize در Box

همانطور که در بالا ذکر شد، اگر می خواهید طرح فرزند به اندازه یک Box والد باشد بدون اینکه بر اندازه Box تأثیر بگذارد، از اصلاح کننده matchParentSize استفاده کنید.

توجه داشته باشید که matchParentSize فقط در محدوده Box در دسترس است، به این معنی که فقط برای فرزندان مستقیم Box composable اعمال می شود.

در مثال زیر، فرزند Spacer اندازه خود را از Box والد خود می گیرد، که به نوبه خود اندازه خود را از بزرگترین فرزندان، ArtistCard در این مورد می گیرد.

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

پس زمینه خاکستری ظرف آن را پر می کند

اگر از fillMaxSize به جای matchParentSize استفاده می شد، Spacer تمام فضای موجود مجاز را به والد می برد و به نوبه خود باعث می شود والد گسترش یابد و تمام فضای موجود را پر کند.

پس زمینه خاکستری که صفحه را پر می کند

weight در Row و Column

همانطور که در بخش قبلی در مورد Padding and size مشاهده کردید، به طور پیش‌فرض، اندازه قابل ترکیب با محتوایی که در آن قرار می‌گیرد تعریف می‌شود. می‌توانید با استفاده از weight اصلاح‌کننده که فقط در 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
    )
}

در عوض، می‌توانید همان نمونه اصلاح‌کننده را ایجاد، استخراج و دوباره استفاده کنید و آن را به composable ارسال کنید:

// 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 مراجعه کنید.

برای اطلاعات بیشتر در مورد اصلاح‌کننده‌های سفارشی و نحوه ایجاد آنها، نگاهی به مستندات طرح‌بندی‌های سفارشی بیاندازید - با استفاده از اصلاح‌کننده طرح .

{% کلمه به کلمه %} {% آخر کلمه %} {% کلمه به کلمه %} {% آخر کلمه %}