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

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

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

تحديد شبكة

تتألف الشبكة من أعمدة وصفوف. يحتوي العنصر القابل للإنشاء 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()
}

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

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

لاستخدام المساحات المُسمّاة فائدتان رئيسيتان لتحسين إمكانية قراءة الرمز البرمجي:

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

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

داخل دالة config lambda، استخدِم الدالة 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)
    )
}

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