کامپوننت ScrollView در React Native — کانتینری با قابلیت اسکرول محتوایی که از اندازه صفحه فراتر میرود. برخلاف FlatList، ScrollView همه محتوا را یکباره رندر میکند که برای حجمهای کوچک داده، فرمها و صفحههایی با ارتفاع مشخص بهینه است. به گفته React Native Docs, 2024، ScrollView از اسکرول عمودی و افقی، رویداد onScroll، کنترل برنامهریزی شده موقعیت و حرکات زوم پشتیبانی میکند. کامپوننت در iOS به صورت UIScrollView بومی و در Android به صورت ScrollView رندر میشود.
نکات اصلی
ScrollView — کامپوننت React Native است که محتوای خود را در یک کانتینر اسکرولپذیر قرار میدهد. اگر محتوا از مرزهای صفحه فراتر رود، کاربر میتواند آن را به صورت عمودی یا افقی پیمایش کند. ScrollView تمام عناصر فرزند را هنگام نصب رندر میکند، صرف نظر از اینکه روی صفحه قابل مشاهده باشند یا خیر.
برخلاف FlatList که فقط عناصر قابل مشاهده را رندر میکند (lazy rendering)، ScrollView همه نمایشهای بومی را یکباره ایجاد میکند. این باعث میشود ScrollView برای فرمها، صفحات تنظیمات، کارتهای محصول در یک صفحه مناسب باشد — هر جا که تعداد عناصر فرزند کم است (تا 20-30) یا تعداد دقیق آنها از قبل مشخص نیست.
به گفته React Native Using ScrollView, 2024، ScrollView از اسکرول تودرتو (مثلاً ScrollView داخل ScrollView)، اثر جهش هنگام رسیدن به لبه، نشانگرهای اسکرول، قفل موقعیت (snap) و حرکات پشتیبانی میکند. در iOS، ScrollView به طور خودکار از طریق contentInsetAdjustmentBehavior زیر SafeArea فاصله اضافه میکند.
ScrollView مجموعه غنی از ویژگیها را برای کنترل رفتار اسکرول، ظاهر و تعامل فراهم میکند. بیایید گروههای کلیدی را بررسی کنیم: کنترل اسکرول، تنظیمات بصری، رویدادها و ویژگیهای پلتفرمی.
horizontal — جهت اسکرول را از عمودی (پیشفرض) به افقی تغییر میدهد. scrollEnabled — در صورت نیاز اسکرول را غیرفعال میکند. showsVerticalScrollIndicator و showsHorizontalScrollIndicator نمایش نشانگرهای اسکرول را کنترل میکنند. bounces (iOS) اثر جهش را هنگام رسیدن به لبه محتوا فعال/غیرفعال میکند.
رویداد اصلی — onScroll که در هر اسکرول فراخوانی میشود و شیءای با nativeEvent شامل contentOffset (موقعیت فعلی)، contentSize (اندازه محتوا)، layoutMeasurement (اندازه ناحیه قابل مشاهده) ارسال میکند. onMomentumScrollEnd پس از اتمام اسکرول اینرسی فراخوانی میشود. onScrollEndDrag — زمانی که کاربر صفحه را رها کرده است. از این رویدادها برای پیادهسازی اسکرول نامحدود، پارالاکس و بارگذاری تنبل استفاده میشود.
ScrollView متدهایی برای کنترل برنامهریزی شده از طریق رفرنس فراهم میکند: scrollTo({x, y, animated}) به مختصات مشخص شده اسکرول میکند، scrollToEnd({animated}) — به انتهای محتوا، flashScrollIndicators() — به طور موقت نشانگرهای اسکرول را نشان میدهد.
const scrollRef = useRef(null);
// اسکرول به بالا
scrollRef.current.scrollTo({ x: 0, y: 0, animated: true });
// اسکرول به انتها
scrollRef.current.scrollToEnd({ animated: true });
کنترل برنامهریزی شده اسکرول اغلب در چتها (اسکرول خودکار به آخرین پیام)، فرمها (اسکرول به فیلد دارای خطا) و کاروسلها (پیمایش برنامهریزی شده) استفاده میشود.
انتخاب بین ScrollView و FlatList — یکی از تصمیمات معماری کلیدی در React Native است. هر دو کامپوننت اسکرول را فراهم میکنند، اما از استراتژیهای رندر متفاوتی استفاده میکنند. ScrollView همه چیز را یکباره رندر میکند، FlatList — فقط عناصر قابل مشاهده.
| ویژگی | ScrollView | FlatList |
|---|---|---|
| رندر | همه عناصر یکباره | فقط قابل مشاهده + بافر |
| عملکرد | با 30+ عنصر کاهش مییابد | در هر تعداد پایدار |
| محتوا | هر کامپوننتی (فرمها، کارتها) | عناصر همنوع از آرایه |
| حجم داده | کوچک و متوسط (تا 30 عنصر) | بزرگ و نامحدود |
| اسکرول افقی | بله (ویژگی horizontal) | بله (horizontal) |
| بخشها | خیر (همانطور که هست رندر میکند) | SectionList برای بخشها |
قانون انتخاب: ScrollView — برای صفحههایی که تعداد عناصر فرزند مشخص است و از 20-30 تجاوز نمیکند (پروفایل کاربر، فرم تنظیمات، صفحه محصول). FlatList — برای لیستهایی با تعداد بالقوه زیاد عناصر (خوراک خبری، کاتالوگ محصولات، پیامهای چت). اگر محتوا ناهمگن است (عنوان، فرم، کارت، فوتر) — ScrollView ترجیح داده میشود، زیرا FlatList انتظار عناصر همنوع دارد.
ScrollView از اسکرول افقی از طریق ویژگی horizontal پشتیبانی میکند که آن را برای کاروسلها، گالریهای تصاویر، تبها و لیستهای افقی ایدهآل میکند. در ترکیب با ویژگی pagingEnabled (iOS) یا snapToInterval، ScrollView به یک کامپوننت برای پیمایش صفحهای تبدیل میشود.
ویژگی horizontal جهت اسکرول را تغییر میدهد. pagingEnabled (iOS) اسکرول صفحهای را فعال میکند، که در آن اسکرول فقط در مرزهای عناصر متوقف میشود. snapToInterval گام چسبندگی را بر حسب پیکسل برای هر دو پلتفرم تعیین میکند.
const ImageCarousel = ({ images }) => (
<ScrollView
horizontal
pagingEnabled
showsHorizontalScrollIndicator={false}
onMomentumScrollEnd={handlePageChange}
>
{images.map((img, index) => (
<Image
key={index}
source={{ uri: img }}
style={{ width: SCREEN_WIDTH, height: 250 }}
/>
))}
</ScrollView>
);
در این کاروسل، pagingEnabled به طور خودکار اسکرول را به مرزهای هر تصویر میچسباند. onMomentumScrollEnd به روزرسانی نشانگر صفحه فعلی را امکانپذیر میکند. چنین کاروسلی به صورت بومی کار میکند و از اسکرول اینرسی پشتیبانی میکند.
برای گامهای چسبندگی سفارشی از snapToInterval (اندازه گام بر حسب پیکسل) و snapToAlignment (start, center, end) استفاده میشود. با snapToOffsets میتوان آرایهای از موقعیتهای خاص برای چسبندگی تعیین کرد. این برای لیستهای افقی با کارتهای با اندازههای مختلف مفید است.
دو سناریوی معمولی را بررسی میکنیم: صفحه با فرم (اسکرول عمودی) و لیست افقی دستهبندیها. هر دو از ScrollView با ویژگیهای مختلف برای رفتار بهینه استفاده میکنند.
صفحه ویرایش پروفایل شامل عناصر ناهمگن است: آواتار، چند فیلد ورودی، سوئیچها و دکمه ذخیره. ScrollView امکان اسکرول کل صفحه را به طور کامل فراهم میکند، نه هر بلوک را جداگانه.
const ProfileScreen = () => (
<ScrollView
contentContainerStyle={styles.container}
keyboardShouldPersistTaps="handled"
showsVerticalScrollIndicator={false}
>
<AvatarPicker />
<TextInput placeholder="Name" />
<TextInput placeholder="Email" />
<TextInput placeholder="About me" multiline />
<SwitchRow label="Notifications" />
<Button title="Save" />
</ScrollView>
);
ویژگی keyboardShouldPersistTaps: 'handled' امکان اسکرول و تعامل با فرم را هنگامی که صفحه کلید باز است فراهم میکند. contentContainerStyle به کل محتوا فاصله اعمال میکند. این الگو در تمام صفحات دارای فرم در React Native استفاده میشود.
برای پیمایش دستهبندیها (چتها، فیلترها، تبها) از ScrollView افقی با چیپها استفاده میشود. چنین کامپوننتی اغلب در برنامههای بازارگاه و شبکههای اجتماعی یافت میشود.
const CategoryChips = ({ categories, selected, onSelect }) => (
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
contentContainerStyle={styles.chipContainer}
>
{categories.map((cat) => (
<Chip
key={cat.id}
label={cat.name}
isSelected={selected === cat.id}
onPress={() => onSelect(cat.id)}
/>
))}
</ScrollView>
);
ScrollView افقی با نشانگر غیرفعال — استانداردی برای نوار دستهبندیها است. هر چیپ یک کامپوننت مجزا با حالت انتخاب است. ویژگی showsHorizontalScrollIndicator: false نوار اسکرول را پنهان میکند که مطابق انتظارات کاربران برنامههای موبایل است.
سوالات متداول
ScrollView برای حجمهای کوچک داده (تا ۲۰-۳۰ عنصر) و محتوای ناهمگن (فرمها، پروفایلها، صفحات تنظیمات) مناسب است. FlatList را برای لیستهای طولانی همنوع انتخاب کنید — خوراک خبری، کاتالوگ محصولات، پیامها.
از رویداد onScroll با onScrollEndDrag یا onMomentumScrollEnd استفاده کنید. در nativeEvent.contentOffset.y موقعیت عمودی فعلی قرار دارد. برای عملکرد از ScrollEventThrottle (iOS) برای تنظیم فرکانس فراخوانی onScroll استفاده کنید.
ScrollView هنگام نصب همه عناصر را رندر میکند و برای هر کدام نمایشهای بومی ایجاد میکند. با ۵۰+ عنصر روی صفحه، بار حافظه و رشته JS افزایش مییابد و باعث افت فریم میشود. برای چنین مواردی از FlatList با رندر تنبل استفاده کنید.
bounces={false} را تنظیم کنید. این ویژگی فقط در iOS کار میکند و اثر فنری را هنگام رسیدن به لبه ScrollView غیرفعال میکند. در Android اثر جهش به طور پیشفرض وجود ندارد، بنابراین ویژگی نادیده گرفته میشود.
ScrollView به صورت بومی از اسکرول نامحدود پشتیبانی نمیکند. با این حال میتوان onScroll را با بررسی نزدیکی به لبه پایینی (contentOffset.y + ارتفاع صفحه >= contentSize.height) ترکیب کرد و عناصر را به state اضافه کرد. برای حجمهای زیاد از FlatList با onEndReached استفاده کنید.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید