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

من موسوعة حسوب
أنشأ الصفحة ب'<noinclude>{{DISPLAYTITLE:LayoutAnimation في React Native}}</noinclude> تحرِّك الإظهارات لمواضعها الجديدة تلقائيًا عند تطب...'
 
طلا ملخص تعديل
 
(6 مراجعات متوسطة بواسطة مستخدمين اثنين آخرين غير معروضة)
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE:LayoutAnimation في React Native}}</noinclude>  
<noinclude>{{DISPLAYTITLE:الواجهة LayoutAnimation في React Native}}</noinclude>  
تحرِّك الإظهارات لمواضعها الجديدة تلقائيًا عند تطبيق التخطيط التاّلي.
تحرِّك الواجهات لمواضعها الجديدة تلقائيًا عند تطبيق التخطيط التالي.


إن الطّريقة المألوفة لاستخدام هذه الواجهة البرمجية هي استدعاؤها قبل تحديث خطاف الحالة (state hook) في المكوّنات الوظيفيّة (functional components)، واستدعاء <code>setState</code> ضمن مكونات الصنف.
تعدّ الطّريقة المألوفة لاستخدام هذه الواجهة البرمجية هي استدعاؤها قبل تحديث خطّاف الحالة (state hook) في المكوّنات الوظيفيّة (functional components)، واستدعاء <code>setState</code> ضمن مكونات الصنف.


يجب وضع الرّايات (flags) التّالية بواسطة <code>UIManager</code> لتعمل هذه الواجهة البرمجيّة على منصّة Android:<syntaxhighlight lang="javascript">
ويجب وضع الرّايات (flags) التّالية بواسطة <code>UIManager</code> لتعمل هذه الواجهة البرمجيّة على منصّة Android:<syntaxhighlight lang="javascript">
if (Platform.OS === 'android') {
if (Platform.OS === 'android') {
   if (UIManager.setLayoutAnimationEnabledExperimental) {
   if (UIManager.setLayoutAnimationEnabledExperimental) {
سطر 13: سطر 13:
__toc__
__toc__
== مثال ==
== مثال ==
<syntaxhighlight lang="javascript">
إليك المثال التالي ([https://snack.expo.dev/@hsoubwiki/layoutanimation تجربة حية]):<syntaxhighlight lang="javascript">
import React, { useState } from "react";
import React, { useState } from "react";
import { LayoutAnimation, Platform, StyleSheet, Text, TouchableOpacity, UIManager, View } from "react-native";
import { LayoutAnimation, Platform, StyleSheet, Text, TouchableOpacity, UIManager, View } from "react-native";
 
if (
if (
 Platform.OS === "android" &&
  Platform.OS === "android" &&
 UIManager.setLayoutAnimationEnabledExperimental
  UIManager.setLayoutAnimationEnabledExperimental
) {
) {
 UIManager.setLayoutAnimationEnabledExperimental(true);
  UIManager.setLayoutAnimationEnabledExperimental(true);
}
}
const App = () => {
const App = () => {
 const [expanded, setExpanded] = useState(false);
  const [expanded, setExpanded] = useState(false);
 
 return (
  return (
   <View style={style.container}>
    <View style={style.container}>
     <TouchableOpacity
      <TouchableOpacity
       onPress={() => {
        onPress={() => {
         LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
          LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
         setExpanded(!expanded);
          setExpanded(!expanded);
       }}
        }}
     >
      >
       <Text>Press me to {expanded ? "collapse" : "expand"}!</Text>
        <Text>Press me to {expanded ? "collapse" : "expand"}!</Text>
     </TouchableOpacity>
      </TouchableOpacity>
     {expanded && (
      {expanded && (
       <View style={style.tile}>
        <View style={style.tile}>
         <Text>I disappear sometimes!</Text>
          <Text>I disappear sometimes!</Text>
       </View>
        </View>
     )}
      )}
   </View>
    </View>
   );
   );
};
};
 
const style = StyleSheet.create({
const style = StyleSheet.create({
 tile: {
  tile: {
   backgroundColor: "lightgrey",
    backgroundColor: "lightgrey",
   borderWidth: 0.5,
    borderWidth: 0.5,
   borderColor: "#d6d7da"
    borderColor: "#d6d7da"
   },
   },
 container: {
  container: {
   flex: 1,
    flex: 1,
   justifyContent: "center",
    justifyContent: "center",
   alignItems: "center",
    alignItems: "center",
   overflow: "hidden"
    overflow: "hidden"
   }
   }
});
});
 
export default App;
export default App;
</syntaxhighlight>
</syntaxhighlight>
سطر 64: سطر 64:
== التوابع ==
== التوابع ==


=== <code>configureNext()</code> ===
=== <code>‎configureNext()</code> ===
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
static configureNext(config, onAnimationDidEnd?)
static configureNext(config, onAnimationDidEnd?)
</syntaxhighlight>يجدوِل الحركة لتحدُث في التخطيط التّالي.
</syntaxhighlight>يجدوِل الحركة لتحدُث في التخطيط التّالي.


==== المعاملات ====
المعاملات:
{| class="wikitable"
{| class="wikitable"
!الاسم
!الاسم
سطر 86: سطر 86:
|تُستدعى عند انتهاء الحركة، مدعومة فقط على منصة IOS
|تُستدعى عند انتهاء الحركة، مدعومة فقط على منصة IOS
|}
|}
المعامل <code>config</code>هو كائن مع المفاتيح الموضّحة في الأسفل، يعيد التابع <code>create()</code> كائنًا موافقًا للكائن <code>config</code>، ويمكن تمرير جميع كائنات الضّبط المسبق <code>Presets</code>، مثل: الكائن <code>config</code>.
المعامل <code>config</code> هو كائن مع المفاتيح الموضّحة في الأسفل، يعيد التابع <code>()create</code> كائنًا موافقًا للكائن <code>config</code>، ويمكن تمرير جميع كائنات الضّبط المسبق <code>Presets</code>، مثل: الكائن <code>config</code>.


* <code>duration</code>: المدّة الزّمنيّة بالميلي ثانية.
* <code>duration</code>: المدّة الزّمنيّة بالميلي ثانية.
* <code>create</code>: مكوّن <code>config</code> اختياريٌّ للتحريك في الإظهارات الجديدة.
* <code>create</code>: مكوّن ضبط <code>config</code> اختياريٌّ للتحريك في الواجهات الجديدة.
* <code>update</code>: مكوّن (config) اختياريٌّ للإظهارات المتحرّكة المحدَّثة.
* <code>update</code>: مكوّن ضبط (config) اختياريٌّ للواجهات المتحرّكة المحدَّثة.
* <code>delete</code>: مكوّن (config) اختياريٌّ للإظهارات المتحرّكة المحذوفة.
* <code>delete</code>: مكوّن ضبط (config) اختياريٌّ للواجهات المتحرّكة المحذوفة.


يتضمن المكوّن (config) الذي يمرّر إلى <code>create</code>، و<code>update</code>، و<code>delete</code> المفاتيح التالية:
يتضمن مكوّن الضبط (config) الذي يمرّر إلى <code>create</code>، و<code>update</code>، و<code>delete</code> المفاتيح التالية:


* <code>type</code>: نوع الحركة <code>animation type</code> التي ستستخدم.
* <code>type</code>: نوع الحركة <code>animation type</code> التي ستستخدم.
سطر 102: سطر 102:
* <code>duration</code>: (عددٌ، اختياريٌّ).
* <code>duration</code>: (عددٌ، اختياريٌّ).


=== <code>create()</code> ===
=== <code>‎create()</code> ===
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
static create(duration, type, creationProp)
static create(duration, type, creationProp)
</syntaxhighlight>هو تابعٌ مساعدٌ يُنشئ كائنًا يحوي الحقول (<code>create</code>, <code>update</code>, <code>delete</code>)، ليمرَّر للتابع <code>configureNext()</code>، حيث المُعامل <code>type</code> هو نوع الحركة <code>animation type</code>، والمُعامل <code>creationProp</code> هو خاصيّة التخطيط <code>layout property</code>.
</syntaxhighlight>هو تابعٌ مساعدٌ يُنشئ كائنًا يحوي الحقول (<code>create</code>, <code>update</code>, <code>delete</code>)، ليمرَّر للتابع <code>()‎configureNext</code>، حيث المُعامل <code>type</code> هو نوع الحركة <code>animation type</code>، والمُعامل <code>creationProp</code> هو خاصيّة التخطيط <code>layout property</code>.
 
==== مثال الاستخدام ====


* مثال لمكوِّن الدالّة (Function Component)
إليك مثال الاستخدام:
* [https://snack.expo.dev/@hsoubwiki/layoutanimation-function-component مثال لمكوِّن دالّة (Function Component)]
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
import React, { useState } from "react";
import React, { useState } from "react";
import {
import {
 View,
  View,
 Platform,
  Platform,
 UIManager,
  UIManager,
 LayoutAnimation,
  LayoutAnimation,
 StyleSheet,
  StyleSheet,
 Button
  Button
} from "react-native";
} from "react-native";
 
if (
if (
 Platform.OS === "android" &&
  Platform.OS === "android" &&
 UIManager.setLayoutAnimationEnabledExperimental
  UIManager.setLayoutAnimationEnabledExperimental
) {
) {
 UIManager.setLayoutAnimationEnabledExperimental(true);
  UIManager.setLayoutAnimationEnabledExperimental(true);
}
}
 
const App = () => {
const App = () => {
 const [boxPosition, setBoxPosition] = useState("left");
  const [boxPosition, setBoxPosition] = useState("left");
 
 const toggleBox = () => {
  const toggleBox = () => {
   LayoutAnimation.configureNext(
    LayoutAnimation.configureNext(
     LayoutAnimation.create(
      LayoutAnimation.create(
       500,
        500,
       LayoutAnimation.Types.spring,
        LayoutAnimation.Types.spring,
       LayoutAnimation.Properties.scaleXY
        LayoutAnimation.Properties.scaleXY
     )
      )
   );
    );
   setBoxPosition(boxPosition === "left" ? "right" : "left");
    setBoxPosition(boxPosition === "left" ? "right" : "left");
   };
   };
 
 return (
  return (
   <View style={styles.container}>
    <View style={styles.container}>
     <View style={styles.buttonContainer}>
      <View style={styles.buttonContainer}>
       <Button title="Toggle Layout" onPress={toggleBox} />
        <Button title="Toggle Layout" onPress={toggleBox} />
     </View>
      </View>
     <View
      <View
       style={[styles.box, boxPosition === "left" ? null : styles.moveRight]}
        style={[styles.box, boxPosition === "left" ? null : styles.moveRight]}
     />
      />
   </View>
    </View>
   );
   );
}
}
 
const styles = StyleSheet.create({
const styles = StyleSheet.create({
 container: {
  container: {
   flex: 1,
    flex: 1,
   alignItems: "flex-start",
    alignItems: "flex-start",
   justifyContent: "center"
    justifyContent: "center"
   },
   },
 box: {
  box: {
   height: 100,
    height: 100,
   width: 100,
    width: 100,
   borderRadius: 5,
    borderRadius: 5,
   margin: 8,
    margin: 8,
   backgroundColor: "blue"
    backgroundColor: "blue"
   },
   },
 moveRight: {
  moveRight: {
   alignSelf: "flex-end",
    alignSelf: "flex-end",
   height: 200,
    height: 200,
   width: 200
    width: 200
   },
   },
 buttonContainer: {
  buttonContainer: {
   alignSelf: "center"
    alignSelf: "center"
   }
   }
});
});
 
export default App;
export default App;
</syntaxhighlight>
</syntaxhighlight>


* مثال لمكوِّن الصنف (Class Component)
* [https://snack.expo.dev/@hsoubwiki/layoutanimation-class-component مثال لمكوِّن صنف (Class Component)]
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
import React, { Component } from "react";
import React, { Component } from "react";
import {
import {
 View,
  View,
 Platform,
  Platform,
 UIManager,
  UIManager,
 LayoutAnimation,
  LayoutAnimation,
 StyleSheet,
  StyleSheet,
 Button
  Button
} from "react-native";
} from "react-native";
 
if (
if (
 Platform.OS === "android" &&
  Platform.OS === "android" &&
 UIManager.setLayoutAnimationEnabledExperimental
  UIManager.setLayoutAnimationEnabledExperimental
) {
) {
 UIManager.setLayoutAnimationEnabledExperimental(true);
  UIManager.setLayoutAnimationEnabledExperimental(true);
}
}
 
class App extends Component {
class App extends Component {
 state = {
  state = {
   boxPosition: "left"
    boxPosition: "left"
   };
   };
 
 toggleBox = () => {
  toggleBox = () => {
   LayoutAnimation.configureNext(
    LayoutAnimation.configureNext(
     LayoutAnimation.create(
      LayoutAnimation.create(
       500,
        500,
       LayoutAnimation.Types.spring,
        LayoutAnimation.Types.spring,
       LayoutAnimation.Properties.scaleXY
        LayoutAnimation.Properties.scaleXY
     )
      )
   );
    );
   this.setState({
    this.setState({
     boxPosition: this.state.boxPosition === "left" ? "right" : "left"
      boxPosition: this.state.boxPosition === "left" ? "right" : "left"
   });
    });
   };
   };
 
 render() {
  render() {
   return (
    return (
     <View style={styles.container}>
      <View style={styles.container}>
       <View style={styles.buttonContainer}>
        <View style={styles.buttonContainer}>
         <Button title="Toggle Layout" onPress={this.toggleBox} />
          <Button title="Toggle Layout" onPress={this.toggleBox} />
       </View>
        </View>
       <View
        <View
         style={[
          style={[
           styles.box,
            styles.box,
           this.state.boxPosition === "left" ? null : styles.moveRight
            this.state.boxPosition === "left" ? null : styles.moveRight
         ]}
          ]}
       />
        />
     </View>
      </View>
   );
    );
   }
   }
}
}
 
const styles = StyleSheet.create({
const styles = StyleSheet.create({
 container: {
  container: {
   flex: 1,
    flex: 1,
   alignItems: "flex-start",
    alignItems: "flex-start",
   justifyContent: "center"
    justifyContent: "center"
   },
   },
 box: {
  box: {
   height: 100,
    height: 100,
   width: 100,
    width: 100,
   borderRadius: 5,
    borderRadius: 5,
   margin: 8,
    margin: 8,
   backgroundColor: "blue"
    backgroundColor: "blue"
   },
   },
 moveRight: {
  moveRight: {
   alignSelf: "flex-end",
    alignSelf: "flex-end",
   height: 200,
    height: 200,
   width: 200
    width: 200
   },
   },
 buttonContainer: {
  buttonContainer: {
   alignSelf: "center"
    alignSelf: "center"
   }
   }
});
});
 
export default App;
export default App;
</syntaxhighlight>
</syntaxhighlight>


== الخاصيّات ==
== الخاصيات ==


=== الأنواع ===
=== <code>Types</code> ===
تستخدم أنواع الحركات من القيم الاسمية (enumeration) في التابع <code>create()</code>، أو في التكوينات <code>create</code>، أو <code>update</code>، أو <code>delete</code> من أجل التابع <code>configureNext()</code>، (يمكن أن يستخدم،مثلًا:  LayoutAnimation.Types.easeIn)، وهذه الأنواع هي:
تستخدم أنواع الحركات من القيم المتعدّدة (enumeration) في التّابع <code>()‎create</code>، أو في المعامل <code>config</code> الذي يمرّر إلى <code>create</code>، أو <code>update</code>، أو <code>delete</code> من أجل التّابع <code>()configureNext</code>، (يمكن أن يستخدم، مثلًا<code>LayoutAnimation.Types.easeIn</code>)، وهذه الأنواع هي:


* <code>spring</code>
* <code>spring</code>
سطر 272: سطر 271:
* <code>keyboard</code>
* <code>keyboard</code>


=== الخاصيّات ===
=== <code>Properties</code> ===
خاصيات التّخطيط من القيم الاسمية (enumeration) المستخدمة في الحركات، وتستخدم في التابع <code>create()</code>، أو في التكوينات <code>create</code>، أو <code>update</code>، أو <code>delete</code> من أجل التابع <code>configureNext()</code>، (يمكن أن يستخدم مثلًا: LayoutAnimation.Properties.opacity)، وهذه الخاصيات هي:
خاصيات التّخطيط من القيم المتعدّدة (enumeration) المستخدمة في الحركات، وتستخدم في التّابع <code>()create</code>، أو في المعامل (config) الذي يمرّر إلى <code>create</code>، أو <code>update</code>، أو <code>delete</code> من أجل التّابع <code>()configureNext</code>، (يمكن أن يستخدم مثلًا: <code>LayoutAnimation.Properties.opacity</code>)، وهذه الخاصيات هي:


* <code>opacity</code>
* <code>opacity</code>
سطر 280: سطر 279:
* <code>scaleXY</code>
* <code>scaleXY</code>


=== Presets ===
=== <code>Presets</code> ===
وهي مجموعة من تكوينات الحركة المعرّفة مسبقًا، والتي تمرّر للتابع <code>configureNext()</code>.
وهي مجموعة من معاملات (أو مكونات ضبط config) حركةٍ معرّفةٍ مسبقًا، تمرّر للتّابع ‪.<code>configureNext()</code>
{| class="wikitable"
{| class="wikitable"
!كائن الضبط المسبق
!كائن الضبط المسبق
!القيمة
!القيمة
|-
|-
|<code>easeInEaseOut</code>
|easeInEaseOut
|create (300, 'easeInEaseOut', 'opacity')‎
|<syntaxhighlight lang="js">
create(300, 'easeInEaseOut', 'opacity')‎
</syntaxhighlight>
|-
|-
|<code>linear</code>
|linear
|create (500, 'linear', 'opacity')‎
|<syntaxhighlight lang="js">
create(500, 'linear', 'opacity')‎
</syntaxhighlight>
|-
|-
|<code>spring</code>
|spring
|{ duration: 700, create: { type: <code>linear</code>, property: <code>opacity</code> }, update: { type: <code>spring</code>, springDamping: 0.4 }, delete: { type: <code>linear</code>, ‎property: <code>opacity</code> } }‎‎‏‪‫
|<syntaxhighlight lang="js">
{ duration: 700, create: { type: 'linear', property: 'opacity' }, update: { type: 'spring', springDamping: 0.4 }, delete: { type: 'linear', property: 'opacity' } }‎
</syntaxhighlight>
|}
|}


==== <code>easeInEaseOut()</code>  ====
* <code>‫‏()‎easeInEaseOut</code>: يستدعي التّابع <code>()configureNext</code> مع <code>Presets.easeInEaseOut</code>.
يستدعي التابع <code>configureNext()</code> مع <code>Presets.easeInEaseOut</code>.
* <code>()liner</code>: يستدعي التّابع <code>()configureNext</code> مع <code>Presets.liner</code>.
* <code>()spring</code>: يستدعي التّابع <code>()configureNext</code> مع <code>Presets.spring</code>.


==== <code>liner()</code>  ====
إليك مثال الاستخدام التالي:
يستدعي التابع <code>configureNext()</code> مع <code>Presets.liner</code>.
* [https://snack.expo.dev/@hsoubwiki/layoutanimation-presets-function-component مثال لمكوِّن دالّة (Function Component)]
 
==== <code>spring()</code>  ====
يستدعي التابع <code>configureNext()</code> مع <code>Presets.spring</code>.
 
==== مثال الاستخدام ====
 
* مثال لمكوِّن الدالّة (Function Component)
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
import React, { useState } from "react";
import React, { useState } from "react";
import {
import {
 View,
  View,
 Platform,
  Platform,
 UIManager,
  UIManager,
 LayoutAnimation,
  LayoutAnimation,
 StyleSheet,
  StyleSheet,
 Button
  Button
} from "react-native";
} from "react-native";
 
if (
if (
 Platform.OS === "android" &&
  Platform.OS === "android" &&
 UIManager.setLayoutAnimationEnabledExperimental
  UIManager.setLayoutAnimationEnabledExperimental
) {
) {
 UIManager.setLayoutAnimationEnabledExperimental(true);
  UIManager.setLayoutAnimationEnabledExperimental(true);
}
}
 
const App = () => {
const App = () => {
 const [firstBoxPosition, setFirstBoxPosition] = useState("left");
  const [firstBoxPosition, setFirstBoxPosition] = useState("left");
 const [secondBoxPosition, setSecondBoxPosition] = useState("left");
  const [secondBoxPosition, setSecondBoxPosition] = useState("left");
 const [thirdBoxPosition, setThirdBoxPosition] = useState("left");
  const [thirdBoxPosition, setThirdBoxPosition] = useState("left");
 
 const toggleFirstBox = () => {
  const toggleFirstBox = () => {
   LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
   setFirstBoxPosition(firstBoxPosition === "left" ? "right" : "left");
    setFirstBoxPosition(firstBoxPosition === "left" ? "right" : "left");
   };
   };
 
 const toggleSecondBox = () => {
  const toggleSecondBox = () => {
   LayoutAnimation.configureNext(LayoutAnimation.Presets.linear);
    LayoutAnimation.configureNext(LayoutAnimation.Presets.linear);
   setSecondBoxPosition(secondBoxPosition === "left" ? "right" : "left");
    setSecondBoxPosition(secondBoxPosition === "left" ? "right" : "left");
   };
   };
 
 const toggleThirdBox = () => {
  const toggleThirdBox = () => {
   LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
    LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
   setThirdBoxPosition(thirdBoxPosition === "left" ? "right" : "left");
    setThirdBoxPosition(thirdBoxPosition === "left" ? "right" : "left");
   };
   };
 
 return (
  return (
   <View style={styles.container}>
    <View style={styles.container}>
     <View style={styles.buttonContainer}>
      <View style={styles.buttonContainer}>
       <Button title="EaseInEaseOut" onPress={toggleFirstBox} />
        <Button title="EaseInEaseOut" onPress={toggleFirstBox} />
     </View>
      </View>
     <View
      <View
       style={[
        style={[
         styles.box,
          styles.box,
         firstBoxPosition === "left" ? null : styles.moveRight
          firstBoxPosition === "left" ? null : styles.moveRight
       ]}
        ]}
     />
      />
     <View style={styles.buttonContainer}>
      <View style={styles.buttonContainer}>
       <Button title="Linear" onPress={toggleSecondBox} />
        <Button title="Linear" onPress={toggleSecondBox} />
     </View>
      </View>
     <View
      <View
       style={[
        style={[
         styles.box,
          styles.box,
         secondBoxPosition === "left" ? null : styles.moveRight
          secondBoxPosition === "left" ? null : styles.moveRight
       ]}
        ]}
     />
      />
     <View style={styles.buttonContainer}>
      <View style={styles.buttonContainer}>
       <Button title="Spring" onPress={toggleThirdBox} />
        <Button title="Spring" onPress={toggleThirdBox} />
     </View>
      </View>
     <View
      <View
       style={[
        style={[
         styles.box,
          styles.box,
         thirdBoxPosition === "left" ? null : styles.moveRight
          thirdBoxPosition === "left" ? null : styles.moveRight
       ]}
        ]}
     />
      />
   </View>
    </View>
   );
   );
}
}
 
const styles = StyleSheet.create({
const styles = StyleSheet.create({
 container: {
  container: {
   flex: 1,
    flex: 1,
   alignItems: "flex-start",
    alignItems: "flex-start",
   justifyContent: "center"
    justifyContent: "center"
   },
   },
 box: {
  box: {
   height: 100,
    height: 100,
   width: 100,
    width: 100,
   borderRadius: 5,
    borderRadius: 5,
   margin: 8,
    margin: 8,
   backgroundColor: "blue"
    backgroundColor: "blue"
   },
   },
 moveRight: {
  moveRight: {
   alignSelf: "flex-end"
    alignSelf: "flex-end"
   },
   },
 buttonContainer: {
  buttonContainer: {
   alignSelf: "center"
    alignSelf: "center"
   }
   }
});
});
 
export default App;
export default App;
</syntaxhighlight>
</syntaxhighlight>


* مثال لمكوِّن الصنف (Class Component)
* [https://snack.expo.dev/@hsoubwiki/layoutanimation-presets-class-component مثال لمكوِّن صنف (Class Component)]
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
import React, { Component } from "react";
import React, { Component } from "react";
import {
import {
 View,
  View,
 Platform,
  Platform,
 UIManager,
  UIManager,
 LayoutAnimation,
  LayoutAnimation,
 StyleSheet,
  StyleSheet,
 Button
  Button
} from "react-native";
} from "react-native";
 
if (
if (
 Platform.OS === "android" &&
  Platform.OS === "android" &&
 UIManager.setLayoutAnimationEnabledExperimental
  UIManager.setLayoutAnimationEnabledExperimental
) {
) {
 UIManager.setLayoutAnimationEnabledExperimental(true);
  UIManager.setLayoutAnimationEnabledExperimental(true);
}
}
 
class App extends Component {
class App extends Component {
 state = {
  state = {
   firstBoxPosition: "left",
    firstBoxPosition: "left",
   secondBoxPosition: "left",
    secondBoxPosition: "left",
   thirdBoxPosition: "left"
    thirdBoxPosition: "left"
   };
   };
 
 toggleFirstBox = () => {
  toggleFirstBox = () => {
   LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
   this.setState({
    this.setState({
     firstBoxPosition:
      firstBoxPosition:
       this.state.firstBoxPosition === "left" ? "right" : "left"
        this.state.firstBoxPosition === "left" ? "right" : "left"
   });
    });
   };
   };
 
 toggleSecondBox = () => {
  toggleSecondBox = () => {
   LayoutAnimation.configureNext(LayoutAnimation.Presets.linear);
    LayoutAnimation.configureNext(LayoutAnimation.Presets.linear);
   this.setState({
    this.setState({
     secondBoxPosition:
      secondBoxPosition:
       this.state.secondBoxPosition === "left" ? "right" : "left"
        this.state.secondBoxPosition === "left" ? "right" : "left"
   });
    });
   };
   };
 
 toggleThirdBox = () => {
  toggleThirdBox = () => {
   LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
    LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
   this.setState({
    this.setState({
     thirdBoxPosition:
      thirdBoxPosition:
       this.state.thirdBoxPosition === "left" ? "right" : "left"
        this.state.thirdBoxPosition === "left" ? "right" : "left"
   });
    });
   };
   };
 
 render() {
  render() {
   return (
    return (
     <View style={styles.container}>
      <View style={styles.container}>
       <View style={styles.buttonContainer}>
        <View style={styles.buttonContainer}>
         <Button title="EaseInEaseOut" onPress={this.toggleFirstBox} />
          <Button title="EaseInEaseOut" onPress={this.toggleFirstBox} />
       </View>
        </View>
       <View
        <View
         style={[
          style={[
           styles.box,
            styles.box,
           this.state.firstBoxPosition === "left" ? null : styles.moveRight
            this.state.firstBoxPosition === "left" ? null : styles.moveRight
         ]}
          ]}
       />
        />
       <View style={styles.buttonContainer}>
        <View style={styles.buttonContainer}>
         <Button title="Linear" onPress={this.toggleSecondBox} />
          <Button title="Linear" onPress={this.toggleSecondBox} />
       </View>
        </View>
       <View
        <View
         style={[
          style={[
           styles.box,
            styles.box,
           this.state.secondBoxPosition === "left" ? null : styles.moveRight
            this.state.secondBoxPosition === "left" ? null : styles.moveRight
         ]}
          ]}
       />
        />
       <View style={styles.buttonContainer}>
        <View style={styles.buttonContainer}>
         <Button title="Spring" onPress={this.toggleThirdBox} />
          <Button title="Spring" onPress={this.toggleThirdBox} />
       </View>
        </View>
       <View
        <View
         style={[
          style={[
           styles.box,
            styles.box,
           this.state.thirdBoxPosition === "left" ? null : styles.moveRight
            this.state.thirdBoxPosition === "left" ? null : styles.moveRight
         ]}
          ]}
       />
        />
     </View>
      </View>
   );
    );
   }
   }
}
}
 
const styles = StyleSheet.create({
const styles = StyleSheet.create({
 container: {
  container: {
   flex: 1,
    flex: 1,
   alignItems: "flex-start",
    alignItems: "flex-start",
   justifyContent: "center"
    justifyContent: "center"
   },
   },
 box: {
  box: {
   height: 100,
    height: 100,
   width: 100,
    width: 100,
   borderRadius: 5,
    borderRadius: 5,
   margin: 8,
    margin: 8,
   backgroundColor: "blue"
    backgroundColor: "blue"
   },
   },
 moveRight: {
  moveRight: {
   alignSelf: "flex-end"
    alignSelf: "flex-end"
   },
   },
 buttonContainer: {
  buttonContainer: {
   alignSelf: "center"
    alignSelf: "center"
   }
   }
});
});
 
export default App;
export default App;
</syntaxhighlight>
</syntaxhighlight>
سطر 516: سطر 515:
* [https://facebook.github.io/react-native/docs/layoutanimation صفحة LayoutAnimation في توثيق React Native الرسميّ]
* [https://facebook.github.io/react-native/docs/layoutanimation صفحة LayoutAnimation في توثيق React Native الرسميّ]
[[تصنيف:ReactNative]]
[[تصنيف:ReactNative]]
[[تصنيف:React Native API]]

المراجعة الحالية بتاريخ 14:13، 9 أكتوبر 2021

تحرِّك الواجهات لمواضعها الجديدة تلقائيًا عند تطبيق التخطيط التالي.

تعدّ الطّريقة المألوفة لاستخدام هذه الواجهة البرمجية هي استدعاؤها قبل تحديث خطّاف الحالة (state hook) في المكوّنات الوظيفيّة (functional components)، واستدعاء setState ضمن مكونات الصنف.

ويجب وضع الرّايات (flags) التّالية بواسطة UIManager لتعمل هذه الواجهة البرمجيّة على منصّة Android:

if (Platform.OS === 'android') {
  if (UIManager.setLayoutAnimationEnabledExperimental) {
    UIManager.setLayoutAnimationEnabledExperimental(true);
  }
}

مثال

إليك المثال التالي (تجربة حية):

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

if (
  Platform.OS === "android" &&
  UIManager.setLayoutAnimationEnabledExperimental
) {
  UIManager.setLayoutAnimationEnabledExperimental(true);
}
const App = () => {
  const [expanded, setExpanded] = useState(false);

  return (
    <View style={style.container}>
      <TouchableOpacity
        onPress={() => {
          LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
          setExpanded(!expanded);
        }}
      >
        <Text>Press me to {expanded ? "collapse" : "expand"}!</Text>
      </TouchableOpacity>
      {expanded && (
        <View style={style.tile}>
          <Text>I disappear sometimes!</Text>
        </View>
      )}
    </View>
  );
};

const style = StyleSheet.create({
  tile: {
    backgroundColor: "lightgrey",
    borderWidth: 0.5,
    borderColor: "#d6d7da"
  },
  container: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    overflow: "hidden"
  }
});

export default App;

التوابع

‎configureNext()‎

static configureNext(config, onAnimationDidEnd?)

يجدوِل الحركة لتحدُث في التخطيط التّالي.

المعاملات:

الاسم النوع مطلوب الوصف
config كائن (object) نعم انظر الوصف بالأسفل
onAnimationDidEnd دالة (function) لا تُستدعى عند انتهاء الحركة، مدعومة فقط على منصة IOS

المعامل config هو كائن مع المفاتيح الموضّحة في الأسفل، يعيد التابع ()create كائنًا موافقًا للكائن config، ويمكن تمرير جميع كائنات الضّبط المسبق Presets، مثل: الكائن config.

  • duration: المدّة الزّمنيّة بالميلي ثانية.
  • create: مكوّن ضبط config اختياريٌّ للتحريك في الواجهات الجديدة.
  • update: مكوّن ضبط (config) اختياريٌّ للواجهات المتحرّكة المحدَّثة.
  • delete: مكوّن ضبط (config) اختياريٌّ للواجهات المتحرّكة المحذوفة.

يتضمن مكوّن الضبط (config) الذي يمرّر إلى create، وupdate، وdelete المفاتيح التالية:

  • type: نوع الحركة animation type التي ستستخدم.
  • property: خاصيّة التّخطيط layout property (اختياريٌّ، لكنّه مطلوبٌ في create، وdelete).
  • springDamping: (عددٌ، اختياريٌّ، ويستخدم فقط مع type: Type.spring).
  • initialVelocity: (عددٌ، اختياريٌّ).
  • delay: (عددٌ، اختياريٌّ).
  • duration: (عددٌ، اختياريٌّ).

‎create()‎

static create(duration, type, creationProp)

هو تابعٌ مساعدٌ يُنشئ كائنًا يحوي الحقول (create, update, delete)، ليمرَّر للتابع ‏()‎configureNext، حيث المُعامل type هو نوع الحركة animation type، والمُعامل creationProp هو خاصيّة التخطيط layout property.

إليك مثال الاستخدام:

import React, { useState } from "react";
import {
  View,
  Platform,
  UIManager,
  LayoutAnimation,
  StyleSheet,
  Button
} from "react-native";

if (
  Platform.OS === "android" &&
  UIManager.setLayoutAnimationEnabledExperimental
) {
  UIManager.setLayoutAnimationEnabledExperimental(true);
}

const App = () => {
  const [boxPosition, setBoxPosition] = useState("left");

  const toggleBox = () => {
    LayoutAnimation.configureNext(
      LayoutAnimation.create(
        500,
        LayoutAnimation.Types.spring,
        LayoutAnimation.Properties.scaleXY
      )
    );
    setBoxPosition(boxPosition === "left" ? "right" : "left");
  };

  return (
    <View style={styles.container}>
      <View style={styles.buttonContainer}>
        <Button title="Toggle Layout" onPress={toggleBox} />
      </View>
      <View
        style={[styles.box, boxPosition === "left" ? null : styles.moveRight]}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: "flex-start",
    justifyContent: "center"
  },
  box: {
    height: 100,
    width: 100,
    borderRadius: 5,
    margin: 8,
    backgroundColor: "blue"
  },
  moveRight: {
    alignSelf: "flex-end",
    height: 200,
    width: 200
  },
  buttonContainer: {
    alignSelf: "center"
  }
});

export default App;
import React, { Component } from "react";
import {
  View,
  Platform,
  UIManager,
  LayoutAnimation,
  StyleSheet,
  Button
} from "react-native";

if (
  Platform.OS === "android" &&
  UIManager.setLayoutAnimationEnabledExperimental
) {
  UIManager.setLayoutAnimationEnabledExperimental(true);
}

class App extends Component {
  state = {
    boxPosition: "left"
  };

  toggleBox = () => {
    LayoutAnimation.configureNext(
      LayoutAnimation.create(
        500,
        LayoutAnimation.Types.spring,
        LayoutAnimation.Properties.scaleXY
      )
    );
    this.setState({
      boxPosition: this.state.boxPosition === "left" ? "right" : "left"
    });
  };

  render() {
    return (
      <View style={styles.container}>
        <View style={styles.buttonContainer}>
          <Button title="Toggle Layout" onPress={this.toggleBox} />
        </View>
        <View
          style={[
            styles.box,
            this.state.boxPosition === "left" ? null : styles.moveRight
          ]}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: "flex-start",
    justifyContent: "center"
  },
  box: {
    height: 100,
    width: 100,
    borderRadius: 5,
    margin: 8,
    backgroundColor: "blue"
  },
  moveRight: {
    alignSelf: "flex-end",
    height: 200,
    width: 200
  },
  buttonContainer: {
    alignSelf: "center"
  }
});

export default App;

الخاصيات

Types

تستخدم أنواع الحركات من القيم المتعدّدة (enumeration) في التّابع ()‎create، أو في المعامل config الذي يمرّر إلى create، أو update، أو delete من أجل التّابع ()configureNext، (يمكن أن يستخدم، مثلًا: LayoutAnimation.Types.easeIn)، وهذه الأنواع هي:

  • spring
  • linear
  • easeInEaseOut
  • easeIn
  • easeOut
  • keyboard

Properties

خاصيات التّخطيط من القيم المتعدّدة (enumeration) المستخدمة في الحركات، وتستخدم في التّابع ()create، أو في المعامل (config) الذي يمرّر إلى create، أو update، أو delete من أجل التّابع ()configureNext، (يمكن أن يستخدم مثلًا: LayoutAnimation.Properties.opacity)، وهذه الخاصيات هي:

  • opacity
  • scaleX
  • scaleY
  • scaleXY

Presets

وهي مجموعة من معاملات (أو مكونات ضبط config) حركةٍ معرّفةٍ مسبقًا، تمرّر للتّابع ‪.configureNext()

كائن الضبط المسبق القيمة
easeInEaseOut
create(300, 'easeInEaseOut', 'opacity')
linear
create(500, 'linear', 'opacity')
spring
{ duration: 700, create: { type: 'linear', property: 'opacity' }, update: { type: 'spring', springDamping: 0.4 }, delete: { type: 'linear', property: 'opacity' } }
  • ‫‏()‎easeInEaseOut: يستدعي التّابع ()configureNext مع Presets.easeInEaseOut.
  • ()liner: يستدعي التّابع ()configureNext مع Presets.liner.
  • ()spring: يستدعي التّابع ()configureNext مع Presets.spring.

إليك مثال الاستخدام التالي:

import React, { useState } from "react";
import {
  View,
  Platform,
  UIManager,
  LayoutAnimation,
  StyleSheet,
  Button
} from "react-native";

if (
  Platform.OS === "android" &&
  UIManager.setLayoutAnimationEnabledExperimental
) {
  UIManager.setLayoutAnimationEnabledExperimental(true);
}

const App = () => {
  const [firstBoxPosition, setFirstBoxPosition] = useState("left");
  const [secondBoxPosition, setSecondBoxPosition] = useState("left");
  const [thirdBoxPosition, setThirdBoxPosition] = useState("left");

  const toggleFirstBox = () => {
    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
    setFirstBoxPosition(firstBoxPosition === "left" ? "right" : "left");
  };

  const toggleSecondBox = () => {
    LayoutAnimation.configureNext(LayoutAnimation.Presets.linear);
    setSecondBoxPosition(secondBoxPosition === "left" ? "right" : "left");
  };

  const toggleThirdBox = () => {
    LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
    setThirdBoxPosition(thirdBoxPosition === "left" ? "right" : "left");
  };

  return (
    <View style={styles.container}>
      <View style={styles.buttonContainer}>
        <Button title="EaseInEaseOut" onPress={toggleFirstBox} />
      </View>
      <View
        style={[
          styles.box,
          firstBoxPosition === "left" ? null : styles.moveRight
        ]}
      />
      <View style={styles.buttonContainer}>
        <Button title="Linear" onPress={toggleSecondBox} />
      </View>
      <View
        style={[
          styles.box,
          secondBoxPosition === "left" ? null : styles.moveRight
        ]}
      />
      <View style={styles.buttonContainer}>
        <Button title="Spring" onPress={toggleThirdBox} />
      </View>
      <View
        style={[
          styles.box,
          thirdBoxPosition === "left" ? null : styles.moveRight
        ]}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: "flex-start",
    justifyContent: "center"
  },
  box: {
    height: 100,
    width: 100,
    borderRadius: 5,
    margin: 8,
    backgroundColor: "blue"
  },
  moveRight: {
    alignSelf: "flex-end"
  },
  buttonContainer: {
    alignSelf: "center"
  }
});

export default App;
import React, { Component } from "react";
import {
  View,
  Platform,
  UIManager,
  LayoutAnimation,
  StyleSheet,
  Button
} from "react-native";

if (
  Platform.OS === "android" &&
  UIManager.setLayoutAnimationEnabledExperimental
) {
  UIManager.setLayoutAnimationEnabledExperimental(true);
}

class App extends Component {
  state = {
    firstBoxPosition: "left",
    secondBoxPosition: "left",
    thirdBoxPosition: "left"
  };

  toggleFirstBox = () => {
    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
    this.setState({
      firstBoxPosition:
        this.state.firstBoxPosition === "left" ? "right" : "left"
    });
  };

  toggleSecondBox = () => {
    LayoutAnimation.configureNext(LayoutAnimation.Presets.linear);
    this.setState({
      secondBoxPosition:
        this.state.secondBoxPosition === "left" ? "right" : "left"
    });
  };

  toggleThirdBox = () => {
    LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
    this.setState({
      thirdBoxPosition:
        this.state.thirdBoxPosition === "left" ? "right" : "left"
    });
  };

  render() {
    return (
      <View style={styles.container}>
        <View style={styles.buttonContainer}>
          <Button title="EaseInEaseOut" onPress={this.toggleFirstBox} />
        </View>
        <View
          style={[
            styles.box,
            this.state.firstBoxPosition === "left" ? null : styles.moveRight
          ]}
        />
        <View style={styles.buttonContainer}>
          <Button title="Linear" onPress={this.toggleSecondBox} />
        </View>
        <View
          style={[
            styles.box,
            this.state.secondBoxPosition === "left" ? null : styles.moveRight
          ]}
        />
        <View style={styles.buttonContainer}>
          <Button title="Spring" onPress={this.toggleThirdBox} />
        </View>
        <View
          style={[
            styles.box,
            this.state.thirdBoxPosition === "left" ? null : styles.moveRight
          ]}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: "flex-start",
    justifyContent: "center"
  },
  box: {
    height: 100,
    width: 100,
    borderRadius: 5,
    margin: 8,
    backgroundColor: "blue"
  },
  moveRight: {
    alignSelf: "flex-end"
  },
  buttonContainer: {
    alignSelf: "center"
  }
});

export default App;

مصادر