ضبط خصائص الحاوية

يمكنك تحديد إعدادات حاوية الشبكة لإنشاء تخطيطات مرنة تستجيب لأحجام الشاشات وأنواع المحتوى المختلفة. توضّح هذه الصفحة كيفية تنفيذ ما يلي:

  • تحديد شبكة: يمكنك إعداد البنية الأساسية للصفوف والأعمدة.
  • وضع العناصر في شبكة: تعرَّف على كيفية وضع العناصر في خلايا الشبكة وكيفية تغيير اتجاه التدفق.
  • إدارة حجم المسار: يمكنك استخدام الحجم الثابت والنسبة المئوية والمرن والداخلي لضبط أحجام المسارات.
  • ضبط الفواصل: يمكنك إدارة "الفواصل" بين الصفوف والأعمدة.

تحديد شبكة

تتكون الشبكة من أعمدة وصفوف. تحتوي الدالة المركّبة Grid على مَعلمة config تقبل دالة lambda لتحديد الأعمدة والصفوف ضمن GridConfigurationScope. يحدّد المثال التالي شبكة تتضمّن ثلاثة صفوف وعمودَين، لكلّ منها حجم ثابت محدّد في Dp:

Grid(
    config = {
        repeat(2) {
            column(160.dp)
        }
        repeat(3) {
            row(90.dp)
        }
    }
) {
}

وضع العناصر في شبكة

تأخذ دالة Grid عناصر في واجهة المستخدم في دالة lambda content وتضعها في خلايا الشبكة. تضع الشبكة العناصر بغض النظر عما إذا كنت قد حددت الصفوف والأعمدة بشكل صريح. يحاول Grid تلقائيًا وضع عنصر في واجهة المستخدم في خلية الشبكة المتاحة في الصف، وإذا لم يتمكّن من ذلك، يضعه في خلية شبكة متاحة في الصف التالي. إذا لم تكن هناك خلايا فارغة، ينشئ Grid صفًا جديدًا.

في المثال التالي، تحتوي الشبكة على ست خلايا وتضع بطاقة في كل منها (الشكل 1). يبلغ حجم كل خلية في الشبكة 160dp × 90dp، ما يجعل إجمالي حجم الشبكة 320dp × 270dp.

Grid(
    config = {
        repeat(2) {
            column(160.dp)
        }
        repeat(3) {
            row(90.dp)
        }
    }
) {
    Card1()
    Card2()
    Card3()
    Card4()
    Card5()
    Card6()
}

يتم وضع ست بطاقات في شبكة تحتوي على ثلاثة صفوف وعمودين.
الشكل 1 يتم وضع ست بطاقات في شبكة تحتوي على ثلاثة صفوف وعمودين.

لتغيير هذا الإعداد التلقائي إلى التعبئة حسب العمود، اضبط السمة flow على GridFlow.Column.

Grid(
    config = {
        repeat(2) {
            column(160.dp)
        }
        repeat(3) {
            row(90.dp)
        }
        gap(8.dp)
        flow = GridFlow.Column // Grid tries to place items to fill the column
    },
) {
    Card1()
    Card2()
    Card3()
    Card4()
    Card5()
    Card6()
}

تغيّر دالة التدفق اتجاه وضع العناصر.
الشكل 2 ‫GridFlow.Row (على اليمين) وGridFlow.Column (على اليسار)

إدارة حجم المسارات

يُشار إلى الصفوف والأعمدة معًا باسم مسار الشبكة. يمكنك تحديد حجم مسار الشبكة باستخدام إحدى الطرق التالية:

  • ثابت (Dp): يخصّص حجمًا معيّنًا (مثل column(180.dp)).
  • النسبة المئوية (Float): لتخصيص نسبة مئوية من إجمالي المساحة المتاحة من 0.0f إلى 1.0f (مثلاً، row(0.5f) لنسبة %50).
  • مرن (Fr): يوزّع المساحة المتبقية بشكل متناسب بعد احتساب المسارات الثابتة والنسبية. على سبيل المثال، إذا تم ضبط صفين على 1.fr و3.fr، سيحصل الأخير على% 75 من الارتفاع المتبقي.
  • Intrinsic: لتحديد حجم المسار استنادًا إلى المحتوى داخله لمزيد من المعلومات، يُرجى الاطّلاع على تحديد حجم مسار الشبكة بشكل جوهري.

يستخدم المثال التالي خيارات مختلفة لتحديد حجم المسار لتحديد ارتفاعات الصفوف:

Grid(
    config = {
        column(1f)

        row(100.dp)
        row(0.2f)
        row(1.fr)
        row(GridTrackSize.Auto)
    },
    modifier = Modifier.height(480.dp)
) {
    PastelRedCard("Fixed(100.dp)")
        PastelGreenCard("Percentage(0.2f)")
    PastelBlueCard("Flex(1.fr)")
        PastelYellowCard("Auto")

}

ارتفاعات الصفوف المحددة باستخدام خيارات حجم المسار الأساسية الأربعة.
الشكل 3 يتم تحديد ارتفاعات الصفوف باستخدام خيارات حجم المسار الأساسية الأربعة في Grid.

ضبط الحدّ الأدنى لحجم مسارات الشبكة المرنة

عندما لا تتوفّر مساحة متبقية في حاوية الشبكة، يمكن أن يتقلّص المسار المرن العادي إلى 0.dp. لتجنُّب ذلك وضمان عدم ضغط المحتوى، استخدِم GridTrackSize.MinMax لفرض حدّ أدنى صريح للحجم مع الحفاظ على مرونة المسار.

يخصّص المثال التالي ما لا يقل عن 100.dp للصف الأول:

Grid(
    config = {
        column(1f)
        // The first row has a minimum height of 100.dp and can expand to 
        // the half of the remaining space.
        row(GridTrackSize.MinMax(100.dp, 1.fr))
        // The second row takes the half of the remaining space.
        row(1.fr)
        // The third row has a fixed height of 200.dp.
        row(200.dp)
    },
    modifier = Modifier.size(360.dp) // Total grid height is 360.dp
) {
    PastelRedCard("MinMax(100.dp, 1.fr)")
        PastelGreenCard("Flex(1.fr)")
    PastelBlueCard("Fixed(200.dp)")
}

ارتفاعات الصفوف المحددة باستخدام خيارات حجم المسار الأساسية الأربعة.
الشكل 4. يبلغ ارتفاع الصف الأول 100.dp على الأقل.

ضبط الحد الأدنى لحجم مسار الشبكة لوضع القوائم الكسولة

تستعلم المسارات المرنة العادية تلقائيًا عن الأحجام الجوهرية للعناصر الفرعية لإنشاء حجم أساسي. ومع ذلك، يحظر Jetpack Compose طلب البحث عن الأحجام الأساسية لـ SubcomposeLayout، التي تدعم المكوّنات، مثل LazyColumn وLazyRow.

يؤدي وضع قائمة بطيئة داخل مسار مرن عادي إلى حدوث عطل في IllegalStateException. لوضع القوائم الكسولة بأمان داخل مسار شبكة مرن، استخدِم MinMax مع حد أدنى صريح للحجم (مثل 0.dp) لتجاوز مسار القياس الجوهري.

Grid(
    config = {
        column(1f)
        // The first row's height is determined by the height of the Text composable.
        row(GridTrackSize.Auto)
        // The second row occupies the remaining space, allowing the LazyColumn to scroll.
        row(GridTrackSize.MinMax(0.dp, 1.fr))

        gap(8.dp)
    },
    modifier = Modifier.size(width = 170.dp, height = 240.dp)
) {
    Text("LazyColumn in a Grid")
    // The LazyColumn is placed in the second row, filling the remaining space.
    LazyColumn(verticalArrangement = Arrangement.spacedBy(4.dp)) {
        items(100) { number ->
            PastelGreenCard("Card $number")
        }
    }
}

ارتفاعات الصفوف المحددة باستخدام خيارات حجم المسار الأساسية الأربعة.
الشكل 5 ‫LazyColumn في خلية شبكة

تحديد حجم مسار الشبكة بشكل جوهري

يمكنك استخدام الحجم الجوهري لـ Grid عندما تريد أن يتكيّف التنسيق مع المحتوى، بدلاً من فرض حجم ثابت على الحاوية. يتم تحديد حجم مسار الشبكة باستخدام القيم التالية:

  • GridTrackSize.MaxContent: يتم استخدام الحد الأقصى للحجم الأساسي للمحتوى (على سبيل المثال، يتم تحديد العرض من خلال الطول الكامل للنص في مجموعة نصية بدون التفاف).
  • GridTrackSize.MinContent: استخدام الحد الأدنى للحجم الجوهري للمحتوى (على سبيل المثال، يتم تحديد العرض من خلال أطول كلمة مفردة في مجموعة نصية).
  • GridTrackSize.Auto: استخدِم حجمًا مرنًا للمسار يتكيّف مع المساحة المتاحة. تعمل هذه السمة مثل MaxContent تلقائيًا، ولكنّها تصغّر محتواها وتلفّه ليتناسب مع الحاوية الرئيسية.

يضع المثال التالي نصين جنبًا إلى جنب. يتم تحديد حجم العمود للنص الأول من خلال الحد الأدنى المطلوب للعرض لعرض النص، ويعتمد عرض العمود الثاني على الحد الأقصى المطلوب لعرض النص.

Grid(
    config = {
        column(GridTrackSize.MinContent)
        column(GridTrackSize.MaxContent)
        row(1.0f)
    },
    modifier = Modifier.width(480.dp)
) {
    Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet.")
    Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet.")
}

الأحجام الأساسية المحدّدة في الأعمدة
الشكل 5 الأحجام الأساسية المحدّدة في الأعمدة

ضبط الفجوات بين الصفوف والأعمدة

بعد تحديد حجم مسارات الشبكة، يمكنك تعديل فجوة الشبكة لتحسين المسافات بين المسارات. يمكنك تحديد الفجوة بين الأعمدة باستخدام الدالة columnGap، والفجوة بين الصفوف باستخدام rowGap. في المثال التالي، هناك فجوة 16dp بين كل صف، وفجوة 8dp بين كل عمود (الشكل 5).

Grid(
    config = {
        repeat(2) {
            column(160.dp)
        }
        repeat(3) {
            row(90.dp)
        }
        rowGap(16.dp)
        columnGap(8.dp)
    }
) {
    Card1()
    Card2()
    Card3()
    Card4()
    Card5()
    Card6()
}

الفجوات بين الصفوف والأعمدة
الشكل 6. الفجوات بين الصفوف والأعمدة

يمكنك أيضًا استخدام الدالة المريحة gap لتحديد فجوات من حجم العمود والصف نفسه، ولتحديد أحجام الأعمدة والفجوات بشكل منفصل باستخدام دالة واحدة. يضيف الرمز التالي فجوات بحجم 8dp إلى الشبكة:

Grid(
    config = {
        repeat(2) {
            column(160.dp)
        }
        repeat(3) {
            row(90.dp)
        }
        gap(8.dp) // Equivalent to columnGap(8.dp) and rowGap(8.dp)
    }
) {
    Card1()
    Card2()
    Card3()
    Card4()
    Card5()
    Card6()
}

تحديد مناطق الشبكة باستخدام مناطق مُعنوَنة

تتيح لك المناطق المُسمّاة إرفاق أسماء بمجموعات من خلايا الشبكة، والتي تُسمى مناطق الشبكة. يمكنك استخدام هذه الأسماء بدلاً من فهارس الإحداثيات عند وضع عناصر في واجهة المستخدم في الشبكة.

هناك فائدتان رئيسيتان لاستخدام المناطق المُسمّاة في ما يتعلّق بسهولة قراءة الرمز البرمجي:

  • عند تحديد تخطيط الشبكة، يكون الغرض من المحتوى المتوقع وموضعه واضحًا.
  • عند إضافة المحتوى، يكون الغرض منه واضحًا.

لتنظيم التنسيقات المعقدة بوضوح، يمكنك فصل بنية الشبكة المادية عن موضع العناصر الفرعية من خلال تحديد مناطق الشبكة الدلالية.

داخل دالة lambda في config، استخدِم الدالة area في GridConfigurationScope لتسجيل المناطق المُسمّاة في الشبكة. يمكنك بعد ذلك تعيين دوال مركّبة فرعية لهذه المناطق باستخدام المُعدِّل gridItem مع معرّف المنطقة المقابل. تعمل الدالة area على ربط معرّف دلالي (مثل قيمة فئة enum أو مفتاح سلسلة) بمجموعة من إحداثيات الشبكة المادية. تستند خطوط الشبكة والفهارس إلى الرقم 1 (أي أنّ الصف الأول هو 1 والعمود الأول هو 1).

على سبيل المثال، يمكنك تحديد شبكة تحتوي على أربعة أرقام تعريف للمناطق:

/**
 * An enum representing the IDs for named areas within the grid.
 */
enum class GridAreaNames {
    Area1,
    Area2,
    Area3,
    Area4
}

أدخِل اسم المنطقة باستخدام المَعلمة areaId مع إحداثيات الخلايا وامتداداتها في المنطقة. يستخدم المُعدِّل gridItem السمة areaId كمفتاح لتعيين كل عنصر فرعي إلى منطقة الشبكة المخصّصة له، كما هو موضّح في المثال التالي:

Grid(
    config = {
        // Define a single column that takes all available width.
        repeat(2) { column(0.5f) }

        // Define four rows, each taking 25% of the total height.
        repeat(4) { row(0.25f) }

        // Define named grid areas by associating an areaId with specific row and column indices.
        // Row and column indices are 1-based.
        area(areaId = GridAreaNames.Area1, row = 1, column = 1, columnSpan = 2)
        area(areaId = GridAreaNames.Area2, row = 2, column = 1, rowSpan = 3)
        area(areaId = GridAreaNames.Area3, rows = 2..3, columns = 2..2)
        area(areaId = GridAreaNames.Area4, row = 4, column = 2)

        gap(4.dp)
    },
    modifier = Modifier.size(360.dp)
) {
    PastelRedCard(
        "Area 1",
        // Use Modifier.gridItem(areaId) to place this composable into the
        // grid area defined with the matching ID in the config block.
        modifier = Modifier.gridItem(areaId = GridAreaNames.Area1)
    )
    PastelGreenCard(
        "Area 2",
        modifier = Modifier.gridItem(areaId = GridAreaNames.Area2)
    )
    PastelBlueCard(
        "Area 3",
        modifier = Modifier.gridItem(areaId = GridAreaNames.Area3)
    )
    PastelYellowCard(
        "Area 4",
        modifier = Modifier.gridItem(areaId = GridAreaNames.Area4)
    )
}

باستخدام المناطق المُسمّاة، يمكنك إعادة تنظيم شبكة التصميم المادي أو تعديلها (على سبيل المثال، تغيير الصفوف أو الأعمدة أو أحجام المسارات) في دالة lambda config بدون الحاجة إلى تعديل ترتيب الدوال المركّبة الفرعية أو مَعلماتها.