
توسعهدهندگان اغلب هنگام ایجاد برنامههای کاربردی برای دستگاههای تاشو - به خصوص دستگاههایی مانند Samsung Trifold یا Pixel Fold اصلی که در قالب افقی باز میشوند (rotation_0 = landscape) - با مشکلات منحصر به فردی روبرو میشوند. اشتباهات توسعهدهندگان شامل موارد زیر است:
- فرضیات اشتباه در مورد جهتگیری دستگاه
- موارد استفاده نادیده گرفته شده
- عدم محاسبه مجدد یا ذخیره مقادیر در حافظه پنهان در طول تغییرات پیکربندی
مشکلات خاص مربوط به دستگاه عبارتند از:
- عدم تطابق در جهتگیری طبیعی دستگاه بین نمایشگرهای داخلی و کاور (فرضیات مبتنی بر rotation_0 = عمودی بودن صفحه نمایش)، که باعث میشود برنامهها در هنگام تا شدن و باز شدن با مشکل مواجه شوند.
- تراکمهای مختلف صفحه نمایش و مدیریت تغییر پیکربندی تراکم نادرست
- مشکلات پیشنمایش دوربین ناشی از وابستگی حسگر دوربین به جهتگیری طبیعی
برای ارائه یک تجربه کاربری با کیفیت بالا در دستگاههای تاشو، روی حوزههای حیاتی زیر تمرکز کنید:
- جهتگیری برنامه را بر اساس مساحت واقعی صفحه نمایش که برنامه اشغال میکند تعیین کنید، نه بر اساس جهت فیزیکی دستگاه
- پیشنمایشهای دوربین را بهروزرسانی کنید تا جهتگیری دستگاه و نسبتهای ابعاد را به درستی مدیریت کنید، از پیشنمایشهای جانبی جلوگیری کنید و از کشیده شدن یا برش تصاویر جلوگیری کنید.
- حفظ پیوستگی برنامه در حین تا شدن یا باز شدن دستگاه، با حفظ وضعیت با
ViewModelیا رویکردهای مشابه، یا مدیریت دستی تغییرات تراکم صفحه و تغییرات جهتگیری، که از راهاندازی مجدد برنامه یا از دست رفتن وضعیت جلوگیری میکند. - برای برنامههایی که از حسگرهای حرکتی استفاده میکنند، سیستم مختصات را طوری تنظیم کنید که با جهت فعلی صفحه نمایش همسو باشد و از فرضیات مبتنی بر rotation_0 = portrait اجتناب کنید، که این امر تعامل دقیق کاربر را تضمین میکند.
ساخت تطبیقی
اگر برنامه شما از قبل تطبیقپذیر است و به سطح بهینهشده (Tier 2) که در دستورالعملهای کیفیت برنامه صفحه بزرگ مشخص شده است، پایبند است، برنامه باید روی دستگاههای تاشو به خوبی کار کند. در غیر این صورت، قبل از بررسی مجدد جزئیات خاص دستگاههای تاشو سهگانه و افقی، مفاهیم اساسی توسعه تطبیقی اندروید زیر را مرور کنید.
طرحبندیهای تطبیقی
رابط کاربری شما نه تنها باید اندازههای مختلف صفحه نمایش، بلکه تغییرات در نسبت ابعاد تصویر، مانند باز شدن و ورود به حالتهای چند پنجرهای یا پنجرهبندی دسکتاپ را نیز به صورت آنی مدیریت کند. برای راهنمایی بیشتر در مورد چگونگی انجام این کار، به «درباره طرحبندیهای تطبیقی» مراجعه کنید:
- طراحی و پیادهسازی طرحهای تطبیقی
- تنظیم ناوبری اصلی برنامه بر اساس اندازه پنجره
- از کلاسهای اندازه پنجره برای تطبیق رابط کاربری برنامه خود استفاده کنید
- سادهسازی پیادهسازی طرحبندیهای متعارف، مانند جزئیات لیست، با استفاده از APIهای Jetpack

کلاسهای اندازه پنجره
دستگاههای تاشو، از جمله تاشوهای افقی و سهلا، میتوانند فوراً بین کلاسهای اندازه پنجره جمعوجور، متوسط و باز تغییر حالت دهند. درک و پیادهسازی این کلاسها تضمین میکند که برنامه شما اجزای ناوبری صحیح و تراکم محتوا را برای وضعیت فعلی دستگاه نمایش میدهد.

مثال زیر از کتابخانه تطبیقی Material 3 برای تعیین میزان فضای در دسترس برنامه استفاده میکند، ابتدا با فراخوانی تابع currentWindowAdaptiveInfo() و سپس با استفاده از طرحبندیهای مربوطه برای سه کلاس اندازه پنجره:
val adaptiveInfo = currentWindowAdaptiveInfo(supportLargeAndXLargeWidth = true)
val windowSizeClass = adaptiveInfo.windowSizeClass
when {
windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_EXPANDED_LOWER_BOUND) -> // Large
windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_MEDIUM_LOWER_BOUND) -> // Medium
else -> // Compact
}
برای اطلاعات بیشتر، به استفاده از کلاسهای اندازه پنجره مراجعه کنید.
کیفیت برنامه روی صفحه نمایش بزرگ
رعایت دستورالعملهای کیفیت اپلیکیشنهای صفحه بزرگ در سطح ۲ (بهینهسازی شده برای صفحه نمایش بزرگ) یا سطح ۱ (متمایز شده برای صفحه نمایش بزرگ) تضمین میکند که اپلیکیشن شما یک تجربه کاربری قانعکننده در دستگاههای سهگانه، تاشوهای افقی و سایر دستگاههای صفحه بزرگ ارائه میدهد. این دستورالعملها بررسیهای حیاتی را در سطوح مختلف پوشش میدهند تا از حالت آماده تطبیقی به یک تجربه متمایز تبدیل شوند.
اندروید ۱۶ و بالاتر
برای برنامههایی که اندروید ۱۶ (سطح API ۳۶) و بالاتر را هدف قرار میدهند، سیستم محدودیتهای جهتگیری، تغییر اندازه و نسبت ابعاد را در نمایشگرهایی با کمترین عرض >= ۶۰۰dp نادیده میگیرد. برنامهها کل پنجره نمایشگر را صرف نظر از نسبت ابعاد یا جهتگیری ترجیحی کاربر پر میکنند و حالت سازگاری با جعبه حروف دیگر دیگر استفاده نمیشود.
ملاحظات ویژه
گوشیهای تاشو سهگانه و تاشوهای افقی، رفتارهای سختافزاری منحصر به فردی را ارائه میدهند که نیاز به مدیریت خاصی دارند، به خصوص در مورد حسگرها، پیشنمایش دوربین و پیوستگی پیکربندی (حفظ حالت هنگام تا کردن، باز کردن یا تغییر اندازه).
پیشنمایش دوربین
یک مشکل رایج در نمایشگرهای تاشو افقی یا محاسبات نسبت ابعاد (در سناریوهایی مانند چند پنجرهای، پنجرهای کردن دسکتاپ یا نمایشگرهای متصل)، زمانی است که پیشنمایش دوربین کشیده، کناری، برش خورده یا چرخانده شده به نظر میرسد.
فرضیات نامتناسب
این مشکل اغلب در دستگاههای با صفحه نمایش بزرگ و تاشو اتفاق میافتد، زیرا برنامهها میتوانند روابط ثابتی بین ویژگیهای دوربین - مانند نسبت ابعاد و جهت حسگر - و ویژگیهای دستگاه - مانند جهت دستگاه و جهت طبیعی - فرض کنند.
فرمفاکتورهای جدید این فرض را به چالش میکشند. یک دستگاه تاشو میتواند اندازه نمایشگر و نسبت ابعاد خود را بدون تغییر چرخش دستگاه تغییر دهد. به عنوان مثال، باز کردن یک دستگاه نسبت ابعاد را تغییر میدهد، اما اگر کاربر دستگاه را نچرخاند، چرخش آن ثابت میماند. اگر یک برنامه فرض کند که نسبت ابعاد با چرخش دستگاه مرتبط است، ممکن است پیشنمایش دوربین را به اشتباه بچرخاند یا مقیاسبندی کند. همین اتفاق میتواند رخ دهد اگر یک برنامه فرض کند که جهت حسگر دوربین با جهت دستگاه عمودی مطابقت دارد، که همیشه برای دستگاههای تاشو افقی صادق نیست.
راه حل ۱: Jetpack CameraX (بهترین)
سادهترین و قویترین راه حل استفاده از کتابخانه Jetpack CameraX است. عنصر رابط کاربری PreviewView آن به گونهای طراحی شده است که تمام پیچیدگیهای پیشنمایش را به طور خودکار مدیریت کند:
-
PreviewViewبه درستی جهت حسگر، چرخش دستگاه و مقیاسبندی را تنظیم میکند. - این تابع نسبت ابعاد تصویر دوربین را حفظ میکند، معمولاً با قرار دادن تصویر در مرکز و برش (FILL_CENTER).
- در صورت نیاز میتوانید نوع مقیاس را روی
FIT_CENTERتنظیم کنید تا پیشنمایش به صورت Letterbox نمایش داده شود.
برای اطلاعات بیشتر، به بخش «پیادهسازی پیشنمایش» در مستندات CameraX مراجعه کنید.
راه حل ۲: دوربین ویو فایندر
اگر از یک کدبیس Camera2 موجود استفاده میکنید، کتابخانه CameraViewfinder (سازگار با API سطح ۲۱) یک راهحل مدرن دیگر است. این کتابخانه با استفاده از TextureView یا SurfaceView و اعمال تمام تبدیلات لازم (نسبت ابعاد، مقیاس و چرخش) نمایش فید دوربین را برای شما ساده میکند.
برای اطلاعات بیشتر، به پست وبلاگ «معرفی منظرهیاب دوربین» و راهنمای توسعهدهندگان پیشنمایش دوربین مراجعه کنید.
راه حل ۳: پیادهسازی دستی Camera2
اگر نمیتوانید از CameraX یا CameraViewfinder استفاده کنید، باید جهت و نسبت ابعاد را به صورت دستی محاسبه کنید و مطمئن شوید که محاسبات با هر تغییر پیکربندی بهروزرسانی میشوند:
- جهت حسگر دوربین (برای مثال، ۰، ۹۰، ۱۸۰، ۲۷۰ درجه) را از
CameraCharacteristicsدریافت کنید. - چرخش فعلی صفحه نمایش دستگاه (مثلاً ۰، ۹۰، ۱۸۰، ۲۷۰ درجه) را دریافت کنید.
- از این دو مقدار برای تعیین تبدیلهای لازم برای
SurfaceViewیاTextureViewخود استفاده کنید. - مطمئن شوید که نسبت ابعاد
Surfaceخروجی شما با نسبت ابعاد تصویر پیشنمایش دوربین مطابقت دارد تا از اعوجاج جلوگیری شود. - ممکن است برنامه دوربین در بخشی از صفحه نمایش، چه در حالت چند پنجرهای یا پنجرهای دسکتاپ یا روی یک صفحه نمایش متصل، اجرا شود. به همین دلیل، نباید از اندازه صفحه نمایش برای تعیین ابعاد منظرهیاب دوربین استفاده کرد، بلکه باید از معیارهای پنجره استفاده کرد.
برای اطلاعات بیشتر، به راهنمای توسعهدهنده پیشنمایش دوربین و ویدیوی برنامه دوربین شما در فرمفکتورهای مختلف مراجعه کنید.
راه حل ۴: انجام اقدامات اولیه دوربین با استفاده از یک intent
اگر به ویژگیهای زیادی از دوربین نیاز ندارید، یک راه حل ساده و سرراست، انجام اقدامات اولیه دوربین مانند گرفتن عکس یا فیلم با استفاده از برنامه دوربین پیشفرض دستگاه است. نیازی به ادغام با کتابخانه دوربین ندارید؛ در عوض، از یک Intent استفاده کنید.
برای اطلاعات بیشتر، به بخش «اهداف دوربین» مراجعه کنید.
پیکربندی و تداوم
دستگاههای تاشو تطبیقپذیری رابط کاربری را افزایش میدهند، اما میتوانند تغییرات پیکربندی بیشتری نسبت به دستگاههای غیر تاشو ایجاد کنند. برنامه شما باید این تغییرات پیکربندی و ترکیب آنها، مانند چرخش دستگاه، تاشو/باز شدن و تغییر اندازه پنجره در حالتهای چند پنجرهای یا دسکتاپ را مدیریت کند، در حالی که حالت برنامه را حفظ یا بازیابی میکند. به عنوان مثال، برنامهها باید پیوستگی زیر را حفظ کنند:
- وضعیت برنامه بدون از کار افتادن یا ایجاد تغییرات مزاحم برای کاربران (برای مثال، هنگام تعویض صفحه یا ارسال برنامه به پسزمینه)
- موقعیت اسکرول فیلدهای قابل اسکرول
- متن تایپ شده در فیلدهای متنی و وضعیت صفحه کلید
- موقعیت پخش رسانه، به طوری که پخش از جایی که هنگام شروع تغییر پیکربندی متوقف شده بود، از سر گرفته شود
تغییرات پیکربندی که اغلب اعمال میشوند شامل screenSize ، smallestScreenSize ، screenLayout ، orientation ، density ، fontScale ، touchscreen و keyboard هستند.
به android:configChanges و Handle configuration changes مراجعه کنید. برای اطلاعات بیشتر در مورد مدیریت وضعیت برنامه، به Save UI states مراجعه کنید.
تغییرات پیکربندی چگالی
صفحه نمایشهای بیرونی و داخلی دستگاههای تاشو سهلایه و افقی ممکن است تراکم پیکسلی متفاوتی داشته باشند. بنابراین، مدیریت تغییر پیکربندی برای density نیاز به توجه بیشتری دارد. اندروید معمولاً هنگام تغییر تراکم نمایش، activity را مجدداً راهاندازی میکند که میتواند باعث از دست رفتن دادهها شود. برای جلوگیری از راهاندازی مجدد activity توسط سیستم، مدیریت تراکم را در مانیفست خود تعریف کنید و تغییر پیکربندی را به صورت برنامهنویسی در برنامه خود مدیریت کنید.
پیکربندی AndroidManifest.xml
-
density: اعلام میکند که برنامه تغییر تراکم صفحه نمایش را مدیریت خواهد کرد. - سایر تغییرات پیکربندی: همچنین خوب است که سایر تغییرات پیکربندی که مرتباً اتفاق میافتند، مانند
screenSize،orientation،keyboardHidden،fontScaleو غیره را نیز تعریف کنید.
اعلام چگالی (و سایر تغییرات پیکربندی) مانع از راهاندازی مجدد فعالیت توسط سیستم میشود و در عوض تابع onConfigurationChanged() را فراخوانی میکند.
پیادهسازی onConfigurationChanged()
وقتی تغییری در چگالی رخ میدهد، باید منابع خود را (مانند بارگذاری مجدد بیتمپها یا محاسبه مجدد اندازههای طرحبندی) در فراخوانی مجدد بهروزرسانی کنید:
- تأیید کنید که DPI به
newConfig.densityDpiتغییر کرده است - نماهای سفارشی، ترسیمهای سفارشی و غیره را با چگالی جدید تنظیم مجدد کنید
موارد منبع برای پردازش
- منبع تصویر : بیتمپها و تصاویر قابل ترسیم را با منابع با چگالی خاص جایگزین کنید، یا مقیاس را مستقیماً تنظیم کنید
- واحد طرحبندی (تبدیل dp به px) : محاسبه مجدد اندازه نما، حاشیه، فاصلهگذاری
- اندازه فونت و متن : اندازه متن واحد sp را دوباره اعمال کنید
-
Viewسفارشی / طراحیCanvas: مقادیر مبتنی بر پیکسل مورد استفاده برای طراحیCanvasرا بهروزرسانی کنید
تعیین جهتگیری برنامه
هرگز هنگام ساخت تطبیقی به چرخش فیزیکی دستگاه تکیه نکنید، زیرا در دستگاههای صفحه نمایش بزرگ نادیده گرفته میشود و یک برنامه در حالت چند پنجرهای میتواند جهتگیری متفاوتی نسبت به دستگاه داشته باشد. در عوض، از Configuration.orientation یا WindowMetrics برای تشخیص اینکه آیا برنامه شما در حال حاضر در جهت افقی یا عمودی است، بر اساس اندازه پنجره استفاده کنید.
راه حل ۱: استفاده از Configuration.orientation
این ویژگی جهت نمایش فعلی برنامه شما را مشخص میکند.
راه حل ۲: استفاده از WindowMetrics#getBounds()
میتوانید محدودههای نمایش فعلی برنامه را دریافت کنید و عرض و ارتفاع آن را برای تعیین جهتگیری بررسی کنید.
اگر نیاز دارید جهتگیری برنامه را در تلفنها (یا صفحههای بیرونی تاشوها) محدود کنید اما در دستگاههای صفحه بزرگ اینطور نیست، به محدود کردن جهتگیری برنامه در تلفنها مراجعه کنید.
حالتها و حالتهای نمایش
حالتها و حالتهای تاشو مانند حالت رومیزی و حالت HALF_OPENED توسط هر دو مدل تاشوی عمودی و افقی پشتیبانی میشوند. با این حال، مدلهای سهگانه از حالت رومیزی پشتیبانی نمیکنند و نمیتوان از آنها HALF_OPENED استفاده کرد. در عوض، مدلهای سهگانه در حالت کاملاً باز، صفحه نمایش بزرگتری را برای یک تجربه کاربری منحصر به فرد ارائه میدهند.
برای متمایز کردن برنامه خود روی دستگاههای تاشو که HALF_OPENED پشتیبانی میکنند، از APIهای Jetpack WindowManager مانند FoldingFeature استفاده کنید.
برای کسب اطلاعات بیشتر در مورد حالتهای تاشو، حالتها و پشتیبانی از پیشنمایش دوربین، به راهنماهای توسعهدهندگان زیر مراجعه کنید:
دستگاههای تاشو تجربیات تماشای منحصر به فردی را ارائه میدهند. حالت نمایش از پشت و حالت صفحه نمایش دوگانه به شما این امکان را میدهد که ویژگیهای نمایشی ویژهای برای دستگاههای تاشو مانند پیشنمایش سلفی دوربین عقب و نمایش همزمان اما متفاوت در صفحه نمایشهای داخلی و خارجی ایجاد کنید. برای اطلاعات بیشتر به لینک زیر مراجعه کنید:
قفل کردن جهت گیری به جهت گیری طبیعی حسگر
برای موارد استفاده بسیار خاص - به ویژه برنامههایی که نیاز دارند کل صفحه نمایش را بدون توجه به حالت تا شده دستگاه در اختیار بگیرند - پرچم nosensor به شما امکان میدهد برنامه را در جهت طبیعی دستگاه قفل کنید. به عنوان مثال، در Pixel Fold، جهت طبیعی دستگاه هنگام تا شدن، عمودی است، در حالی که جهت طبیعی هنگام باز شدن، افقی است. اضافه کردن پرچم nosensor باعث میشود برنامه هنگام اجرا در صفحه نمایش بیرونی در حالت عمودی قفل شود و هنگام اجرا در صفحه نمایش داخلی در حالت افقی قفل شود.
<activity
android:name=".MainActivity"
android:screenOrientation="nosensor">
بازیها و بازنگاشت حسگر XR
برای بازیها و برنامههای واقعیت افزوده (XR)، دادههای خام حسگر (مانند ژیروسکوپ یا شتابسنج) در سیستم مختصات ثابت دستگاه ارائه میشوند. اگر کاربر دستگاه را برای انجام بازی در حالت افقی بچرخاند، محورهای حسگر با صفحه نمایش نمیچرخند و منجر به کنترلهای نادرست بازی میشوند.
برای رفع این مشکل، Display.getRotation() فعلی را بررسی کنید و محورها را بر اساس آن تغییر دهید:
- چرخش ۰ : x=x, y=y
- چرخش ۹۰ : x=-y، y=x
- چرخش ۱۸۰ : x=-x، y=-y
- چرخش ۲۷۰ : x=y, y=-x
برای بردارهای چرخش (که در برنامههای قطبنما یا XR استفاده میشوند)، از SensorManager.remapCoordinateSystem() برای نگاشت جهت لنز دوربین یا بالای صفحه به محورهای جدید بر اساس چرخش فعلی استفاده کنید.
سازگاری برنامه
برنامهها باید از دستورالعملهای کیفیت برنامه پیروی کنند تا سازگاری در تمام فرم فاکتورها و نمایشگرهای متصل تضمین شود. اگر یک برنامه نتواند با دستورالعملها مطابقت داشته باشد، تولیدکنندگان دستگاه میتوانند اقدامات سازگاری را اجرا کنند، اگرچه این ممکن است تجربه کاربر را خراب کند.
برای اطلاعات بیشتر، فهرست جامع راهحلهای سازگاری ارائه شده در پلتفرم، به ویژه موارد مربوط به پیشنمایش دوربین ، لغو تنظیمات و تغییرات API اندروید ۱۶ که میتوانند رفتار برنامه شما را تغییر دهند، را بررسی کنید.
برای کسب اطلاعات بیشتر در مورد ساخت برنامههای تطبیقی، به کیفیت برنامه صفحه نمایش بزرگ مراجعه کنید.