الفرق بين المراجعتين لصفحة: «ReactNative/flexbox»

من موسوعة حسوب
لا ملخص تعديل
لا ملخص تعديل
سطر 47: سطر 47:


اطّلع على المزيد من [https://yogalayout.com/docs/flex-direction/ الخاصية <code>flexDirection</code>].<syntaxhighlight lang="javascript">
اطّلع على المزيد من [https://yogalayout.com/docs/flex-direction/ الخاصية <code>flexDirection</code>].<syntaxhighlight lang="javascript">
import React, { Component } from 'react';
import React, { useState } from "react";
import { AppRegistry, View } from 'react-native';
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";


export default class FlexDirectionBasics extends Component {
const FlexDirectionBasics = () => {
   render() {
   const [flexDirection, setflexDirection] = useState("column");
     return (
 
       <View style={{flex: 1, flexDirection: 'row'}}>
  return (
         <View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} />
    <PreviewLayout
         <View style={{width: 50, height: 50, backgroundColor: 'skyblue'}} />
      label="flexDirection"
        <View style={{width: 50, height: 50, backgroundColor: 'steelblue'}} />
      values={["column", "row", "row-reverse", "column-reverse"]}
      </View>
      selectedValue={flexDirection}
    );
      setSelectedValue={setflexDirection}
  }
     >
       <View
        style={[styles.box, { backgroundColor: "powderblue" }]}
      />
      <View
        style={[styles.box, { backgroundColor: "skyblue" }]}
      />
      <View
         style={[styles.box, { backgroundColor: "steelblue" }]}
      />
    </PreviewLayout>
  );
};
 
const PreviewLayout = ({
  label,
  children,
  values,
  selectedValue,
  setSelectedValue,
}) => (
  <View style={{ padding: 10, flex: 1 }}>
    <Text style={styles.label}>{label}</Text>
    <View style={styles.row}>
      {values.map((value) => (
        <TouchableOpacity
          key={value}
          onPress={() => setSelectedValue(value)}
          style={[
            styles.button,
            selectedValue === value && styles.selected,
          ]}
        >
          <Text
            style={[
              styles.buttonLabel,
              selectedValue === value && styles.selectedLabel,
            ]}
          >
            {value}
          </Text>
         </TouchableOpacity>
      ))}
    </View>
    <View style={[styles.container, { [label]: selectedValue }]}>
      {children}
    </View>
  </View>
);
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 8,
    backgroundColor: "aliceblue",
  },
  box: {
    width: 50,
    height: 50,
  },
  row: {
    flexDirection: "row",
    flexWrap: "wrap",
  },
  button: {
    paddingHorizontal: 8,
    paddingVertical: 6,
    borderRadius: 4,
    backgroundColor: "oldlace",
    alignSelf: "flex-start",
    marginHorizontal: "1%",
    marginBottom: 6,
    minWidth: "48%",
    textAlign: "center",
  },
  selected: {
    backgroundColor: "coral",
    borderWidth: 0,
  },
  buttonLabel: {
    fontSize: 12,
    fontWeight: "500",
    color: "coral",
  },
  selectedLabel: {
    color: "white",
  },
  label: {
    textAlign: "center",
    marginBottom: 10,
    fontSize: 24,
  },
});
 
export default FlexDirectionBasics;
</syntaxhighlight>
 
== اتجاه التخطيط Layout Direction ==
تحدّد خاصية اتجاه التخطيط اتجاهَ توزيع الأبناء والنص ضمن تسلسلٍ هرمي، كما يؤثّر اتجاه التخطيط أيضًا على ما تشير إليه بداية <code>start</code> ونهاية <code>end</code> الأطراف. يحدّد React Native اتجاه التخطيط على القيمة LTR افتراضيًا، حيث تشير البداية <code>start</code> إلى اليسار وتشير النهاية <code>end</code> إلى اليمين في هذه الحالة.
 
* <code>LTR</code> (القيمة الافتراضية): يوضَع النص والأبناء من اليسار إلى اليمين باستخدام هذه القيمة، حيث تُطبَّق الهوامش والحاشية المُطبَّقة على بداية العنصر من الجانب الأيسر.
* <code>RTL</code>: يُوضَع النص والأبناء من اليمين إلى اليسار باستخدام هذه القيمة، حيث تُطبَّق الهوامش والحاشية المُطبَّقة على بداية العنصر من الجانب الأيمن.
<syntaxhighlight lang="javascript">
import React, { useState } from "react";
import { View, TouchableOpacity, Text, StyleSheet } from "react-native";
 
const DirectionLayout = () => {
  const [direction, setDirection] = useState("ltr");
 
  return (
    <PreviewLayout
      label="direction"
      selectedValue={direction}
      values={["ltr", "rtl"]}
      setSelectedValue={setDirection}>
      <View
        style={[styles.box, { backgroundColor: "powderblue" }]}
      />
      <View
        style={[styles.box, { backgroundColor: "skyblue" }]}
      />
      <View
        style={[styles.box, { backgroundColor: "steelblue" }]}
      />
    </PreviewLayout>
  );
};
};


// تخطّ هذا السطر إن كنت تستعمل أداة
const PreviewLayout = ({
// Create React Native App
  label,
AppRegistry.registerComponent('AwesomeProject', () => FlexDirectionBasics);
  children,
  values,
  selectedValue,
  setSelectedValue,
}) => (
  <View style={{ padding: 10, flex: 1 }}>
    <Text style={styles.label}>{label}</Text>
    <View style={styles.row}>
      {values.map((value) => (
        <TouchableOpacity
          key={value}
          onPress={() => setSelectedValue(value)}
          style={[
            styles.button,
            selectedValue === value && styles.selected,
          ]}
        >
          <Text
            style={[
              styles.buttonLabel,
              selectedValue === value && styles.selectedLabel,
            ]}
          >
            {value}
          </Text>
        </TouchableOpacity>
      ))}
    </View>
    <View style={[styles.container, { [label]: selectedValue }]}>
      {children}
    </View>
  </View>
);
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 8,
    backgroundColor: "aliceblue",
  },
  box: {
    width: 50,
    height: 50,
  },
  row: {
    flexDirection: "row",
    flexWrap: "wrap",
  },
  button: {
    paddingHorizontal: 8,
    paddingVertical: 6,
    borderRadius: 4,
    backgroundColor: "oldlace",
    alignSelf: "flex-start",
    marginHorizontal: "1%",
    marginBottom: 6,
    minWidth: "48%",
    textAlign: "center",
  },
  selected: {
    backgroundColor: "coral",
    borderWidth: 0,
  },
  buttonLabel: {
    fontSize: 12,
    fontWeight: "500",
    color: "coral",
  },
  selectedLabel: {
    color: "white",
  },
  label: {
    textAlign: "center",
    marginBottom: 10,
    fontSize: 24,
  },
});
 
export default DirectionLayout;
</syntaxhighlight>
</syntaxhighlight>


==الخاصية ‎<code>justifyContent</code>‎==
==الخاصية ‎<code>justifyContent</code>‎==
تُحدِّد الخاصية <code>justifyContent</code>‎ كيفيّة توزيع المسافة بين العناصر وحولها على امتداد المحور الرئيسي. هل تريد توزيع الأطفال بجوار بعضها بدءًا من بداية المحور الرئيسي، أو المركز، أو في النهاية، أو متباعدةً بالتساوي؟ الخيارات المتاحة هي ‎<code>flex-start</code>‎، و‎<code>center</code>‎، و‎<code>flex-end</code>‎، و‎<code>space-around</code>‎، و‎<code>space-between</code>‎، ‎<code>space-evenly</code>. جرّب تعديل قيمة الخاصيّة ‎<code>justifyContent</code>‎ وانظر النتيجة لتفهم آلية التنسيق، يُمكنك كذلك تغيير قيمة ‎<code>flexDirection</code>‎ إلى ‎<code>row</code>‎ لتفهم أكثر:
تحدّد الخاصية <code>[[ReactNative/layout props#justifyContent|justifyContent]]</code> كيفية محاذاة المكونات الأبناء وفق محور الحاوية الرئيسي، حيث يمكنك استخدام هذه الخاصية لتوسيط ابنٍ أفقيًا ضمن حاوية مع ضبط الخاصية <code>flexDirection</code> على القيمة <code>row</code> أو عموديًا ضمن حاوية مع ضبط الخاصية <code>flexDirection</code> على القيمة <code>column</code>.


<syntaxhighlight lang="javascript">
* <code>flex-start</code> (القيمة الافتراضية): تحاذي أبناء الحاوية إلى بداية محور الحاوية الرئيسي.
import React, { Component } from 'react';
* <code>flex-end</code>: تحاذي هذه القيمة الحاوية إلى نهاية محور الحاوية الرئيسي.
import { AppRegistry, View } from 'react-native';
* <code>center</code>: تحاذي أبناء الحاوية إلى مركز محور الحاوية الرئيسي.
* <code>space-between</code>: تكون المسافة بين الأبناء متساوية على طول محور الحاوية الرئيسي، وتُوزَّع المسافة المتبقية بين الأبناء.
* <code>space-around</code>: تكون المسافة متساوية بين الأبناء على طول محور الحاوية الرئيسي، وتُوزَّع المسافة المتبقية حول الأبناء، فإن استخدام القيمة <code>space-around</code> سيؤدي إلى توزيع المسافة المتبقية على بداية الابن الأول ونهاية الابن الأخير بالموازنة مع <code>space-between</code>.
* <code>space-evenly</code>: يُوزَّع الأبناء بمسافة متساوية ضمن حاوية المحاذاة على طول المحور الرئيسي. التباعد بين كل زوج من العناصر المتجاورة، وطرف البداية الرئيسية والعنصر الأول، وطرف النهاية الرئيسية والعنصر الأخير، كلها متماثلة تمامًا.
 
اطّلع على المزيد من [https://yogalayout.com/docs/justify-content/ الخاصية <code>justifyContent</code>].<syntaxhighlight lang="javascript">
import React, { useState } from "react";
import { View, TouchableOpacity, Text, StyleSheet } from "react-native";
 
const JustifyContentBasics = () => {
  const [justifyContent, setJustifyContent] = useState("flex-start");


export default class JustifyContentBasics extends Component {
   return (
   render() {
     <PreviewLayout
     return (
      label="justifyContent"
       <View style={{
       selectedValue={justifyContent}
         flex: 1,
      values={[
         flexDirection: 'column',
        "flex-start",
         justifyContent: 'space-between',
         "flex-end",
       }}>
         "center",
        <View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} />
         "space-between",
        <View style={{width: 50, height: 50, backgroundColor: 'skyblue'}} />
        "space-around",
        <View style={{width: 50, height: 50, backgroundColor: 'steelblue'}} />
        "space-evenly",
      </View>
       ]}
    );
      setSelectedValue={setJustifyContent}
  }
    >
      <View
        style={[styles.box, { backgroundColor: "powderblue" }]}
      />
      <View
        style={[styles.box, { backgroundColor: "skyblue" }]}
      />
      <View
        style={[styles.box, { backgroundColor: "steelblue" }]}
      />
    </PreviewLayout>
  );
};
};


// تخطّ هذا السطر إن كنت تستعمل أداة
const PreviewLayout = ({
// Create React Native App
  label,
AppRegistry.registerComponent('AwesomeProject', () => JustifyContentBasics);
  children,
  values,
  selectedValue,
  setSelectedValue,
}) => (
  <View style={{ padding: 10, flex: 1 }}>
    <Text style={styles.label}>{label}</Text>
    <View style={styles.row}>
      {values.map((value) => (
        <TouchableOpacity
          key={value}
          onPress={() => setSelectedValue(value)}
          style={[styles.button, selectedValue === value && styles.selected]}
        >
          <Text
            style={[
              styles.buttonLabel,
              selectedValue === value && styles.selectedLabel,
            ]}
          >
            {value}
          </Text>
        </TouchableOpacity>
      ))}
    </View>
    <View style={[styles.container, { [label]: selectedValue }]}>
      {children}
    </View>
  </View>
);
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 8,
    backgroundColor: "aliceblue",
  },
  box: {
    width: 50,
    height: 50,
  },
  row: {
    flexDirection: "row",
    flexWrap: "wrap",
  },
  button: {
    paddingHorizontal: 8,
    paddingVertical: 6,
    borderRadius: 4,
    backgroundColor: "oldlace",
    alignSelf: "flex-start",
    marginHorizontal: "1%",
    marginBottom: 6,
    minWidth: "48%",
    textAlign: "center",
  },
  selected: {
    backgroundColor: "coral",
    borderWidth: 0,
  },
  buttonLabel: {
    fontSize: 12,
    fontWeight: "500",
    color: "coral",
  },
  selectedLabel: {
    color: "white",
  },
  label: {
    textAlign: "center",
    marginBottom: 10,
    fontSize: 24,
  },
});
 
export default JustifyContentBasics;
</syntaxhighlight>
</syntaxhighlight>
==الخاصية ‎<code>alignItems</code>‎==
==الخاصية ‎<code>alignItems</code>‎==
تؤدي إضافة ‎<code>alignItems</code>‎ إلى نمطِ مكونٍ إلى تحديد محاذاة الأطفال على طول المحور الثانوي (إذا كان المحور الأساسي صفًا (‎<code>row</code>‎)، فسيكون المحور الثانوي هو العمود (‎<code>column</code>‎) والعكس صحيح). هل تريد مُحاذاة الأطفال في البداية، أو المركز، أو النهاية، أو أن تمتدّ لملء المساحة؟ الخيارات المتاحة هي ‎<code>flex-start</code>‎، و‎<code>center</code>‎، و‎<code>flex-end</code>‎، و‎<code>stretch</code>‎.
تحدّد الخاصية <code>alignItems</code> كيفية محاذاة الأبناء وفق محور الحاوية المتعامد مع المحور الرئيسي. تتشابه محاذاة العناصر إلى حد كبير مع الخاصية <code>justifyContent</code> ولكن تُطبَّق الخاصية <code>alignItems</code> على المحور المتعامد مع المحور الرئيسي cross axis بدلًا من تطبيقها على المحور الرئيسي main axis.


'''ملاحظة:''' ليكون للخاصيّة ‎<code>stretch</code>‎ (التي تتحكّم بالتمدّد) تأثير، يجب ألا يكون للأطفال بعدٌ ثابت على طول المحور الثانوي. في المثال التالي، ضبط ‎<code>alignItems: stretch</code>‎ لا تأثير له حتى تُزالَ القيمة ‎<code>width: 50</code>‎ من الأطفال (جرّب تغيير مختلف القيم وانظر النّتيجة):
<code>stretch</code> (القيمة الافتراضية): يمتد أبناء الحاوية للتطابق مع ارتفاع <code>height</code> محور الحاوية المتعامد مع المحور الرئيسي.
<syntaxhighlight lang="javascript">
 
import React, { Component } from 'react';
<code>flex-start</code>: تحاذي هذه القيمة أبناء الحاوية مع بداية محور الحاوية المتعامد مع المحور الرئيسي.
import { AppRegistry, View } from 'react-native';
 
<code>flex-end</code>: تحاذي هذه القيمة أبناء الحاوية إلى نهاية محور الحاوية المتعامد مع المحور الرئيسي.
 
<code>center</code>: تحاذي هذه القيمة أبناء الحاوية إلى مركز محور الحاوية المتعامد مع المحور الرئيسي.
 
<code>baseline</code>: تحاذي هذه القيمة أبناء الحاوية على طول خط الأساس baseline المشترك، إذ يمكن ضبط الأبناء ليكونوا خط الأساس المرجعي لآبائهم.<blockquote>'''ملاحظة:''' يجب ألا يكون للأبناء بُعد ثابت على طول المحور الثانوي، ليكون للخاصيّة ‎<code>stretch</code>‎ (التي تتحكّم بالتمدّد) تأثير، فضبط القيمة ‎<code>alignItems: stretch</code>‎ في المثال التالي لا تأثير له حتى تُزالَ القيمة ‎<code>width: 50</code>‎ من الأبناء.</blockquote>اطّلع على المزيد من [https://yogalayout.com/docs/align-items/ الخاصية <code>alignItems</code>].<syntaxhighlight lang="javascript">
import React, { useState } from "react";
import {
  View,
  TouchableOpacity,
  Text,
  StyleSheet,
} from "react-native";
 
const AlignItemsLayout = () => {
  const [alignItems, setAlignItems] = useState("stretch");
 
  return (
    <PreviewLayout
      label="alignItems"
      selectedValue={alignItems}
      values={[
        "stretch",
        "flex-start",
        "flex-end",
        "center",
        "baseline",
      ]}
      setSelectedValue={setAlignItems}
    >
      <View
        style={[styles.box, { backgroundColor: "powderblue" }]}
      />
      <View
        style={[styles.box, { backgroundColor: "skyblue" }]}
      />
      <View
        style={[
          styles.box,
          {
            backgroundColor: "steelblue",
            width: "auto",
            minWidth: 50,
          },
        ]}
      />
    </PreviewLayout>
  );
};
 
const PreviewLayout = ({
  label,
  children,
  values,
  selectedValue,
  setSelectedValue,
}) => (
  <View style={{ padding: 10, flex: 1 }}>
    <Text style={styles.label}>{label}</Text>
    <View style={styles.row}>
      {values.map((value) => (
        <TouchableOpacity
          key={value}
          onPress={() => setSelectedValue(value)}
          style={[
            styles.button,
            selectedValue === value && styles.selected,
          ]}
        >
          <Text
            style={[
              styles.buttonLabel,
              selectedValue === value &&
                styles.selectedLabel,
            ]}
          >
            {value}
          </Text>
        </TouchableOpacity>
      ))}
    </View>
    <View
      style={[
        styles.container,
        { [label]: selectedValue },
      ]}
    >
      {children}
    </View>
  </View>
);
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 8,
    backgroundColor: "aliceblue",
    minHeight: 200,
  },
  box: {
    width: 50,
    height: 50,
  },
  row: {
    flexDirection: "row",
    flexWrap: "wrap",
  },
  button: {
    paddingHorizontal: 8,
    paddingVertical: 6,
    borderRadius: 4,
    backgroundColor: "oldlace",
    alignSelf: "flex-start",
    marginHorizontal: "1%",
    marginBottom: 6,
    minWidth: "48%",
    textAlign: "center",
  },
  selected: {
    backgroundColor: "coral",
    borderWidth: 0,
  },
  buttonLabel: {
    fontSize: 12,
    fontWeight: "500",
    color: "coral",
  },
  selectedLabel: {
    color: "white",
  },
  label: {
    textAlign: "center",
    marginBottom: 10,
    fontSize: 24,
  },
});
 
export default AlignItemsLayout;
</syntaxhighlight>
 
== الخاصية <code>alignSelf</code> ==
تتمتع الخاصية <code>[[ReactNative/layout props#alignSelf|alignSelf]]</code> بنفس خيارات وتأثير الخاصية <code>alignItems</code>، ولكن يمكنك تطبيق الخاصية <code>alignSelf</code> على ابن واحد لتغيير محاذاته ضمن الأب، بدلًا من التأثير على الأبناء ضمن الحاوية. تعدّل الخاصية <code>alignSelf</code> أيّ خيار ضبطه الأب باستخدام الخاصية <code>alignItems</code>.<syntaxhighlight lang="javascript">
import React, { useState } from "react";
import { View, TouchableOpacity, Text, StyleSheet } from "react-native";
 
const AlignSelfLayout = () => {
  const [alignSelf, setAlignSelf] = useState("stretch");


export default class AlignItemsBasics extends Component {
   return (
   render() {
     <PreviewLayout
     return (
       label="alignSelf"
       // Try setting `alignItems` to 'flex-start'
       selectedValue={alignSelf}
       // Try setting `justifyContent` to `flex-end`.
       values={["stretch", "flex-start", "flex-end", "center", "baseline"]}
      // Try setting `flexDirection` to `row`.
       setSelectedValue={setAlignSelf}>
       <View style={{
         <View
        flex: 1,
          style={[styles.box, {
        flexDirection: 'column',
            alignSelf,
        justifyContent: 'center',
            width: "auto",
        alignItems: 'stretch',
            minWidth: 50,
       }}>
            backgroundColor: "powderblue",
         <View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} />
          }]}
        <View style={{height: 50, backgroundColor: 'skyblue'}} />
        />
        <View style={{height: 100, backgroundColor: 'steelblue'}} />
      <View
      </View>
        style={[styles.box, { backgroundColor: "skyblue" }]}
    );
      />
  }
      <View
        style={[styles.box, { backgroundColor: "steelblue" }]}
      />
    </PreviewLayout>
  );
};
};


// تخطّ هذا السطر إن كنت تستعمل أداة
const PreviewLayout = ({
// Create React Native App
  label,
AppRegistry.registerComponent('AwesomeProject', () => AlignItemsBasics);
  children,
  values,
  selectedValue,
  setSelectedValue,
}) => (
  <View style={{ padding: 10, flex: 1 }}>
    <Text style={styles.label}>{label}</Text>
    <View style={styles.row}>
      {values.map((value) => (
        <TouchableOpacity
          key={value}
          onPress={() => setSelectedValue(value)}
          style={[
            styles.button,
            selectedValue === value && styles.selected,
          ]}
        >
          <Text
            style={[
              styles.buttonLabel,
              selectedValue === value &&
                styles.selectedLabel,
            ]}
          >
            {value}
          </Text>
        </TouchableOpacity>
      ))}
    </View>
    <View style={styles.container}>
      {children}
    </View>
  </View>
);
 
const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 8,
    backgroundColor: "aliceblue",
    minHeight: 200,
  },
  box: {
    width: 50,
    height: 50,
  },
  row: {
    flexDirection: "row",
    flexWrap: "wrap",
  },
  button: {
    paddingHorizontal: 8,
    paddingVertical: 6,
    borderRadius: 4,
    backgroundColor: "oldlace",
    alignSelf: "flex-start",
    marginHorizontal: "1%",
    marginBottom: 6,
    minWidth: "48%",
    textAlign: "center",
  },
  selected: {
    backgroundColor: "coral",
    borderWidth: 0,
  },
  buttonLabel: {
    fontSize: 12,
    fontWeight: "500",
    color: "coral",
  },
  selectedLabel: {
    color: "white",
  },
  label: {
    textAlign: "center",
    marginBottom: 10,
    fontSize: 24,
  },
});
 
export default AlignSelfLayout;
</syntaxhighlight>
</syntaxhighlight>
== الخاصية <code>alignContent</code> ==


== المزيد من المعلومات==
== المزيد من المعلومات==

مراجعة 19:52، 28 يونيو 2021


التخطيط Layout باستخدام Flexbox

يمكن للمكوّن تحديد تخطيط أبنائه باستخدام خوارزمية Flexbox التي صُمِّمَت لتوفير تخطيط متناسق على أحجام شاشات مختلفة.

ستعتمد عادةً على كلّ من الخاصيّات ‎flexDirection‎، و‎alignItems‎، و‎justifyContent‎ للحصول على التصميم الصحيح.

يعمل Flexbox في React Native كما يعمل في CSS على الويب مع اختلافات طفيفة، حيث تختلف الإعدادات الافتراضية، إذ أنّ القيمة الافتراضيّة للخاصيّة ‎flexDirection‎ هي ‎column‎ عوضًا عن ‎row‎، والقيمة الافتراضيّة للخاصيّة ‎alignContent‎ هي ‎flex-start‎ عوضًا عن stretch‎، والقيمة الافتراضيّة للخاصيّة ‎flexShrink‎ هي ‎0‎ عوضًا عن 1‎، وخاصيّة ‎flex‎ لا تدعم إلّا عددًا واحدًا كقيمة.

الخاصية Flex

ستحدّد الخاصية flex كيف "تملأ" عناصرك المساحةَ المتاحة على طول المحور الرئيسي، حيث تُقسَم المساحة وفقًا للخاصية flex لكل عنصر.

تكون العروض views ذات اللون الأحمر والأصفر والأخضر في المثال التالي كلها عناصرًا أبناء في عرض الحاوية التي لها الخاصية flex: 1. يستخدم العرض ذو اللون الأحمر الخاصية flex: 1، ويستخدم العرض ذو اللون الأصفر الخاصية flex: 2، ويستخدم العرض ذو اللون الأخضر الخاصية flex: 3، أي 1 + 2 + 3 = 6، مما يعني أن العرض الأحمر سيحصل على 1/6 من المساحة، ويحصل العرض الأصفر على 2/6 من المساحة، والأخضر على 3/6 من اللمساحة.

import React from "react";
import { StyleSheet, Text, View } from "react-native";

const Flex = () => {
  return (
    <View style={[styles.container, {
      // ‫جرّب ضبط الخاصية flexDirection على القيمة row
      flexDirection: "column"
    }]}>
      <View style={{ flex: 1, backgroundColor: "red" }} />
      <View style={{ flex: 2, backgroundColor: "darkorange" }} />
      <View style={{ flex: 3, backgroundColor: "green" }} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
  },
});

export default Flex;

الخاصية flexDirection

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

  • column (القيمة الافتراضية): تحاذي هذه القيمة العناصر الأبناء من الأعلى إلى الأسفل. إذا كان الالتفاف wrapping مفعَّلًا، فسيبدأ السطر التالي على يمين العنصر الأول أعلى الحاوية.
  • row: تحاذي هذه القيمة العناصر الأبناء من اليسار إلى اليمين. إذا كان الالتفاف wrapping مفعَّلًا، فسيبدأ السطر التالي أسفل العنصر الأول على يسار الحاوية.
  • column-reverse: تحاذي هذه القيمة العناصر الأبناء من الأسفل إلى الأعلى. إذا كان الالتفاف wrapping مفعَّلًا، فسيبدأ السطر التالي على يمين العنصر الأول في أسفل الحاوية.
  • row-reverse: تحاذي هذه القيمة العناصر الأبناء من اليمين إلى اليسار. إذا كان الالتفاف wrapping مفعَّلًا، فسيبدأ السطر التالي أسفل العنصر الأول على يمين الحاوية.

اطّلع على المزيد من الخاصية flexDirection.

import React, { useState } from "react";
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";

const FlexDirectionBasics = () => {
  const [flexDirection, setflexDirection] = useState("column");

  return (
    <PreviewLayout
      label="flexDirection"
      values={["column", "row", "row-reverse", "column-reverse"]}
      selectedValue={flexDirection}
      setSelectedValue={setflexDirection}
    >
      <View
        style={[styles.box, { backgroundColor: "powderblue" }]}
      />
      <View
        style={[styles.box, { backgroundColor: "skyblue" }]}
      />
      <View
        style={[styles.box, { backgroundColor: "steelblue" }]}
      />
    </PreviewLayout>
  );
};

const PreviewLayout = ({
  label,
  children,
  values,
  selectedValue,
  setSelectedValue,
}) => (
  <View style={{ padding: 10, flex: 1 }}>
    <Text style={styles.label}>{label}</Text>
    <View style={styles.row}>
      {values.map((value) => (
        <TouchableOpacity
          key={value}
          onPress={() => setSelectedValue(value)}
          style={[
            styles.button,
            selectedValue === value && styles.selected,
          ]}
        >
          <Text
            style={[
              styles.buttonLabel,
              selectedValue === value && styles.selectedLabel,
            ]}
          >
            {value}
          </Text>
        </TouchableOpacity>
      ))}
    </View>
    <View style={[styles.container, { [label]: selectedValue }]}>
      {children}
    </View>
  </View>
);

const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 8,
    backgroundColor: "aliceblue",
  },
  box: {
    width: 50,
    height: 50,
  },
  row: {
    flexDirection: "row",
    flexWrap: "wrap",
  },
  button: {
    paddingHorizontal: 8,
    paddingVertical: 6,
    borderRadius: 4,
    backgroundColor: "oldlace",
    alignSelf: "flex-start",
    marginHorizontal: "1%",
    marginBottom: 6,
    minWidth: "48%",
    textAlign: "center",
  },
  selected: {
    backgroundColor: "coral",
    borderWidth: 0,
  },
  buttonLabel: {
    fontSize: 12,
    fontWeight: "500",
    color: "coral",
  },
  selectedLabel: {
    color: "white",
  },
  label: {
    textAlign: "center",
    marginBottom: 10,
    fontSize: 24,
  },
});

export default FlexDirectionBasics;

اتجاه التخطيط Layout Direction

تحدّد خاصية اتجاه التخطيط اتجاهَ توزيع الأبناء والنص ضمن تسلسلٍ هرمي، كما يؤثّر اتجاه التخطيط أيضًا على ما تشير إليه بداية start ونهاية end الأطراف. يحدّد React Native اتجاه التخطيط على القيمة LTR افتراضيًا، حيث تشير البداية start إلى اليسار وتشير النهاية end إلى اليمين في هذه الحالة.

  • LTR (القيمة الافتراضية): يوضَع النص والأبناء من اليسار إلى اليمين باستخدام هذه القيمة، حيث تُطبَّق الهوامش والحاشية المُطبَّقة على بداية العنصر من الجانب الأيسر.
  • RTL: يُوضَع النص والأبناء من اليمين إلى اليسار باستخدام هذه القيمة، حيث تُطبَّق الهوامش والحاشية المُطبَّقة على بداية العنصر من الجانب الأيمن.
import React, { useState } from "react";
import { View, TouchableOpacity, Text, StyleSheet } from "react-native";

const DirectionLayout = () => {
  const [direction, setDirection] = useState("ltr");

  return (
    <PreviewLayout
      label="direction"
      selectedValue={direction}
      values={["ltr", "rtl"]}
      setSelectedValue={setDirection}>
      <View
        style={[styles.box, { backgroundColor: "powderblue" }]}
      />
      <View
        style={[styles.box, { backgroundColor: "skyblue" }]}
      />
      <View
        style={[styles.box, { backgroundColor: "steelblue" }]}
      />
    </PreviewLayout>
  );
};

const PreviewLayout = ({
  label,
  children,
  values,
  selectedValue,
  setSelectedValue,
}) => (
  <View style={{ padding: 10, flex: 1 }}>
    <Text style={styles.label}>{label}</Text>
    <View style={styles.row}>
      {values.map((value) => (
        <TouchableOpacity
          key={value}
          onPress={() => setSelectedValue(value)}
          style={[
            styles.button,
            selectedValue === value && styles.selected,
          ]}
        >
          <Text
            style={[
              styles.buttonLabel,
              selectedValue === value && styles.selectedLabel,
            ]}
          >
            {value}
          </Text>
        </TouchableOpacity>
      ))}
    </View>
    <View style={[styles.container, { [label]: selectedValue }]}>
      {children}
    </View>
  </View>
);

const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 8,
    backgroundColor: "aliceblue",
  },
  box: {
    width: 50,
    height: 50,
  },
  row: {
    flexDirection: "row",
    flexWrap: "wrap",
  },
  button: {
    paddingHorizontal: 8,
    paddingVertical: 6,
    borderRadius: 4,
    backgroundColor: "oldlace",
    alignSelf: "flex-start",
    marginHorizontal: "1%",
    marginBottom: 6,
    minWidth: "48%",
    textAlign: "center",
  },
  selected: {
    backgroundColor: "coral",
    borderWidth: 0,
  },
  buttonLabel: {
    fontSize: 12,
    fontWeight: "500",
    color: "coral",
  },
  selectedLabel: {
    color: "white",
  },
  label: {
    textAlign: "center",
    marginBottom: 10,
    fontSize: 24,
  },
});

export default DirectionLayout;

الخاصية ‎justifyContent

تحدّد الخاصية justifyContent كيفية محاذاة المكونات الأبناء وفق محور الحاوية الرئيسي، حيث يمكنك استخدام هذه الخاصية لتوسيط ابنٍ أفقيًا ضمن حاوية مع ضبط الخاصية flexDirection على القيمة row أو عموديًا ضمن حاوية مع ضبط الخاصية flexDirection على القيمة column.

  • flex-start (القيمة الافتراضية): تحاذي أبناء الحاوية إلى بداية محور الحاوية الرئيسي.
  • flex-end: تحاذي هذه القيمة الحاوية إلى نهاية محور الحاوية الرئيسي.
  • center: تحاذي أبناء الحاوية إلى مركز محور الحاوية الرئيسي.
  • space-between: تكون المسافة بين الأبناء متساوية على طول محور الحاوية الرئيسي، وتُوزَّع المسافة المتبقية بين الأبناء.
  • space-around: تكون المسافة متساوية بين الأبناء على طول محور الحاوية الرئيسي، وتُوزَّع المسافة المتبقية حول الأبناء، فإن استخدام القيمة space-around سيؤدي إلى توزيع المسافة المتبقية على بداية الابن الأول ونهاية الابن الأخير بالموازنة مع space-between.
  • space-evenly: يُوزَّع الأبناء بمسافة متساوية ضمن حاوية المحاذاة على طول المحور الرئيسي. التباعد بين كل زوج من العناصر المتجاورة، وطرف البداية الرئيسية والعنصر الأول، وطرف النهاية الرئيسية والعنصر الأخير، كلها متماثلة تمامًا.

اطّلع على المزيد من الخاصية justifyContent.

import React, { useState } from "react";
import { View, TouchableOpacity, Text, StyleSheet } from "react-native";

const JustifyContentBasics = () => {
  const [justifyContent, setJustifyContent] = useState("flex-start");

  return (
    <PreviewLayout
      label="justifyContent"
      selectedValue={justifyContent}
      values={[
        "flex-start",
        "flex-end",
        "center",
        "space-between",
        "space-around",
        "space-evenly",
      ]}
      setSelectedValue={setJustifyContent}
    >
      <View
        style={[styles.box, { backgroundColor: "powderblue" }]}
      />
      <View
        style={[styles.box, { backgroundColor: "skyblue" }]}
      />
      <View
        style={[styles.box, { backgroundColor: "steelblue" }]}
      />
    </PreviewLayout>
  );
};

const PreviewLayout = ({
  label,
  children,
  values,
  selectedValue,
  setSelectedValue,
}) => (
  <View style={{ padding: 10, flex: 1 }}>
    <Text style={styles.label}>{label}</Text>
    <View style={styles.row}>
      {values.map((value) => (
        <TouchableOpacity
          key={value}
          onPress={() => setSelectedValue(value)}
          style={[styles.button, selectedValue === value && styles.selected]}
        >
          <Text
            style={[
              styles.buttonLabel,
              selectedValue === value && styles.selectedLabel,
            ]}
          >
            {value}
          </Text>
        </TouchableOpacity>
      ))}
    </View>
    <View style={[styles.container, { [label]: selectedValue }]}>
      {children}
    </View>
  </View>
);

const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 8,
    backgroundColor: "aliceblue",
  },
  box: {
    width: 50,
    height: 50,
  },
  row: {
    flexDirection: "row",
    flexWrap: "wrap",
  },
  button: {
    paddingHorizontal: 8,
    paddingVertical: 6,
    borderRadius: 4,
    backgroundColor: "oldlace",
    alignSelf: "flex-start",
    marginHorizontal: "1%",
    marginBottom: 6,
    minWidth: "48%",
    textAlign: "center",
  },
  selected: {
    backgroundColor: "coral",
    borderWidth: 0,
  },
  buttonLabel: {
    fontSize: 12,
    fontWeight: "500",
    color: "coral",
  },
  selectedLabel: {
    color: "white",
  },
  label: {
    textAlign: "center",
    marginBottom: 10,
    fontSize: 24,
  },
});

export default JustifyContentBasics;

الخاصية ‎alignItems

تحدّد الخاصية alignItems كيفية محاذاة الأبناء وفق محور الحاوية المتعامد مع المحور الرئيسي. تتشابه محاذاة العناصر إلى حد كبير مع الخاصية justifyContent ولكن تُطبَّق الخاصية alignItems على المحور المتعامد مع المحور الرئيسي cross axis بدلًا من تطبيقها على المحور الرئيسي main axis.

stretch (القيمة الافتراضية): يمتد أبناء الحاوية للتطابق مع ارتفاع height محور الحاوية المتعامد مع المحور الرئيسي.

flex-start: تحاذي هذه القيمة أبناء الحاوية مع بداية محور الحاوية المتعامد مع المحور الرئيسي.

flex-end: تحاذي هذه القيمة أبناء الحاوية إلى نهاية محور الحاوية المتعامد مع المحور الرئيسي.

center: تحاذي هذه القيمة أبناء الحاوية إلى مركز محور الحاوية المتعامد مع المحور الرئيسي.

baseline: تحاذي هذه القيمة أبناء الحاوية على طول خط الأساس baseline المشترك، إذ يمكن ضبط الأبناء ليكونوا خط الأساس المرجعي لآبائهم.

ملاحظة: يجب ألا يكون للأبناء بُعد ثابت على طول المحور الثانوي، ليكون للخاصيّة ‎stretch‎ (التي تتحكّم بالتمدّد) تأثير، فضبط القيمة ‎alignItems: stretch‎ في المثال التالي لا تأثير له حتى تُزالَ القيمة ‎width: 50‎ من الأبناء.

اطّلع على المزيد من الخاصية alignItems.

import React, { useState } from "react";
import {
  View,
  TouchableOpacity,
  Text,
  StyleSheet,
} from "react-native";

const AlignItemsLayout = () => {
  const [alignItems, setAlignItems] = useState("stretch");

  return (
    <PreviewLayout
      label="alignItems"
      selectedValue={alignItems}
      values={[
        "stretch",
        "flex-start",
        "flex-end",
        "center",
        "baseline",
      ]}
      setSelectedValue={setAlignItems}
    >
      <View
        style={[styles.box, { backgroundColor: "powderblue" }]}
      />
      <View
        style={[styles.box, { backgroundColor: "skyblue" }]}
      />
      <View
        style={[
          styles.box,
          {
            backgroundColor: "steelblue",
            width: "auto",
            minWidth: 50,
          },
        ]}
      />
    </PreviewLayout>
  );
};

const PreviewLayout = ({
  label,
  children,
  values,
  selectedValue,
  setSelectedValue,
}) => (
  <View style={{ padding: 10, flex: 1 }}>
    <Text style={styles.label}>{label}</Text>
    <View style={styles.row}>
      {values.map((value) => (
        <TouchableOpacity
          key={value}
          onPress={() => setSelectedValue(value)}
          style={[
            styles.button,
            selectedValue === value && styles.selected,
          ]}
        >
          <Text
            style={[
              styles.buttonLabel,
              selectedValue === value &&
                styles.selectedLabel,
            ]}
          >
            {value}
          </Text>
        </TouchableOpacity>
      ))}
    </View>
    <View
      style={[
        styles.container,
        { [label]: selectedValue },
      ]}
    >
      {children}
    </View>
  </View>
);

const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 8,
    backgroundColor: "aliceblue",
    minHeight: 200,
  },
  box: {
    width: 50,
    height: 50,
  },
  row: {
    flexDirection: "row",
    flexWrap: "wrap",
  },
  button: {
    paddingHorizontal: 8,
    paddingVertical: 6,
    borderRadius: 4,
    backgroundColor: "oldlace",
    alignSelf: "flex-start",
    marginHorizontal: "1%",
    marginBottom: 6,
    minWidth: "48%",
    textAlign: "center",
  },
  selected: {
    backgroundColor: "coral",
    borderWidth: 0,
  },
  buttonLabel: {
    fontSize: 12,
    fontWeight: "500",
    color: "coral",
  },
  selectedLabel: {
    color: "white",
  },
  label: {
    textAlign: "center",
    marginBottom: 10,
    fontSize: 24,
  },
});

export default AlignItemsLayout;

الخاصية alignSelf

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

import React, { useState } from "react";
import { View, TouchableOpacity, Text, StyleSheet } from "react-native";

const AlignSelfLayout = () => {
  const [alignSelf, setAlignSelf] = useState("stretch");

  return (
    <PreviewLayout
      label="alignSelf"
      selectedValue={alignSelf}
      values={["stretch", "flex-start", "flex-end", "center", "baseline"]}
      setSelectedValue={setAlignSelf}>
        <View
          style={[styles.box, {
            alignSelf,
            width: "auto",
            minWidth: 50,
            backgroundColor: "powderblue",
          }]}
        />
      <View
        style={[styles.box, { backgroundColor: "skyblue" }]}
      />
      <View
        style={[styles.box, { backgroundColor: "steelblue" }]}
      />
    </PreviewLayout>
  );
};

const PreviewLayout = ({
  label,
  children,
  values,
  selectedValue,
  setSelectedValue,
}) => (
  <View style={{ padding: 10, flex: 1 }}>
    <Text style={styles.label}>{label}</Text>
    <View style={styles.row}>
      {values.map((value) => (
        <TouchableOpacity
          key={value}
          onPress={() => setSelectedValue(value)}
          style={[
            styles.button,
            selectedValue === value && styles.selected,
          ]}
        >
          <Text
            style={[
              styles.buttonLabel,
              selectedValue === value &&
                styles.selectedLabel,
            ]}
          >
            {value}
          </Text>
        </TouchableOpacity>
      ))}
    </View>
    <View style={styles.container}>
      {children}
    </View>
  </View>
);

const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 8,
    backgroundColor: "aliceblue",
    minHeight: 200,
  },
  box: {
    width: 50,
    height: 50,
  },
  row: {
    flexDirection: "row",
    flexWrap: "wrap",
  },
  button: {
    paddingHorizontal: 8,
    paddingVertical: 6,
    borderRadius: 4,
    backgroundColor: "oldlace",
    alignSelf: "flex-start",
    marginHorizontal: "1%",
    marginBottom: 6,
    minWidth: "48%",
    textAlign: "center",
  },
  selected: {
    backgroundColor: "coral",
    borderWidth: 0,
  },
  buttonLabel: {
    fontSize: 12,
    fontWeight: "500",
    color: "coral",
  },
  selectedLabel: {
    color: "white",
  },
  label: {
    textAlign: "center",
    marginBottom: 10,
    fontSize: 24,
  },
});

export default AlignSelfLayout;

الخاصية alignContent

المزيد من المعلومات

هذه هي الأساسيات، لكن هناك عدّة أنماط أخرى قد تحتاج إليها لتخطيط تطبيقاتك. اطّلع على قائمة خاصيّات التخطيط الكاملة هنا.

اقتربنا من التمّكن من بناء تطبيق واقعيّ. لكن ما زلنا بحاجة إلى طريقة للحصول على مدخلات المستخدم ليتمكّن من التفاعل مع التطبيق، لذا سننتقل إلى تعلم كيفية التعامل مع إدخال النص بالمكون TextInput.

مصادر