در دستگاههای صفحهنمایش بزرگ، کاربران اغلب با استفاده از صفحهکلید، ماوس، پد لمسی، قلم، یا گیمپد با برنامهها تعامل دارند. برای فعال کردن برنامه خود برای پذیرش ورودی از دستگاه های خارجی، موارد زیر را انجام دهید:
- پشتیبانی اولیه صفحه کلید مانند پیمایش صفحه کلید Tab و پیکان، تأیید ورود متن کلید را وارد کنید و پخش/مکث نوار فاصله در برنامههای رسانه را آزمایش کنید .
- در صورت لزوم، میانبرهای استاندارد صفحه کلید را اضافه کنید . برای مثال، Ctrl + Z برای لغو و Ctrl + S برای ذخیره
- تعاملات اساسی ماوس را به روش کلیک راست برای منوی زمینه، تغییرات نمادها در شناور، و رویدادهای اسکرول چرخ ماوس یا صفحه لمسی در نماهای سفارشی آزمایش کنید .
- دستگاههای ورودی خاص برنامه مانند قلم برای طراحی برنامهها، کنترلکنندههای بازی برای بازیها و کنترلکنندههای MIDI برای برنامههای موسیقی
- پشتیبانی پیشرفته ورودی را در نظر بگیرید که می تواند برنامه را در محیط های دسکتاپ متمایز کند. به عنوان مثال، پد لمسی به عنوان یک فیدر متقاطع برای برنامه های DJ، ضبط ماوس برای بازی ها، و میانبرهای صفحه کلید گسترده برای کاربران صفحه کلید محور
صفحه کلید
روشی که برنامه شما به ورودی صفحهکلید پاسخ میدهد به یک تجربه خوب صفحه نمایش بزرگ کمک میکند. سه نوع ورودی صفحه کلید وجود دارد: ناوبری ، فشار دادن کلید ، و میانبر .
ناوبری
ناوبری صفحه کلید به ندرت در برنامه های لمسی اجرا می شود، اما کاربران زمانی که از یک برنامه استفاده می کنند و دستشان روی صفحه کلید است، انتظار آن را دارند. همچنین میتواند برای کاربرانی که نیازهای دسترسی به تلفنها، تبلتها، تاشوها و دستگاههای رومیزی دارند ضروری باشد.
برای بسیاری از برنامه ها، کلید پیکان ساده و پیمایش برگه تنها چیزی است که مورد نیاز است و عمدتاً به طور خودکار توسط فریم ورک اندروید مدیریت می شود. به عنوان مثال، نمای یک Button
به طور پیش فرض قابل فوکوس است و پیمایش صفحه کلید معمولاً باید بدون هیچ کد اضافی کار کند. برای فعال کردن پیمایش صفحهکلید برای نماهایی که بهطور پیشفرض قابل فوکوس نیستند، توسعهدهندگان باید آنها را بهعنوان قابل فوکوس علامتگذاری کنند، که میتواند به صورت برنامهریزی یا XML انجام شود، همانطور که در زیر نشان داده شده است. برای اطلاعات بیشتر به Focus Handling مراجعه کنید.
کاتلین
yourView.isFocusable = true
جاوا
yourView.setFocusable(true);
همچنین می توانید ویژگی focusable
را در فایل طرح بندی خود تنظیم کنید:
android:focusable="true"
هنگامی که فوکوس فعال می شود، چارچوب Android یک نقشه ناوبری برای همه نماهای قابل فوکوس بر اساس موقعیت آنها ایجاد می کند. این معمولاً همانطور که انتظار می رود کار می کند و نیازی به کار بیشتری نیست. زمانی که نقشه پیشفرض برای نیازهای یک برنامه صحیح نباشد، میتوان آن را به صورت زیر لغو کرد:
کاتلین
// Arrow keys yourView.nextFocusLeftId = R.id.view_to_left yourView.nextFocusRightId = R.id.view_to_right yourView.nextFocusTopId = R.id.view_above yourView.nextFocusBottomId = R.id.view_below // Tab key yourView.nextFocusForwardId = R.id.next_view
جاوا
// Arrow keys yourView.setNextFocusLeftId(R.id.view_to_left); yourView.setNextFocusRightId(R.id.view_to_left); yourView.setNextFocusTopId(R.id.view_to_left); yourView.setNextFocusBottomId(R.id.view_to_left); // Tab key yourView.setNextFocusForwardId(R.id.next_view);
این تمرین خوبی است که سعی کنید قبل از هر نسخه فقط با استفاده از صفحه کلید به تمام عملکردهای برنامه خود دسترسی داشته باشید. دسترسی به متداول ترین اقدامات بدون ورودی ماوس یا لمسی باید آسان باشد.
به یاد داشته باشید، پشتیبانی از صفحه کلید ممکن است برای کاربرانی که نیازهای دسترسی دارند ضروری باشد.
ضربه زدن به کلید
برای ورودی متنی که توسط صفحهکلید مجازی روی صفحه ( IME ) مانند EditText
مدیریت میشود، برنامهها باید همانطور که انتظار میرود در دستگاههای صفحهنمایش بزرگ بدون کار اضافی از سوی توسعهدهنده رفتار کنند. برای کلیدهایی که توسط چارچوب قابل پیش بینی نیست، برنامه ها باید خودشان رفتار را مدیریت کنند. این امر به ویژه برای برنامه هایی با نمای سفارشی صادق است.
برخی از نمونهها برنامههای چت هستند که از کلید enter برای ارسال پیام استفاده میکنند، برنامههای رسانهای که پخش را با کلید فاصله شروع و متوقف میکنند و بازیهایی که حرکت را با کلیدهای w، a، s و d کنترل میکنند.
اکثر برنامهها پاسخ تماس onKeyUp()
لغو میکنند و رفتار مورد انتظار را برای هر کد کلید دریافتی اضافه میکنند، همانطور که در زیر نشان داده شده است:
کاتلین
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { return when (keyCode) { KeyEvent.KEYCODE_ENTER -> { sendChatMessage() true } KeyEvent.KEYCODE_SPACE -> { playOrPauseMedia() true } else -> super.onKeyUp(keyCode, event) } }
جاوا
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_ENTER) { sendMessage(); return true; } else if (KeyEvent.KEYCODE_SPACE){ playOrPauseMedia(); return true; } else { return super.onKeyUp(keyCode, event); } }
یک رویداد onKeyUp
زمانی رخ می دهد که یک کلید آزاد شود. استفاده از این پاسخ تماس باعث میشود که برنامهها نیازی به پردازش چندین رویداد onKeyDown
نداشته باشند، اگر کلیدی به آرامی نگه داشته یا رها شود. بازیها و برنامههایی که میخواهند از لحظه فشار دادن یک کلید مطلع شوند یا انتظار دارند کاربران کلیدهای صفحهکلید را نگه دارند، میتوانند به دنبال رویداد onKeyDown()
بگردند و رویدادهای تکراری onKeyDown
را خودشان مدیریت کنند.
برای اطلاعات بیشتر در مورد ارائه پشتیبانی از صفحه کلید، به کنترل عملکردهای صفحه کلید مراجعه کنید.
میانبرها
هنگام استفاده از صفحه کلید سخت افزاری، میانبرهای متداول Ctrl، Alt و Shift مورد انتظار هستند. اگر برنامه ای آنها را پیاده سازی نکند، تجربه می تواند برای کاربران ناامید کننده باشد. کاربران پیشرفته همچنین از میانبرها برای کارهای خاص برنامه که اغلب استفاده می شوند قدردانی می کنند. میانبرها استفاده از برنامه را آسان تر می کند و آن را از برنامه هایی که میانبر ندارند متمایز می کند.
برخی از میانبرهای رایج عبارتند از Ctrl + S (ذخیره)، Ctrl + Z (لغو) و Ctrl + Shift + Z (دوباره). برای نمونه ای از میانبرهای پیشرفته تر، به فهرست کلیدهای میانبر VLC Media Player مراجعه کنید.
میانبرها را می توان با استفاده از dispatchKeyShortcutEvent()
پیاده سازی کرد. این همه ترکیبات متا کلید (Alt، Ctrl و Shift) را برای یک کد کلید معین قطع می کند. برای بررسی یک متاکلید خاص، از KeyEvent.isCtrlPressed()
, KeyEvent.isShiftPressed()
, KeyEvent.isAltPressed()
یا KeyEvent.hasModifiers()
استفاده کنید.
جدا کردن کد میانبر از سایر روشهای کنترل فشار کلید (مانند onKeyUp()
و onKeyDown()
) میتواند نگهداری کد را آسانتر کند و پذیرش پیشفرض کلیدهای متا را بدون نیاز به اجرای دستی بررسیهای متاکلید در هر موردی امکانپذیر میسازد. اجازه دادن به همه ترکیبهای متاکلید میتواند برای کاربرانی که به چیدمانهای صفحهکلید و سیستمعاملهای مختلف عادت دارند راحتتر باشد.
کاتلین
override fun dispatchKeyShortcutEvent(event: KeyEvent): Boolean { return when (event.keyCode) { KeyEvent.KEYCODE_O -> { openFile() // Ctrl+O, Shift+O, Alt+O true } KeyEvent.KEYCODE_Z-> { if (event.isCtrlPressed) { if (event.isShiftPressed) { redoLastAction() // Ctrl+Shift+Z pressed true } else { undoLastAction() // Ctrl+Z pressed true } } } else -> { return super.dispatchKeyShortcutEvent(event) } } }
جاوا
@Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_O) { openFile(); // Ctrl+O, Shift+O, Alt+O return true; } else if(event.getKeyCode() == KeyEvent.KEYCODE_Z) { if (event.isCtrlPressed()) { if (event.isShiftPressed()) { redoLastAction(); return true; } else { undoLastAction(); return true; } } } return super.dispatchKeyShortcutEvent(event); }
همچنین می توانید با بررسی KeyEvent.isCtrlPressed()
, KeyEvent.isShiftPressed()
یا KeyEvent.isAltPressed()
به همان روشی که در بالا ذکر شد، میانبرها را در onKeyUp()
پیاده سازی کنید. اگر متا-رفتار بیشتر تغییری در رفتار برنامه باشد تا یک میانبر، حفظ این امر آسان تر است. به عنوان مثال، زمانی که W به معنای "راه رفتن به جلو" و Shift + W به معنای "دویدن به جلو" است.
کاتلین
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { return when(keyCode) { KeyEvent.KEYCODE_W-> { if (event.isShiftPressed) { if (event.isCtrlPressed) { flyForward() // Ctrl+Shift+W pressed true } else { runForward() // Shift+W pressed true } } else { walkForward() // W pressed true } } else -> super.onKeyUp(keyCode, event) } }
جاوا
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_W) { if (event.isShiftPressed()) { if (event.isCtrlPressed()) { flyForward(); // Ctrl+Shift+W pressed return true; } else { runForward(); // Shift+W pressed return true; } } else { walkForward(); return true; } } return super.onKeyUp(keyCode, event); }
قلم
بسیاری از دستگاههای صفحهنمایش بزرگ دارای قلم هستند و برنامههای اندروید از آن به عنوان ورودی صفحه لمسی استفاده میکنند. ممکن است برخی از دستگاهها مانند Wacom Intuos دارای یک میز طراحی USB یا بلوتوث باشند. برنامههای Android میتوانند ورودی بلوتوث را دریافت کنند، اما با ورودی USB کار نمیکنند.
یک رویداد قلم به عنوان یک رویداد صفحه لمسی از طریق View.onTouchEvent()
یا View.onGenericMotionEvent()
گزارش می شود و حاوی یک MotionEvent.getSource()
از نوع SOURCE_STYLUS
است.
MotionEvent
همچنین حاوی داده های اضافی خواهد بود:
-
MotionEvent.getToolType()
TOOL_TYPE_FINGER
، TOOL_TYPE_STYLUS ، یاTOOL_TYPE_ERASER
را بسته به ابزاری که با سطح تماس برقرار کرده است، برمی گرداند. -
MotionEvent.getPressure()
فشار فیزیکی اعمال شده به قلم استایلوس را گزارش می دهد (در صورت پشتیبانی) -
MotionEvent.getAxisValue()
باMotionEvent.AXIS_TILT
وMotionEvent.AXIS_ORIENTATION
که می تواند برای خواندن شیب فیزیکی و جهت گیری قلم (در صورت پشتیبانی) استفاده شود.
نکات تاریخی
Android رویدادهای ورودی را دستهبندی میکند و آنها را یک بار در هر فریم ارائه میکند. قلم استایلوس می تواند رویدادها را با فرکانس های بسیار بالاتر از نمایشگر گزارش دهد. هنگام ایجاد برنامههای طراحی، مهم است که با استفاده از getHistorical
API رویدادهایی را که ممکن است در گذشته نزدیک باشند بررسی کنید:
-
MotionEvent.getHistoricalX()
-
MotionEvent.getHistoricalY()
-
MotionEvent.getHistoricalPressure()
-
MotionEvent.getHistoricalAxisValue()
رد کف دست
هنگامی که کاربران با استفاده از قلم طراحی می کنند، می نویسند یا با برنامه شما تعامل می کنند، گاهی اوقات صفحه را با کف دست لمس می کنند. رویداد لمسی (روی ACTION_DOWN
یا ACTION_POINTER_DOWN
تنظیم شده است) را می توان قبل از اینکه سیستم لمس ناخواسته کف دست را تشخیص دهد و نادیده بگیرد، به برنامه شما گزارش شود.
Android رویدادهای لمس کف دست را با ارسال MotionEvent
لغو میکند. اگر برنامه شما ACTION_CANCEL
را دریافت کرد، حرکت را لغو کنید. اگر برنامه شما ACTION_POINTER_UP
را دریافت کرد، بررسی کنید که آیا FLAG_CANCELED
تنظیم شده است یا خیر. اگر چنین است، ژست را لغو کنید.
فقط FLAG_CANCELED
را بررسی نکنید. از Android 13، برای راحتی، سیستم FLAG_CANCELED
برای رویدادهای ACTION_CANCEL
تنظیم میکند، اما نسخههای قبلی این کار را نمیکنند.
اندروید 12
در Android 12 (سطح API 32) و پایینتر، تشخیص رد کف دست فقط برای رویدادهای لمسی تک اشارهای امکانپذیر است. اگر لمس کف دست تنها نشانگر باشد، سیستم با تنظیم ACTION_CANCEL
روی شی رویداد حرکتی، رویداد را لغو میکند. اگر سایر نشانگرها پایین باشند، سیستم ACTION_POINTER_UP
را تنظیم می کند که برای تشخیص رد کف دست کافی نیست.
اندروید 13
در Android 13 (سطح API 33) و بالاتر، اگر تنها اشارهگر لمس کف دست باشد، سیستم با تنظیم ACTION_CANCEL
و FLAG_CANCELED
روی شی رویداد حرکتی، رویداد را لغو میکند. اگر سایر نشانگرها پایین باشند، سیستم ACTION_POINTER_UP
و FLAG_CANCELED
را تنظیم میکند.
هر زمان که برنامه شما یک رویداد حرکتی با ACTION_POINTER_UP
دریافت کرد، FLAG_CANCELED
را بررسی کنید تا مشخص شود آیا رویداد نشان دهنده رد کف دست (یا لغو رویداد دیگر) است.
برنامه های یادداشت برداری
ChromeOS هدف خاصی دارد که برنامههای ثبتشده یادداشتبرداری را در اختیار کاربران قرار میدهد. برای ثبت یک برنامه به عنوان یک برنامه یادداشت برداری، موارد زیر را به مانیفست اندروید اضافه کنید:
<intent-filter>
<action android:name="org.chromium.arc.intent.action.CREATE_NOTE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
هنگامی که یک برنامه ثبت شده است، کاربر می تواند آن را به عنوان برنامه پیش فرض یادداشت برداری انتخاب کند. وقتی یادداشت جدیدی درخواست میشود، برنامه باید یک یادداشت خالی آماده برای ورودی قلم ایجاد کند. هنگامی که کاربر می خواهد یک تصویر را حاشیه نویسی کند (مانند یک اسکرین شات یا تصویر بارگیری شده)، برنامه با ClipData
شامل یک یا چند مورد با content://
URI راه اندازی می شود. برنامه باید یادداشتی ایجاد کند که از اولین تصویر پیوست شده به عنوان تصویر پسزمینه استفاده کند و حالتی را وارد کند که کاربر بتواند با یک قلم روی صفحه نمایش بکشد.
اهداف یادداشت برداری را بدون قلم تست کنید
برای آزمایش اینکه آیا یک برنامه بدون قلم فعال به اهداف یادداشتبرداری به درستی پاسخ میدهد، از روش زیر برای نمایش گزینههای یادداشتبرداری در ChromeOS استفاده کنید:
- به حالت توسعه دهنده بروید و دستگاه را قابل نوشتن کنید
- Ctrl + Alt + F2 را فشار دهید تا ترمینال باز شود
- دستور
sudo vi /etc/chrome_dev.conf
را اجرا کنید -
i
برای ویرایش فشار دهید و--ash-enable-palette
به خط جدیدی در انتهای فایل اضافه کنید - با فشار دادن Esc و سپس تایپ :, w, q و فشردن Enter ذخیره کنید
- برای بازگشت به رابط کاربری عادی ChromeOS، Ctrl + Alt + F1 را فشار دهید
- از سیستم خارج شوید و دوباره وارد شوید
اکنون باید یک منوی قلم در قفسه وجود داشته باشد:
- روی دکمه قلم در قفسه ضربه بزنید و یادداشت جدید را انتخاب کنید. این باید یک یادداشت نقاشی خالی را باز کند.
- اسکرین شات بگیرید از قفسه، دکمه قلم > ضبط صفحه را انتخاب کنید یا یک تصویر را دانلود کنید. باید گزینه "Annotate image" در اعلان وجود داشته باشد. این باید برنامه را با تصویر آماده برای حاشیه نویسی راه اندازی کند.
پشتیبانی از ماوس و تاچ پد
اکثر برنامهها معمولاً فقط به سه رویداد بزرگ صفحهنمایش نیاز دارند: کلیک راست ، شناور ، و کشیدن و رها کردن .
کلیک راست کنید
هر اقدامی که باعث میشود برنامه یک منوی زمینه را نشان دهد، مانند لمس و نگهداشتن یک مورد فهرست، باید به رویدادهای کلیک راست نیز واکنش نشان دهد. برای مدیریت رویدادهای کلیک راست، برنامهها باید یک View.OnContextClickListener
ثبت کنند. برای جزئیات در مورد ساخت منوی زمینه، به ایجاد منوهای متنی مراجعه کنید.
کاتلین
yourView.setOnContextClickListener { showContextMenu() true }
جاوا
yourView.setOnContextClickListener(v -> { showContextMenu(); return true; });
شناور
توسعهدهندگان میتوانند با مدیریت رویدادهای شناور، طرحبندی برنامههای خود را صیقلیتر و استفاده آسانتر کنند. این به ویژه برای نماهای سفارشی صادق است. دو نمونه رایج در این مورد عبارتند از:
- با تغییر نماد اشاره گر ماوس به کاربران نشان می دهد که آیا یک عنصر رفتار تعاملی دارد، مانند قابل کلیک یا قابل ویرایش بودن
- افزودن بازخورد بصری به موارد موجود در یک لیست یا شبکه بزرگ هنگامی که نشانگر روی آنها قرار دارد
کاتلین
// Change the icon to a "hand" pointer on hover, // Highlight the view by changing the background. yourView.setOnHoverListener { view, _ -> addVisualHighlighting(true) view.pointerIcon = PointerIcon.getSystemIcon(view.context, PointerIcon.TYPE_HAND) false // listener did not consume the event. }
جاوا
yourView.setOnHoverListener((view, event) -> { addVisualHighlighting(true); view.setPointerIcon(PointerIcon .getSystemIcon(view.getContext(), PointerIcon.TYPE_HAND)); return true; });
بکشید و رها کنید
در یک محیط چند پنجره ای، کاربران انتظار دارند که بتوانند آیتم ها را بین برنامه ها بکشند و رها کنند. این برای دستگاههای رومیزی و همچنین تبلتها، تلفنها و دستگاههای تاشو در حالت تقسیم صفحه صادق است.
توسعه دهندگان باید در نظر بگیرند که آیا کاربران احتمالاً موارد را به برنامه خود می کشند یا خیر. برخی از مثالهای رایج عبارتند از: ویرایشگرهای عکس باید انتظار دریافت عکسها را داشته باشند، پخشکنندههای صوتی باید انتظار دریافت فایلهای صوتی را داشته باشند، و برنامههای طراحی باید انتظار دریافت عکسها را داشته باشند.
برای افزودن پشتیبانی کشیدن و رها کردن، مستندات Android Drag and drop را دنبال کنید و به این پست وبلاگ ChromeOS نگاهی بیندازید.
ملاحظات ویژه برای ChromeOS
- به خاطر داشته باشید که از طریق
requestDragAndDropPermissions
برای دسترسی به مواردی که از خارج از برنامه به داخل کشیده شده اند، مجوز درخواست کنید. - یک مورد باید دارای پرچم
View.DRAG_FLAG_GLOBAL
باشد تا به برنامه های دیگر کشیده شود
پشتیبانی از اشاره گر پیشرفته
برنامههایی که مدیریت پیشرفته ورودی ماوس و پد لمسی را انجام میدهند باید از مستندات Android برای View.onGenericMotionEvent()
پیروی کنند و از MotionEvent.getSource()
برای تمایز بین SOURCE_MOUSE
و SOURCE_TOUCHSCREEN
استفاده کنند.
MotionEvent
برای اجرای رفتار مورد نیاز بررسی کنید:
- Movement رویدادهای
ACTION_HOVER_MOVE
را ایجاد می کند. - دکمهها رویدادهای
ACTION_BUTTON_PRESS
وACTION_BUTTON_RELEASE
را ایجاد میکنند. همچنین می توانید با استفاده ازgetButtonState()
وضعیت فعلی همه دکمه های ماوس/پد آهنگ را بررسی کنید. - پیمایش چرخ ماوس رویدادهای
ACTION_SCROLL
را ایجاد می کند.
کنترلرهای بازی
برخی از دستگاه های اندرویدی با صفحه نمایش بزرگ تا چهار کنترلر بازی را پشتیبانی می کنند. توسعهدهندگان باید از APIهای استاندارد کنترلکننده بازی اندروید برای مدیریت آنها استفاده کنند (به پشتیبانی از کنترلکنندههای بازی مراجعه کنید).
دکمه ها به دنبال یک نگاشت مشترک به مقادیر مشترک نگاشت می شوند. متأسفانه، همه سازندگان کنترلرهای بازی از قوانین نقشه برداری یکسانی پیروی نمی کنند. اگر به کاربران اجازه دهید تا نگاشت های مختلف کنترلر محبوب را انتخاب کنند، می توانید تجربه بسیار بهتری ارائه دهید. برای اطلاعات بیشتر به فرآیند فشار دادن دکمه گیم پد مراجعه کنید.
حالت ترجمه ورودی
ChromeOS حالت ترجمه ورودی را به طور پیشفرض فعال میکند. برای اکثر برنامههای اندروید، این حالت به برنامهها کمک میکند تا در محیط دسکتاپ همانطور که انتظار میرود کار کنند. برخی از نمونهها عبارتند از فعال کردن خودکار پیمایش دو انگشتی روی صفحه لمسی، پیمایش چرخ ماوس، و نگاشت مختصات صفحه نمایش خام به مختصات پنجره. به طور کلی، توسعه دهندگان اپلیکیشن نیازی به پیاده سازی هیچ یک از این رفتارها ندارند.
اگر برنامهای رفتار ورودی سفارشی را پیادهسازی کند، بهعنوان مثال، یک عمل چسباندن صفحه لمسی با دو انگشت سفارشی را تعریف کند، یا این ترجمههای ورودی رویدادهای ورودی مورد انتظار برنامه را ارائه نمیکنند، میتوانید با افزودن برچسب زیر به Android حالت ترجمه ورودی را غیرفعال کنید. آشکار:
<uses-feature
android:name="android.hardware.type.pc"
android:required="false" />
منابع اضافی
{% کلمه به کلمه %}برای شما توصیه می شود
- توجه: وقتی جاوا اسکریپت خاموش است، متن پیوند نمایش داده می شود
- پشتیبانی از قلم را در یک برنامه اندرویدی تقویت کنید
- ویرایشگرهای متن سفارشی
- پشتیبانی از تبلت و صفحه نمایش بزرگ