ویرگول
ورودثبت نام
Peyman
Peymanاز برنامه نویسی مینویسم،سعی میکنم مفاهیم سختش رو جوری که خودم یادمیگیرم توضیحشو بذارم شاید به درد کسی خورد.چون به جاوااسکریپت علاقمندم مثالهام بیشترشون حول جاوااسکریپت میچرخن
Peyman
Peyman
خواندن ۳ دقیقه·۱ ماه پیش

تغییر بزرگ Android 16 در حالت Edge-to-Edge و راه‌حل برای React Native

اندروید ۱۶ (API سطح ۳۶) یه تغییر اساسی آورده که شاید در نگاه اول ساده به‌نظر بیاد،
ولی واقعاً تأثیر زیادی روی ظاهر و رفتار اپ‌هامون می‌ذاره — مخصوصاً برای ما که با React Native کار می‌کنیم.

بیاین باهم ببینیم دقیقاً چی عوض شده، چرا مهمه، و چطور می‌تونیم باهاش کنار بیایم.


💡 داستان از کجا شروع شد؟

از اندروید ۱۵ (API 35) گوگل تصمیم گرفت که اپ‌ها باید edge-to-edge بشن.
یعنی محتوای اپ از بالا تا پایینِ واقعی صفحه (زیر نوار وضعیت و نوار ناوبری) کشیده بشه.

ولی اون موقع یه راه فرار وجود داشت — اگه توی تم اپ می‌نوشتی:

<item name="windowOptOutEdgeToEdgeEnforcement">true</item>

می‌تونستی بگی:

"نه گوگل! من نمی‌خوام محتوای اپم تا لبه بره، بذار پایینش فاصله باشه."

اما حالا توی Android 16 گوگل گفته:

تمومه. دیگه نمی‌تونی از edge-to-edge فرار کنی.

اون attribute به‌طور کامل حذف و بی‌اثر شده.


📱 Edge-to-Edge یعنی چی دقیقاً؟

یعنی اپت کل صفحه رو می‌گیره — از زیر نوار وضعیت تا زیر gesture bar (نوار پایین گوشی).
خود سیستم UI مثل نوار پایین یا بالای گوشی روی محتوای تو می‌افته، نه اینکه براش فضا نگه داره.

یه نگاه تصویری:

قدیما (Android 13 و پایین‌تر):

+--------------------------+ | Status Bar (24px) | |--------------------------| | App Content | |--------------------------| | Navigation Bar (48px) | +--------------------------+

الان (Android 16):

+--------------------------+ | Status Bar (overlay) | |--------------------------| | App Content (زیر status bar) | |--------------------------| | Gesture Bar (overlay) | +--------------------------+

یعنی محتوای اپت تا ته صفحه کشیده می‌شه
و اگه خودت فاصله‌ی لازم رو ندی، مثلاً متن یا دکمه‌هات ممکنه برن زیر gesture bar.


⚙️ چرا این موضوع مهمه برای React Native

توی React Native خیلی وقت‌ها برای تشخیص ارتفاع صفحه از این دو استفاده می‌کنیم:

Dimensions.get('screen') Dimensions.get('window')

قبلاً فرق بین این دوتا معمولاً ارتفاع نوار ناوبری (Navigation Bar) بود.
اما از اندروید ۱۶ به بعد، چون اپ تا لبه می‌ره، این دوتا یکی می‌شن.

یعنی این تیکه کد:

const screenHeight = Dimensions.get('screen').height; const windowHeight = Dimensions.get('window').height; const navBarHeight = screenHeight - windowHeight;

دیگه به‌جای ۴۸ یا ۲۴، عدد صفر برمی‌گردونه 😅
و در نتیجه کلی از تنظیمات ظاهری‌مون مثل bottom sheet یا modal اشتباه کار می‌کنن.


🧠 راه‌حل: یه Helper بنویس

من برای اینکه این مشکل رو توی کل پروژه به‌صورت یکدست حل کنم، یه ساختار مرکزی طراحی کردم.

اول باید ارتفاع نوار وضعیت (StatusBar) و نوار ناوبری (NavigationBar) رو بگیریم:

NAVIGATION_BAR_HEIGHT: initialWindowMetrics?.insets?.bottom, STATUS_BAR_HEIGHT: StatusBar.currentHeight,

بعد دو بخش اصلی توی فایل کانفیگ ساختم:

  1. SCREEN_METADATA → اطلاعات مربوط به وضعیت صفحه و دستگاه (مثل notch، fullscreen و API level)

  2. OffsetCalculator → تابعی که با توجه به نوع کامپوننت و موقعیت (بالا/پایین) مقدار فاصله رو محاسبه می‌کنه


🧱 مرحله ۱ — تعریف Screen Metadata

{ API_LEVEL: 36, SCREEN_METADATA: { HAS_NOTCH: DeviceInfo.hasNotch(), STATUS_BAR_HEIGHT: StatusBar.currentHeight, OS_NAVIGATION_BAR_HEIGHT: initialWindowMetrics?.insets?.bottom, IS_FULL_SCREEN: API_LEVEL > 34 ? initialWindowMetrics?.insets?.bottom < 48 : true, }, }

این اطلاعات به من کمک می‌کنه تا در همه‌جا بدون نگرانی از جزئیات دستگاه، به‌صورت یکدست با layout کار کنم.


⚙️ مرحله ۲ — ساخت Offset Calculator

حالا یه تابع نوشتم که دوتا ورودی می‌گیره:

  • component: اسم بخشی از اپ (مثلاً drawer، tabbar، chat و غیره)

  • section: کدوم قسمت (بالا یا پایین)

نمونه ساده‌ش:

export default function OffsetCalculator(component = '', section = 'bottom') { const { API_LEVEL, SCREEN_METADATA } = AppConfig; const { HAS_NOTCH, IS_FULL_SCREEN, OS_NAVIGATION_BAR_HEIGHT } = SCREEN_METADATA; let offset = 0; switch (component) { case 'drawer': offset = section === 'top' ? (HAS_NOTCH ? AppSizes[15] : 0) : (IS_FULL_SCREEN ? AppSizes[15] : AppSizes[45]); break; case 'tabBarContainer': if (API_LEVEL > 34) { offset = IS_FULL_SCREEN ? -OS_NAVIGATION_BAR_HEIGHT / 1.5 : OS_NAVIGATION_BAR_HEIGHT / 1.2; } else { offset = IS_FULL_SCREEN ? -OS_NAVIGATION_BAR_HEIGHT * 2.5 : -OS_NAVIGATION_BAR_HEIGHT * 1.2; } break; // ... و همین‌طور برای سایر کامپوننت‌ها } return offset; }

حالا هر جای اپ (از Splash گرفته تا Chat و Drawer)، فقط کافیه این تابع رو صدا بزنم تا فاصله مناسب خودش رو حساب کنه.


🚀 مزایای این روش

✅ فقط یک نقطه مرکزی برای تنظیم Offsetها
✅ راحت برای آپدیت در نسخه‌های آینده Android
✅ سازگار با گوشی‌های دارای Notch یا بدون اون
✅ یکپارچگی کامل بین Android 14، 15 و 16
✅ دیگه لازم نیست برای هر کامپوننت جداگانه safe area بنویسی


💭 جمع‌بندی

تغییر Edge-to-Edge در Android 16 فقط یه تغییر ظاهری نیست — یه تحول ساختاری در نحوه تعامل اپ با سیستم UI محسوب میشه.
با مدیریت برنامه‌نویسی‌شده و متمرکز Offsetها، می‌تونی اپ React Native خودت رو در برابر نسخه‌های آینده هم آینده‌نگر و مقاوم کنی.

دفعه بعدی که دیدی یه دکمه یا تب‌بار چسبیده به Gesture Bar، نترس 😄
فقط OffsetCalculator رو صدا بزن!

react nativeبرنامه نویسی موبایلبرنامه نویس اندرویدری اکت نیتیو
۲
۰
Peyman
Peyman
از برنامه نویسی مینویسم،سعی میکنم مفاهیم سختش رو جوری که خودم یادمیگیرم توضیحشو بذارم شاید به درد کسی خورد.چون به جاوااسکریپت علاقمندم مثالهام بیشترشون حول جاوااسکریپت میچرخن
شاید از این پست‌ها خوشتان بیاید