اصول چیدمان را بنویسید

Jetpack Compose طراحی و ساخت رابط کاربری برنامه شما را بسیار ساده تر می کند. نوشتن حالت را به عناصر UI تبدیل می کند، از طریق:

  1. ترکیب عناصر
  2. چیدمان عناصر
  3. ترسیم عناصر

نوشتن حالت تبدیل به رابط کاربری از طریق ترکیب، چیدمان، طراحی

این سند بر روی چیدمان عناصر تمرکز دارد و برخی از بلوک‌های سازنده Compose را توضیح می‌دهد تا به شما در چیدمان عناصر UI خود کمک کند.

اهداف طرح‌بندی در Compose

پیاده سازی Jetpack Compose سیستم طرح بندی دو هدف اصلی دارد:

مبانی توابع ترکیبی

توابع Composable بلوک اصلی Compose هستند. یک تابع ترکیبی یک Unit ساطع کننده تابع است که بخشی از رابط کاربری شما را توصیف می کند. این تابع مقداری ورودی می گیرد و آنچه را که روی صفحه نمایش داده می شود تولید می کند. برای اطلاعات بیشتر در مورد Composable ها، نگاهی به مستندات مدل ذهنی Compose بیندازید.

یک تابع قابل ترکیب ممکن است چندین عنصر UI را منتشر کند. با این حال، اگر راهنمایی در مورد نحوه چیدمان آنها ارائه ندهید، Compose ممکن است عناصر را به گونه ای که شما دوست ندارید ترتیب دهد. به عنوان مثال، این کد دو عنصر متنی را تولید می کند:

@Composable
fun ArtistCard() {
    Text("Alfred Sisley")
    Text("3 minutes ago")
}

بدون راهنمایی در مورد نحوه چیدمان آنها، Compose عناصر متن را روی هم قرار می دهد و آنها را غیرقابل خواندن می کند:

دو عنصر متنی که روی هم کشیده شده اند و متن را غیرقابل خواندن می کند

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

اجزای چیدمان استاندارد

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

Column برای قرار دادن موارد به صورت عمودی روی صفحه استفاده کنید.

@Composable
fun ArtistCardColumn() {
    Column {
        Text("Alfred Sisley")
        Text("3 minutes ago")
    }
}

دو عنصر متن در یک طرح ستون مرتب شده اند، بنابراین متن قابل خواندن است

به طور مشابه، از Row برای قرار دادن موارد به صورت افقی روی صفحه استفاده کنید. هر دو Column و Row از پیکربندی هم ترازی عناصر موجود در آنها پشتیبانی می کنند.

@Composable
fun ArtistCardRow(artist: Artist) {
    Row(verticalAlignment = Alignment.CenterVertically) {
        Image(bitmap = artist.image, contentDescription = "Artist image")
        Column {
            Text(artist.name)
            Text(artist.lastSeenOnline)
        }
    }
}

طرح‌بندی پیچیده‌تر را با یک گرافیک کوچک در کنار ستونی از عناصر متن نشان می‌دهد

از Box برای قرار دادن عناصر روی دیگری استفاده کنید. Box همچنین از پیکربندی تراز خاصی از عناصر موجود در آن پشتیبانی می کند.

@Composable
fun ArtistAvatar(artist: Artist) {
    Box {
        Image(bitmap = artist.image, contentDescription = "Artist image")
        Icon(Icons.Filled.Check, contentDescription = "Check mark")
    }
}

دو عنصر را که روی هم چیده شده اند نشان می دهد

اغلب این بلوک های ساختمانی تنها چیزی است که شما نیاز دارید. می‌توانید تابع ترکیب‌پذیر خود را بنویسید تا این طرح‌بندی‌ها را در یک طرح‌بندی پیچیده‌تر که مناسب برنامه شما باشد، ترکیب کنید.

سه ترکیب طرح بندی ساده را با هم مقایسه می کند: ستون، ردیف و کادر

برای تنظیم موقعیت کودکان در یک Row ، آرگومان های horizontalArrangement و verticalAlignment را تنظیم کنید. برای یک Column ، آرگومان های verticalArrangement و horizontalAlignment را تنظیم کنید:

@Composable
fun ArtistCardArrangement(artist: Artist) {
    Row(
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.End
    ) {
        Image(bitmap = artist.image, contentDescription = "Artist image")
        Column { /*...*/ }
    }
}

موارد در سمت راست تراز شده اند

مدل چیدمان

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

به طور خلاصه، والدین قبل از فرزندان خود اندازه گیری می کنند، اما اندازه و بعد از فرزندان خود قرار می گیرند.

تابع SearchResult زیر را در نظر بگیرید.

@Composable
fun SearchResult() {
    Row {
        Image(
            // ...
        )
        Column {
            Text(
                // ...
            )
            Text(
                // ...
            )
        }
    }
}

این تابع درخت UI زیر را ایجاد می کند.

SearchResult
  Row
    Image
    Column
      Text
      Text

در مثال SearchResult ، طرح درختی UI از این ترتیب پیروی می کند:

  1. از گره ریشه Row خواسته می شود تا اندازه گیری کند.
  2. گره ریشه Row از فرزند اول خود، Image ، می خواهد که اندازه گیری کند.
  3. Image یک گره برگ است (یعنی فرزندی ندارد)، بنابراین اندازه را گزارش می‌کند و دستورالعمل‌های قرار دادن را برمی‌گرداند.
  4. گره ریشه Row از فرزند دوم خود، Column می خواهد که اندازه گیری کند.
  5. گره Column از اولین فرزند Text خود می خواهد که اندازه گیری کند.
  6. اولین گره Text یک گره برگ است، بنابراین اندازه را گزارش می کند و دستورالعمل های قرار دادن را برمی گرداند.
  7. گره Column از فرزند Text دوم خود می خواهد که اندازه گیری کند.
  8. گره Text دوم یک گره برگ است، بنابراین اندازه را گزارش می کند و دستورالعمل های قرار دادن را برمی گرداند.
  9. اکنون که گره Column اندازه گیری، اندازه گیری و فرزندان خود را قرار داده است، می تواند اندازه و مکان خود را تعیین کند.
  10. اکنون که گره ریشه Row اندازه گیری، اندازه و قرار دادن فرزندان خود را انجام داده است، می تواند اندازه و مکان خود را تعیین کند.

ترتیب اندازه گیری، اندازه، و قرار دادن در درخت UI نتایج جستجو

عملکرد

Compose تنها با یک بار اندازه گیری کودکان به عملکرد بالایی دست می یابد. اندازه‌گیری تک گذر برای عملکرد خوب است، و به Compose اجازه می‌دهد تا درخت‌های عمیق UI را به‌طور مؤثر مدیریت کند. اگر یک عنصر فرزند خود را دو بار اندازه گیری کند و آن کودک هر یک از فرزندان خود را دو بار و غیره اندازه گیری کند، یک تلاش برای چیدمان یک رابط کاربری کامل باید کار زیادی انجام دهد و عملکرد برنامه شما را سخت نگه می دارد.

اگر چیدمان شما به دلایلی به اندازه گیری های متعدد نیاز دارد، Compose یک سیستم ویژه، اندازه گیری های ذاتی را ارائه می دهد. می‌توانید در مورد این ویژگی در اندازه‌گیری‌های درونی در طرح‌بندی‌های Compose بیشتر بخوانید.

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

استفاده از اصلاح کننده ها در طرح بندی های خود

همانطور که در Compose Modifiers توضیح داده شد، می‌توانید از اصلاح‌کننده‌ها برای تزئین یا تقویت اجزای سازنده خود استفاده کنید. اصلاح کننده ها برای سفارشی کردن چیدمان شما ضروری هستند. به عنوان مثال، در اینجا ما چندین اصلاح کننده را برای سفارشی کردن ArtistCard زنجیره ای می کنیم:

@Composable
fun ArtistCardModifiers(
    artist: Artist,
    onClick: () -> Unit
) {
    val padding = 16.dp
    Column(
        Modifier
            .clickable(onClick = onClick)
            .padding(padding)
            .fillMaxWidth()
    ) {
        Row(verticalAlignment = Alignment.CenterVertically) { /*...*/ }
        Spacer(Modifier.size(padding))
        Card(
            elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
        ) { /*...*/ }
    }
}

طرح‌بندی پیچیده‌تر، با استفاده از اصلاح‌کننده‌ها برای تغییر نحوه چیدمان گرافیک و مناطقی که به ورودی کاربر پاسخ می‌دهند.

در کد بالا، به توابع مختلف اصلاح کننده توجه کنید که با هم استفاده می شوند.

  • clickable باعث می شود که یک composable به ورودی کاربر واکنش نشان دهد و یک موج را نشان دهد.
  • padding فضایی را در اطراف یک عنصر قرار می دهد.
  • fillMaxWidth باعث می‌شود که composable حداکثر عرضی که از والد به آن داده شده را پر کند.
  • size() عرض و ارتفاع مورد نظر یک عنصر را مشخص می کند.

طرح بندی های قابل پیمایش

درباره طرح‌بندی‌های قابل پیمایش در مستندات نوشتن حرکات بیشتر بیاموزید.

برای فهرست‌ها و فهرست‌های تنبل، مستندات نوشتن فهرست‌ها را بررسی کنید.

طرح بندی پاسخگو

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

محدودیت ها

برای دانستن محدودیت‌های والد و طراحی طرح‌بندی مطابق با آن، می‌توانید از BoxWithConstraints استفاده کنید. محدودیت های اندازه گیری را می توان در محدوده محتوای لامبدا یافت. می‌توانید از این محدودیت‌های اندازه‌گیری برای ایجاد طرح‌بندی‌های مختلف برای پیکربندی‌های مختلف صفحه استفاده کنید:

@Composable
fun WithConstraintsComposable() {
    BoxWithConstraints {
        Text("My minHeight is $minHeight while my maxWidth is $maxWidth")
    }
}

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

Compose طیف گسترده‌ای از قابلیت‌های ترکیب‌پذیر را بر اساس طراحی متریال با وابستگی androidx.compose.material:material (که هنگام ایجاد پروژه Compose در Android Studio گنجانده می‌شود) فراهم می‌کند تا ساخت UI آسان شود. عناصری مانند Drawer ، FloatingActionButton و TopAppBar همگی ارائه شده‌اند.

اجزای متریال از APIهای اسلات استفاده زیادی می‌کنند، الگویی که Compose معرفی می‌کند تا لایه‌ای از سفارشی‌سازی را در بالای اجزای سازنده ایجاد کند. این رویکرد مولفه ها را انعطاف پذیرتر می کند، زیرا آنها یک عنصر فرزند را می پذیرند که می تواند خودش را پیکربندی کند به جای اینکه مجبور باشد هر پارامتر پیکربندی فرزند را در معرض دید قرار دهد. اسلات ها یک فضای خالی در رابط کاربری ایجاد می کنند تا توسعه دهنده آن را به دلخواه پر کند. برای مثال، این اسلات‌هایی هستند که می‌توانید در یک TopAppBar سفارشی کنید:

نموداری که اسلات های موجود در نوار برنامه Material Components را نشان می دهد

Composable ها معمولاً یک content لامبدای قابل ترکیب را می گیرند ( content: @Composable () -> Unit ). Slot API ها چندین پارامتر content را برای کاربردهای خاص در معرض دید قرار می دهند. به عنوان مثال، TopAppBar به شما امکان می دهد محتوای title ، navigationIcon و actions را ارائه دهید.

به عنوان مثال، Scaffold به شما اجازه می دهد تا یک UI با ساختار طرح بندی اولیه Material Design پیاده سازی کنید. Scaffold اسلات هایی را برای متداول ترین اجزای متریال سطح بالا، مانند TopAppBar ، BottomAppBar ، FloatingActionButton و Drawer فراهم می کند. با استفاده از Scaffold ، به راحتی می توان مطمئن شد که این اجزا به درستی قرار گرفته اند و به درستی با هم کار می کنند.

برنامه نمونه JetNews که از Scaffold برای قرار دادن چندین عنصر استفاده می کند

@Composable
fun HomeScreen(/*...*/) {
    ModalNavigationDrawer(drawerContent = { /* ... */ }) {
        Scaffold(
            topBar = { /*...*/ }
        ) { contentPadding ->
            // ...
        }
    }
}

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