تطبيق لياقة يدمج عدّة مستشعرات
تطبيقٌ حقيقيّ يجمع الحركة والطاقة والإضاءة. ⏱ نحو 45 دقيقة.
- تدمج عدّة مستشعراتٍ في تطبيقٍ واحد.
- تبني عدّاد خطواتٍ مبسّطًا مع منع التكرار.
- تعرض تنبيهاتٍ شرطيّة من قراءات المستشعرات.
١دمج عدّة مستشعرات
التطبيقات الحقيقيّة تدمج مستشعراتٍ عدّة. تطبيق لياقةٍ مثلًا: الحركة (خطوات من الإمالة)، البطارية (تنبيه عند الانخفاض)، والضوء (وضع ليليّ للتمارين المسائيّة). ندير ذلك بمكوّنٍ رئيسٍ يجمع القراءات.
٢عدّاد خطوات من الحركة
نشترك في الإمالة؛ عند تجاوز المقدار عتبةً نعدّ خطوة (مع منع العدّ المزدوج):
import { useState, useEffect, useRef } from 'react';import { View, Text, StyleSheet } from 'react-native';import SmartDevice from 'smartdevice'; export default function App() { const [steps, setSteps] = useState(0); const armed = useRef(true); useEffect(() => { return SmartDevice.onTilt(({ x, y }) => { const mag = Math.abs(x) + Math.abs(y); if (mag > 30 && armed.current) { armed.current = false; setSteps((s) => s + 1); } if (mag < 10) armed.current = true; // أعد التسليح عند الهدوء }); }, []); const goal = 20; const pct = Math.min(100, Math.round((steps / goal) * 100)); return ( <View style={styles.box}> <Text testID="steps" style={styles.n}>{steps}</Text> <Text style={styles.lbl}>خطوة من {goal}</Text> <View style={styles.barBg}><View style={[styles.barFill, { width: pct + '%' }]} /></View> </View> );} const styles = StyleSheet.create({ box: { padding: 24, alignItems: 'center' }, n: { fontSize: 52, fontWeight: 'bold', color: '#E8820C' }, lbl: { color: '#666' }, barBg: { width: 200, height: 12, backgroundColor: '#eee', borderRadius: 6, marginTop: 12, overflow: 'hidden' }, barFill: { height: 12, backgroundColor: '#2E7D32' },});
useRef يحمل علَم «مسلّح» دون إعادة رسم. اضغط «هزّ» عدّة مرّات ليرتفع العدّاد.
٣لوحة اللياقة الكاملة
نجمع الخطوات مع البطارية والإضاءة في لوحةٍ واحدة. حرّك المستشعرات الثلاثة:
import { View, Text, StyleSheet } from 'react-native';import { useBattery, useLight } from 'smartdevice'; function Stat({ icon, label, value, color }) { return ( <View style={styles.stat}> <Text style={styles.ic}>{icon}</Text> <Text style={[styles.val, { color }]}>{value}</Text> <Text style={styles.lbl}>{label}</Text> </View> );} export default function App() { const bat = useBattery(); const lux = useLight(); const night = lux < 50; return ( <View style={[styles.box, { backgroundColor: night ? '#1a2330' : '#F7FAFC' }]}> <Text style={[styles.h, { color: night ? '#fff' : '#333' }]}> {night ? '🌙 تمرين مسائيّ' : '☀️ تمرين نهاريّ'} </Text> <View style={styles.row}> <Stat icon="🚶" label="خطوات" value="12" color="#E8820C" /> <Stat icon="🔋" label="البطارية" value={bat.level + '%'} color={bat.level < 20 ? '#C62828' : '#2E7D32'} /> <Stat icon="💡" label="الإضاءة" value={lux} color="#1565C0" /> </View> {bat.level < 20 && <Text style={styles.warn}>⚠ البطارية منخفضة — قد يتوقّف التتبّع</Text>} </View> );} const styles = StyleSheet.create({ box: { padding: 18, borderRadius: 14, margin: 10 }, h: { fontSize: 18, fontWeight: 'bold', marginBottom: 14, textAlign: 'center' }, row: { flexDirection: 'row', justifyContent: 'space-around' }, stat: { alignItems: 'center' }, ic: { fontSize: 26 }, val: { fontSize: 20, fontWeight: 'bold', marginTop: 4 }, lbl: { color: '#888', fontSize: 12 }, warn: { color: '#C62828', textAlign: 'center', marginTop: 14 },});
ثلاث قراءاتٍ في لوحةٍ واحدة، وتنبيهٌ شرطيّ عند انخفاض البطارية. هذا دمج المستشعرات الحقيقيّ.
توقّع وتحقّق
لماذا useRef لعلَم التسليح؟
لمنع العدّ المزدوج للخطوة:
دمج المستشعرات يعني:
التنبيه عند انخفاض البطارية:
الخلاصة
- دمج المستشعرات: حركة + بطارية + ضوء في لوحةٍ واحدة.
useRefيحمل علَمًا دون إعادة رسم (منع العدّ المزدوج).- العرض الشرطيّ بـ && يُظهر التنبيهات عند الحاجة.
تحدٍّ برمجي: عدّاد نشاط
متقدمادمج الخطوات (ثابتة) مع تنبيه البطارية.
- استورد
useBattery. <Text testID="steps">يعرض عدد خطواتٍ ثابت (مثلًا 8).<Text testID="bat">: إن كانت البطارية أقلّ من 20 «منخفضة» وإلا «جيدة».
👀 اعرض الناتج المطلوب (وجرّبه)
- الكود يعمل بلا أخطاء في Console
- الخطوات 8
- البطارية «جيدة» ابتداءً
- استُخدم useBattery
💡 تلميح 1
💡 تلميح 2
حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.
import { View, Text, StyleSheet } from 'react-native';import { useBattery } from 'smartdevice'; export default function App() { const bat = useBattery(); const steps = 8; const low = bat.level < 20; return ( <View style={{ padding: 20, gap: 8 }}> <Text testID="steps" style={styles.s}>الخطوات: {steps}</Text> <Text testID="bat" style={{ color: low ? '#C62828' : '#2E7D32' }}> {low ? 'منخفضة' : 'جيدة'} </Text> </View> );} const styles = StyleSheet.create({ s: { fontSize: 22, fontWeight: 'bold', color: '#E8820C' } });