مطالب زیر برای توسعه دهندگان برنامه است.
برای اینکه برنامه خود را به صورت چرخشی پشتیبانی کنید، باید:
- یک
FocusParkingView
در طرح فعالیت مربوطه قرار دهید. - از نماهایی که قابل تمرکز هستند (یا نیستند) اطمینان حاصل کنید.
- از
FocusArea
استفاده کنید تا همه نماهای قابل فوکوس خود را بپیچید، به جزFocusParkingView
.
پس از اینکه محیط خود را برای توسعه برنامه های دارای قابلیت چرخشی تنظیم کردید، هر یک از این وظایف در زیر به تفصیل توضیح داده شده است.
یک کنترلر چرخشی راه اندازی کنید
قبل از اینکه بتوانید توسعه برنامههای دارای قابلیت چرخشی را شروع کنید، به یک کنترلر چرخشی یا یک پایه نیاز دارید. شما گزینه های شرح داده شده در زیر را دارید.
شبیه ساز
source build/envsetup.sh && lunch car_x86_64-userdebug m -j emulator -wipe-data -no-snapshot -writable-system
همچنین می توانید از aosp_car_x86_64-userdebug
استفاده کنید.
برای دسترسی به کنترلر چرخشی شبیه سازی شده:
- روی سه نقطه در پایین نوار ابزار ضربه بزنید:
شکل 1. به کنترل کننده چرخشی شبیه سازی شده دسترسی پیدا کنید - در پنجره کنترلهای توسعهیافته Car rotary را انتخاب کنید:
شکل 2. Car rotary را انتخاب کنید
صفحه کلید USB
- یک صفحه کلید USB را به دستگاه خود وصل کنید که دارای سیستم عامل Android Automotive (AAOS) است، در برخی موارد، این کار از نمایش صفحه کلید روی صفحه جلوگیری می کند.
- از یک
userdebug
یاeng
build استفاده کنید. - فعال کردن فیلتر رویداد کلیدی:
adb shell settings put secure android.car.ROTARY_KEY_EVENT_FILTER 1
- برای یافتن کلید مربوطه برای هر عمل به جدول زیر مراجعه کنید:
کلید عمل چرخشی س در خلاف جهت عقربه های ساعت بچرخانید E در جهت عقربه های ساعت بچرخانید الف به چپ تکان دهید D به سمت راست تکان دهید دبلیو تلنگر بزنید اس به پایین تلنگر بزنید F یا کاما دکمه مرکزی R یا Esc دکمه برگشت
دستورات ADB
می توانید از دستورات car_service
برای تزریق رویدادهای ورودی چرخشی استفاده کنید. این دستورات را می توان در دستگاه هایی اجرا کرد که سیستم عامل Android Automotive (AAOS) یا شبیه ساز را اجرا می کنند.
دستورات car_service | ورودی چرخشی |
---|---|
adb shell cmd car_service inject-rotary | در خلاف جهت عقربه های ساعت بچرخانید |
adb shell cmd car_service inject-rotary -c true | در جهت عقربه های ساعت بچرخانید |
adb shell cmd car_service inject-rotary -dt 100 50 | چندین بار در خلاف جهت عقربه های ساعت بچرخانید (100 میلی ثانیه قبل و 50 میلی ثانیه قبل) |
adb shell cmd car_service inject-key 282 | به چپ تکان دهید |
adb shell cmd car_service inject-key 283 | به سمت راست تکان دهید |
adb shell cmd car_service inject-key 280 | تلنگر بزنید |
adb shell cmd car_service inject-key 281 | به پایین تلنگر بزنید |
adb shell cmd car_service inject-key 23 | روی دکمه مرکزی کلیک کنید |
adb shell input keyevent inject-key 4 | دکمه برگشت را کلیک کنید |
کنترل کننده چرخشی OEM
هنگامی که سخت افزار کنترلر چرخشی شما آماده و در حال اجرا است، این واقعی ترین گزینه است. این به ویژه برای تست چرخش سریع مفید است.
FocusParkingView
FocusParkingView
یک نمای شفاف در کتابخانه UI Car (car-ui-library) است. RotaryService
از آن برای پشتیبانی از ناوبری کنترلر چرخشی استفاده می کند. FocusParkingView
باید اولین نمای قابل فوکوس در طرح باشد. باید خارج از همه FocusArea
قرار گیرد. هر پنجره باید یک FocusParkingView
داشته باشد. اگر قبلاً از طرحبندی پایه car-ui-library که حاوی FocusParkingView
است استفاده میکنید، نیازی نیست FocusParkingView
دیگری اضافه کنید. در زیر نمونه ای از FocusParkingView
در RotaryPlayground
نشان داده شده است.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <com.android.car.ui.FocusParkingView android:layout_width="wrap_content" android:layout_height="wrap_content"/> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"/> </FrameLayout>
در اینجا دلایلی وجود دارد که شما به FocusParkingView
نیاز دارید:
- هنگامی که فوکوس در پنجره دیگری تنظیم می شود، Android به طور خودکار فوکوس را پاک نمی کند. اگر سعی کنید فوکوس را در پنجره قبلی پاک کنید، اندروید نمای آن پنجره را مجدداً فوکوس میکند که منجر به فوکوس شدن همزمان دو پنجره میشود. افزودن
FocusParkingView
به هر پنجره می تواند این مشکل را برطرف کند. این نما شفاف است و برجسته کردن فوکوس پیشفرض آن غیرفعال است، به طوری که بدون توجه به فوکوس یا عدم تمرکز، برای کاربر نامرئی است. می تواند فوکوس را بگیرد تاRotaryService
بتواند فوکوس را روی آن پارک کند تا برجسته شدن فوکوس حذف شود. - اگر فقط یک
FocusArea
در پنجره فعلی وجود داشته باشد، چرخاندن کنترلر درFocusArea
باعث می شود تاRotaryService
فوکوس را از نمای سمت راست به نمای سمت چپ (و بالعکس) منتقل کند. افزودن این نما به هر پنجره می تواند مشکل را برطرف کند. هنگامی کهRotaryService
تعیین می کند که هدف فوکوس یکFocusParkingView
است، می تواند تعیین کند که یک wrap-around در شرف وقوع است که در آن نقطه با عدم حرکت فوکوس از چرخش دور جلوگیری می کند. - هنگامی که کنترل چرخشی یک برنامه را راه اندازی می کند، Android اولین نمای قابل فوکوس را متمرکز می کند که همیشه
FocusParkingView
است.FocusParkingView
نمای بهینه برای فوکوس را تعیین می کند و سپس فوکوس را اعمال می کند.
نماهای قابل تمرکز
RotaryService
مبتنی بر مفهوم موجود چارچوب Android از تمرکز دید است که به زمانی برمی گردد که تلفن ها دارای صفحه کلید فیزیکی و D-pad بودند. ویژگی android:nextFocusForward
موجود برای چرخشی تغییر کاربری داده شده است (به سفارشی سازی FocusArea مراجعه کنید)، اما android:nextFocusLeft
، android:nextFocusRight
، android:nextFocusUp
و android:nextFocusDown
اینگونه نیستند.
RotaryService
فقط بر روی نماهایی تمرکز می کند که قابل فوکوس هستند. برخی از نماها، مانند Button
s، معمولاً قابل فوکوس هستند. سایرین، مانند TextView
s و ViewGroup
s، معمولاً اینطور نیستند. نماهای قابل کلیک به طور خودکار قابل فوکوس هستند و نماها زمانی که شنونده کلیک داشته باشند به طور خودکار قابل کلیک هستند. اگر این منطق خودکار منجر به فوکوس پذیری مورد نظر می شود، نیازی نیست به صراحت قابلیت فوکوس پذیری نما را تنظیم کنید. اگر منطق خودکار به فوکوسپذیری مورد نظر منجر نمیشود، ویژگی android:focusable
روی true
یا false
تنظیم کنید، یا با برنامه View.setFocusable(boolean)
قابلیت تمرکز نمای را تنظیم کنید. برای اینکه RotaryService
روی آن تمرکز کند، یک View باید شرایط زیر را داشته باشد:
- قابل تمرکز
- فعال شد
- قابل مشاهده است
- مقادیر غیر صفر برای عرض و ارتفاع داشته باشید
اگر یک نما تمام این الزامات را برآورده نکند، برای مثال یک دکمه قابل فوکوس اما غیرفعال، کاربر نمی تواند از کنترل چرخشی برای فوکوس روی آن استفاده کند. اگر میخواهید روی نماهای غیرفعال تمرکز کنید، به جای android:state_enabled
از یک حالت سفارشی استفاده کنید تا نحوه نمایش نما را کنترل کنید بدون اینکه نشان دهید که Android باید آن را غیرفعال در نظر بگیرد. برنامه شما میتواند به کاربر اطلاع دهد که چرا هنگام ضربه زدن، نما غیرفعال است. بخش بعدی نحوه انجام این کار را توضیح می دهد.
حالت سفارشی
برای افزودن حالت سفارشی:
- برای افزودن یک ویژگی سفارشی به نمای خود. به عنوان مثال، برای افزودن یک حالت سفارشی
state_rotary_enabled
به کلاسCustomView
، از:<declare-styleable name="CustomView"> <attr name="state_rotary_enabled" format="boolean" /> </declare-styleable>
- برای ردیابی این وضعیت، یک متغیر نمونه به نمای خود به همراه متدهای دسترسی اضافه کنید:
private boolean mRotaryEnabled; public boolean getRotaryEnabled() { return mRotaryEnabled; } public void setRotaryEnabled(boolean rotaryEnabled) { mRotaryEnabled = rotaryEnabled; }
- برای خواندن مقدار مشخصه خود هنگام ایجاد نمای شما:
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomView); mRotaryEnabled = a.getBoolean(R.styleable.CustomView_state_rotary_enabled);
- در کلاس view خود، متد
onCreateDrawableState()
را نادیده بگیرید و در صورت لزوم حالت سفارشی را اضافه کنید. به عنوان مثال:@Override protected int[] onCreateDrawableState(int extraSpace) { if (mRotaryEnabled) extraSpace++; int[] drawableState = super.onCreateDrawableState(extraSpace); if (mRotaryEnabled) { mergeDrawableStates(drawableState, { R.attr.state_rotary_enabled }); } return drawableState; }
- کاری کنید که کنترل کننده کلیک نمای شما بسته به وضعیت آن عملکرد متفاوتی داشته باشد. به عنوان مثال، کنترل کننده کلیک ممکن است کاری انجام ندهد یا زمانی که
mRotaryEnabled
false
است، یک نان تست ظاهر شود. - برای اینکه دکمه غیرفعال به نظر برسد، در پسزمینه نمای خود، به جای android
app:state_rotary_enabled
android:state_enabled
استفاده کنید. اگر قبلاً آن را ندارید، باید اضافه کنید:xmlns:app="http://schemas.android.com/apk/res-auto"
- اگر نمای شما در هر طرحبندی غیرفعال است،
android:enabled="false"
را باapp:state_rotary_enabled="false"
جایگزین کنید و سپس فضای نامapp
را مانند بالا اضافه کنید. - اگر نمای شما از نظر برنامهنویسی غیرفعال است، تماسهای
setEnabled()
را با تماسsetRotaryEnabled()
جایگزین کنید.
Focus Area
از FocusAreas
برای تقسیم نماهای قابل تمرکز به بلوکها استفاده کنید تا پیمایش آسانتر شود و با سایر برنامهها سازگار باشد. به عنوان مثال، اگر برنامه شما دارای یک نوار ابزار است، نوار ابزار باید در یک FocusArea
مجزا از بقیه برنامه شما باشد. نوارهای برگه و سایر عناصر ناوبری نیز باید از بقیه برنامه جدا شوند. فهرستهای بزرگ معمولاً باید FocusArea
خاص خود را داشته باشند. در غیر این صورت، کاربران باید در کل لیست بچرخند تا به برخی از نماها دسترسی داشته باشند.
FocusArea
یک زیر کلاس از LinearLayout
در car-ui-library است. هنگامی که این ویژگی فعال است، FocusArea
زمانی که یکی از نوادگان آن فوکوس شده است، یک نقطه برجسته میکشد. برای کسب اطلاعات بیشتر، به سفارشیسازی برجستهسازی فوکوس مراجعه کنید.
هنگام ایجاد یک بلوک ناوبری در فایل طرح بندی، اگر قصد دارید از یک LinearLayout
به عنوان ظرفی برای آن بلوک استفاده کنید، به جای آن از FocusArea
استفاده کنید. در غیر این صورت، بلوک را در یک FocusArea
بپیچید.
یک FocusArea
در FocusArea
دیگر قرار ندهید . انجام این کار منجر به رفتار ناوبری نامشخص می شود. اطمینان حاصل کنید که همه نماهای قابل فوکوس در یک FocusArea
تودرتو هستند.
نمونه ای از FocusArea
در RotaryPlayground
در زیر نشان داده شده است:
<com.android.car.ui.FocusArea android:layout_margin="16dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true"> </EditText> </com.android.car.ui.FocusArea>
FocusArea
به شرح زیر عمل می کند:
-
RotaryService
هنگام مدیریت عملکردهای چرخش و حرکت دادن، به دنبال نمونه هایی ازFocusArea
در سلسله مراتب view می گردد. - هنگام دریافت یک رویداد چرخشی،
RotaryService
فوکوس را به نمای دیگری منتقل می کند که می تواند در همانFocusArea
تمرکز کند. - هنگام دریافت یک رویداد نوج،
RotaryService
فوکوس را به نمای دیگری منتقل می کند که می تواند درFocusArea
دیگر (معمولاً مجاور) تمرکز کند.
اگر هیچ FocusAreas
در طرح بندی خود وارد نکنید، نمای ریشه به عنوان یک ناحیه تمرکز ضمنی در نظر گرفته می شود. کاربر نمی تواند برای پیمایش در برنامه تلنگر بزند. در عوض، آنها از طریق تمام نمای های قابل فوکوس می چرخند، که ممکن است برای گفتگوها کافی باشد.
سفارشی سازی FocusArea
برای سفارشی کردن ناوبری چرخشی می توان از دو ویژگی View استاندارد استفاده کرد:
-
android:nextFocusForward
به توسعه دهندگان برنامه اجازه می دهد تا ترتیب چرخش را در یک ناحیه فوکوس مشخص کنند. این همان مشخصه ای است که برای کنترل ترتیب Tab برای پیمایش صفحه کلید استفاده می شود. از این ویژگی برای ایجاد یک حلقه استفاده نکنید . در عوض، ازapp:wrapAround
(به زیر مراجعه کنید) برای ایجاد یک حلقه استفاده کنید. -
android:focusedByDefault
به توسعه دهندگان برنامه اجازه می دهد نمای فوکوس پیش فرض را در پنجره مشخص کنند. از این ویژگی وapp:defaultFocus
(به زیر مراجعه کنید) در همانFocusArea
استفاده نکنید .
FocusArea
همچنین برخی از ویژگی ها را برای سفارشی کردن ناوبری چرخشی تعریف می کند. مناطق فوکوس ضمنی را نمی توان با این ویژگی ها سفارشی کرد.
- ( اندروید 11 QPR3، اندروید 11 ماشین، اندروید 12 )
app:defaultFocus
را می توان برای تعیین شناسه نمای اصلی قابل فوکوس استفاده کرد، که وقتی کاربر به اینFocusArea
اشاره می کند باید روی آن متمرکز شود. - ( اندروید 11 QPR3، اندروید 11 ماشین، اندروید 12 )
app:defaultFocusOverridesHistory
را می توان رویtrue
تنظیم کرد تا نمای مشخص شده در بالا تمرکز داشته باشد، حتی اگر با تاریخچه نشان دهد نمای دیگری در اینFocusArea
روی آن متمرکز شده بود. - ( اندروید 12 )
ازapp:nudgeLeftShortcut
،app:nudgeRightShortcut
،app:nudgeUpShortcut
، وapp:nudgeDownShortcut
برای تعیین شناسه نمای اصلی قابل فوکوس استفاده کنید، که وقتی کاربر در جهت معینی حرکت میکند باید روی آن متمرکز شود. برای کسب اطلاعات بیشتر، به محتوای میانبرهای نوج زیر مراجعه کنید.( Android 11 QPR3، Android 11 Car، در Android 12 منسوخ شده است )
app:nudgeShortcut
وapp:nudgeShortcutDirection
تنها از یک میانبر nudge پشتیبانی می کنند. - ( اندروید 11 QPR3، اندروید 11 ماشین، اندروید 12 )
برای فعال کردن چرخش در اینFocusArea
،app:wrapAround
را می توان رویtrue
تنظیم کرد. این معمولاً زمانی استفاده می شود که نماها در یک دایره یا بیضی مرتب شده باشند. - ( اندروید 11 QPR3، اندروید 11 ماشین، اندروید 12 )
برای تنظیم لایه هایلایت در اینFocusArea
، ازapp:highlightPaddingStart
،app:highlightPaddingEnd
،app:highlightPaddingTop
،app:highlightPaddingBottom
،app:highlightPaddingHorizontal
وapp:highlightPaddingVertical
استفاده کنید. - ( اندروید 11 QPR3، اندروید 11 ماشین، اندروید 12 )
برای تنظیم مرزهای درک شده اینFocusArea
برای یافتن یک هدف حرکتی، ازapp:startBoundOffset
،app:endBoundOffset
،app:topBoundOffset
،app:bottomBoundOffset
،app:horizontalBoundOffset
، وapp:verticalBoundOffset
استفاده کنید. - ( اندروید 11 QPR3، اندروید 11 ماشین، اندروید 12 )
برای مشخص کردن صریح شناسه یکFocusArea
(یا مناطق) مجاور در جهتهای داده شده، ازapp:nudgeLeft
،app:nudgeRight
،app:nudgeUp
وapp:nudgeDown
استفاده کنید. وقتی جستجوی هندسی که به طور پیشفرض استفاده میشود، هدف مورد نظر را پیدا نمیکند، از این استفاده کنید.
Nudging معمولاً بین Focus Areas حرکت می کند. اما با میانبرهای اشارهای، گاهی اوقات حرکت دادن ابتدا در یک FocusArea
حرکت میکند، به طوری که کاربر ممکن است برای پیمایش به FocusArea
بعدی نیاز داشته باشد دو بار ضربه بزند. میانبرهای Nudge زمانی مفید هستند که یک FocusArea
شامل یک لیست طولانی و به دنبال آن یک دکمه عمل شناور باشد ، مانند مثال زیر:
![میانبر اشاره](https://source.android.com/static/docs/automotive/images/rotary_03.png?authuser=2&hl=fa)
بدون میانبر nudge، کاربر باید در کل لیست بچرخد تا به FAB برسد.
سفارشی سازی برجسته فوکوس
همانطور که در بالا ذکر شد، RotaryService
بر اساس مفهوم موجود در چارچوب Android از تمرکز دیدگاه است. هنگامی که کاربر میچرخد و حرکت میدهد، RotaryService
فوکوس را به اطراف منتقل میکند، یک نمای را فوکوس میکند و دیگری را از حالت فوکوس خارج میکند. در اندروید، زمانی که یک نما فوکوس می شود، اگر نمای:
- برجسته تمرکز خود را مشخص کرده است، آندروید برجسته فوکوس نمای را می کشد.
- برجستهسازی فوکوس را مشخص نمیکند، و برجستهسازی پیشفرض فوکوس غیرفعال نیست، اندروید برجستهسازی فوکوس پیشفرض را برای نما ترسیم میکند.
برنامه هایی که برای لمس طراحی شده اند معمولاً نقاط برجسته فوکوس مناسب را مشخص نمی کنند.
برجستهسازی پیشفرض فوکوس توسط چارچوب Android ارائه میشود و میتواند توسط OEM لغو شود. توسعه دهندگان برنامه زمانی آن را دریافت می کنند که طرح زمینه ای که استفاده می کنند از Theme.DeviceDefault
مشتق شده باشد.
برای تجربه کاربری ثابت، هر زمان که ممکن است به برجسته کردن فوکوس پیشفرض تکیه کنید. اگر به برجستهسازی فوکوس سفارشی (مثلاً گرد یا قرصشکل) نیاز دارید، یا اگر از موضوعی استفاده میکنید که از Theme.DeviceDefault
مشتق نشده است، از منابع car-ui-library برای مشخص کردن هایلایت فوکوس خودتان استفاده کنید. هر نما
برای تعیین برجستهسازی فوکوس سفارشی برای یک نما، پسزمینه یا پیشزمینه قابل ترسیم نما را به قابل ترسیمی تغییر دهید که وقتی نما روی آن فوکوس میشود، متفاوت باشد. به طور معمول، شما پس زمینه را تغییر می دهید. ترسیم زیر، اگر به عنوان پسزمینه برای نمای مربعی استفاده شود، برجسته فوکوس گرد ایجاد میکند:
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_focused="true" android:state_pressed="true"> <shape android:shape="oval"> <solid android:color="@color/car_ui_rotary_focus_pressed_fill_color"/> <stroke android:width="@dimen/car_ui_rotary_focus_pressed_stroke_width" android:color="@color/car_ui_rotary_focus_pressed_stroke_color"/> </shape> </item> <item android:state_focused="true"> <shape android:shape="oval"> <solid android:color="@color/car_ui_rotary_focus_fill_color"/> <stroke android:width="@dimen/car_ui_rotary_focus_stroke_width" android:color="@color/car_ui_rotary_focus_stroke_color"/> </shape> </item> <item> <ripple...> ... </ripple> </item> </selector>
( Android 11 QPR3, Android 11 Car, Android 12 ) منابع پررنگ در نمونه بالا منابع تعریف شده توسط car-ui-library را شناسایی می کند. OEM این موارد را لغو می کند تا با برجسته سازی پیش فرضی که مشخص می کنند مطابقت داشته باشد. این تضمین میکند که وقتی کاربر بین یک نمای با برجستهسازی فوکوس سفارشی و یک نمای با برجستهسازی فوکوس پیشفرض حرکت میکند، رنگ برجسته فوکوس، عرض ضربه و غیره تغییر نمیکند. آخرین مورد یک ریپل است که برای لمس استفاده می شود. مقادیر پیش فرض استفاده شده برای منابع پررنگ به صورت زیر ظاهر می شوند:
![مقادیر پیشفرض برای منابع پررنگ](https://source.android.com/static/docs/automotive/images/rotary_04.png?authuser=2&hl=fa)
علاوه بر این، هنگامی که به دکمهای رنگ پسزمینه ثابت داده میشود تا توجه کاربر را جلب کند، برجستهسازی فوکوس سفارشی فراخوانی میشود، مانند مثال زیر. این می تواند برجسته شدن فوکوس را دشوار کند. در این شرایط، با استفاده از رنگ های ثانویه ، یک برجسته فوکوس سفارشی را مشخص کنید:
![]() |
- ( اندروید 11 QPR3، اندروید 11 ماشین، اندروید 12 )
car_ui_rotary_focus_fill_secondary_color
car_ui_rotary_focus_stroke_secondary_color
- ( اندروید 12 )
car_ui_rotary_focus_pressed_fill_secondary_color
car_ui_rotary_focus_pressed_stroke_secondary_color
به عنوان مثال:
![]() | ![]() | |
متمرکز، نه تحت فشار | متمرکز، فشرده |
پیمایش چرخشی
اگر برنامه شما از RecyclerView
s استفاده می کند، باید به جای آن CarUiRecyclerView
استفاده کنید. این تضمین میکند که UI شما با دیگران سازگار است، زیرا سفارشیسازی OEM برای همه CarUiRecyclerView
اعمال میشود.
اگر عناصر موجود در لیست شما همه قابل تمرکز هستند، لازم نیست کار دیگری انجام دهید. پیمایش چرخشی، فوکوس را از میان عناصر موجود در لیست حرکت میدهد و فهرست برای نمایان شدن عنصر تازه فوکوسشده، پیمایش میکند.
( اندروید 11 QPR3، اندروید 11 ماشین، اندروید 12 )
اگر ترکیبی از عناصر قابل فوکوس و غیرقابل تمرکز وجود دارد، یا اگر همه عناصر غیرقابل تمرکز هستند، میتوانید پیمایش چرخشی را فعال کنید، که به کاربر اجازه میدهد از کنترلکننده چرخشی استفاده کند تا به تدریج در لیست بدون رد شدن از موارد غیرقابل تمرکز حرکت کند. برای فعال کردن پیمایش چرخشی، ویژگی app:rotaryScrollEnabled
روی true
تنظیم کنید.
( اندروید 11 QPR3، اندروید 11 ماشین، اندروید 12 )
میتوانید اسکرول چرخشی را در هر نمای قابل پیمایش، از جمله av CarUiRecyclerView
، با متد setRotaryScrollEnabled()
در CarUiUtils
فعال کنید. اگر این کار را انجام دهید، باید:
- نمای پیمایشی را قابل فوکوس کنید تا زمانی که هیچ یک از نماهای اصلی قابل فوکوس قابل مشاهده نیست، روی آن فوکوس شود.
- با فراخوانی
setDefaultFocusHighlightEnabled(false)
برجسته کردن فوکوس پیشفرض در نمای قابل پیمایش را غیرفعال کنید تا نمای قابل پیمایش متمرکز به نظر نرسد. - با فراخوانی
setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS)
اطمینان حاصل کنید که نمای قابل پیمایش قبل از فرزندان خود متمرکز شده است. - با
SOURCE_ROTARY_ENCODER
وAXIS_VSCROLL
یاAXIS_HSCROLL
به MotionEvents گوش دهید تا فاصله پیمایش و جهت را (از طریق علامت) نشان دهید.
هنگامی که پیمایش چرخشی در CarUiRecyclerView
فعال میشود و کاربر به ناحیهای میچرخد که در آن هیچ نمای قابل تمرکزی وجود ندارد، نوار اسکرول از خاکستری به آبی تغییر میکند، گویی که نشان میدهد نوار اسکرول فوکوس شده است. اگر دوست دارید می توانید یک افکت مشابه را پیاده سازی کنید.
MotionEvents مانند مواردی است که توسط چرخ اسکرول روی ماوس ایجاد می شود، به جز منبع.
حالت دستکاری مستقیم
به طور معمول، تکان دادن و چرخش در رابط کاربری حرکت می کند، در حالی که دکمه مرکزی را فشار می دهد، هر چند همیشه اینطور نیست. به عنوان مثال، اگر کاربری بخواهد صدای زنگ هشدار را تنظیم کند، ممکن است از کنترلر چرخشی برای حرکت به نوار لغزنده صدا استفاده کند، دکمه مرکز را فشار دهد، کنترلر را بچرخاند تا صدای زنگ هشدار را تنظیم کند، و سپس دکمه برگشت را برای بازگشت به مسیریابی فشار دهد. . به این حالت دستکاری مستقیم (DM) می گویند. در این حالت، کنترلر چرخشی برای تعامل مستقیم با نما به جای جهت یابی استفاده می شود.
DM را به یکی از دو روش پیاده سازی کنید. اگر فقط باید چرخش را مدیریت کنید و نمای مورد نظر برای دستکاری به ACTION_SCROLL_FORWARD
و ACTION_SCROLL_BACKWARD
AccessibilityEvent
به طور مناسب پاسخ می دهد، از مکانیسم ساده استفاده کنید. در غیر این صورت از مکانیزم پیشرفته استفاده کنید.
مکانیسم ساده تنها گزینه در ویندوز سیستم است. برنامه ها می توانند از هر مکانیزم استفاده کنند.
مکانیزم ساده
( اندروید 11 QPR3، اندروید 11 ماشین، اندروید 12 )
برنامه شما باید DirectManipulationHelper.setSupportsRotateDirectly(View view, boolean enable)
را فراخوانی کند. RotaryService
تشخیص می دهد که کاربر در حالت DM است و هنگامی که کاربر دکمه مرکز را فشار می دهد در حالی که یک نما فوکوس شده است وارد حالت DM می شود. در حالت DM، چرخشها ACTION_SCROLL_FORWARD
یا ACTION_SCROLL_BACKWARD
را انجام میدهند و وقتی کاربر دکمه برگشت را فشار میدهد از حالت DM خارج میشود. مکانیسم ساده حالت انتخاب شده نما را هنگام ورود و خروج از حالت DM تغییر می دهد.
برای ارائه یک نشانه بصری مبنی بر اینکه کاربر در حالت DM است، هنگام انتخاب نمای خود را متفاوت نشان دهید. برای مثال، زمانی که android:state_selected
true
است، پسزمینه را تغییر دهید.
مکانیزم پیشرفته
برنامه تعیین میکند که RotaryService
چه زمانی وارد حالت DM شود و از آن خارج شود. برای تجربه کاربری ثابت، فشار دادن دکمه مرکز با نمای DM متمرکز باید وارد حالت DM شود و دکمه برگشت باید از حالت DM خارج شود. اگر از دکمه مرکزی و/یا تلنگر استفاده نمیشود، میتوانند راههای جایگزینی برای خروج از حالت DM باشند. برای برنامه هایی مانند Maps، می توان از دکمه ای برای نشان دادن DM برای ورود به حالت DM استفاده کرد.
برای پشتیبانی از حالت DM پیشرفته، یک نمای:
- ( Android 11 QPR3, Android 11 Car, Android 12 ) برای ورود به حالت DM باید به رویداد
KEYCODE_DPAD_CENTER
گوش دهید و برای خروج از حالت DM به رویدادKEYCODE_BACK
گوش دهید و در هر موردDirectManipulationHelper.enableDirectManipulationMode()
فراخوانی کنید. برای گوش دادن به این رویدادها، یکی از موارد زیر را انجام دهید:- یک
OnKeyListener
ثبت کنید. یا، - View را گسترش دهید و سپس متد
dispatchKeyEvent()
آن را لغو کنید.
- یک
- اگر نما باید با تلنگرها برخورد کند، باید به رویدادهای نوج گوش دهید (
KEYCODE_DPAD_UP
،KEYCODE_DPAD_DOWN
،KEYCODE_DPAD_LEFT
، یاKEYCODE_DPAD_RIGHT
). - اگر نمای میخواهد چرخش را مدیریت کند، باید به
MotionEvent
گوش دهید و تعداد چرخش را درAXIS_SCROLL
دریافت کنید. چندین راه برای این کار وجود دارد:- یک
OnGenericMotionListener
ثبت کنید. - نمایش را گسترش دهید و متد
dispatchTouchEvent()
آن را لغو کنید.
- یک
- برای جلوگیری از گیر افتادن در حالت DM، باید از حالت DM خارج شوید زمانی که بخش یا فعالیتی که نمای به آن تعلق دارد تعاملی نیست.
- باید یک نشانه بصری برای نشان دادن اینکه نما در حالت DM است ارائه دهد.
نمونه ای از نمای سفارشی که از حالت DM برای حرکت و بزرگنمایی نقشه استفاده می کند در زیر ارائه شده است:
/** Whether this view is in DM mode. */ private boolean mInDirectManipulationMode;
/** Initializes the view. Called by the constructors. */ private void init() { setOnKeyListener((view, keyCode, keyEvent) -> { boolean isActionUp = keyEvent.getAction() == KeyEvent.ACTION_UP; switch (keyCode) { // Always consume KEYCODE_DPAD_CENTER and KEYCODE_BACK events. case KeyEvent.KEYCODE_DPAD_CENTER: if (!mInDirectManipulationMode && isActionUp) { mInDirectManipulationMode = true; DirectManipulationHelper.enableDirectManipulationMode(this, true); setSelected(true); // visually indicate DM mode } return true; case KeyEvent.KEYCODE_BACK: if (mInDirectManipulationMode && isActionUp) { mInDirectManipulationMode = false; DirectManipulationHelper.enableDirectManipulationMode(this, false); setSelected(false); } return true; // Consume controller nudge events only when in DM mode. // When in DM mode, nudges pan the map. case KeyEvent.KEYCODE_DPAD_UP: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(0f, -10f); return true; case KeyEvent.KEYCODE_DPAD_DOWN: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(0f, 10f); return true; case KeyEvent.KEYCODE_DPAD_LEFT: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(-10f, 0f); return true; case KeyEvent.KEYCODE_DPAD_RIGHT: if (!mInDirectManipulationMode) return false; if (isActionUp) pan(10f, 0f); return true; // Don't consume other key events. default: return false; } });
// When in DM mode, rotation zooms the map. setOnGenericMotionListener(((view, motionEvent) -> { if (!mInDirectManipulationMode) return false; float scroll = motionEvent.getAxisValue(MotionEvent.AXIS_SCROLL); zoom(10 * scroll); return true; })); }
@Override public void onPause() { if (mInDirectManipulationMode) { // To ensure that the user doesn't get stuck in DM mode, disable DM mode // when the fragment is not interactive (e.g., a dialog shows up). mInDirectManipulationMode = false; DirectManipulationHelper.enableDirectManipulationMode(this, false); } super.onPause(); }
نمونه های بیشتری را می توان در پروژه RotaryPlayground
یافت.
ActivityView
هنگام استفاده از ActivityView:
-
ActivityView
نباید قابل تمرکز باشد. - ( Android 11 QPR3، Android 11 Car، منسوخ شده در Android 11 )
محتویاتActivityView
باید حاویFocusParkingView
به عنوان اولین نمای قابل فوکوس باشد و ویژگیapp:shouldRestoreFocus
بایدfalse
باشد. - محتویات
ActivityView
نباید نماهایandroid:focusByDefault
داشته باشند.
برای کاربر، ActivityViews نباید هیچ تأثیری در مسیریابی داشته باشد، به جز اینکه مناطق فوکوس نمی توانند ActivityViews را پوشش دهند. به عبارت دیگر، نمیتوانید یک ناحیه فوکوس واحد داشته باشید که دارای محتوای داخل و خارج از ActivityView
باشد. اگر هیچ FocusAreas را به ActivityView
خود اضافه نکنید، ریشه سلسله مراتب view در ActivityView
یک ناحیه تمرکز ضمنی در نظر گرفته می شود.
دکمه هایی که با نگه داشتن آن عمل می کنند
اکثر دکمهها هنگام کلیک کردن باعث ایجاد برخی عملکردها میشوند. در عوض برخی از دکمه ها با نگه داشتن آن کار می کنند. به عنوان مثال، دکمههای Fast Forward و Rewind معمولاً زمانی کار میکنند که پایین نگه داشته میشوند. برای اینکه چنین دکمههایی از چرخش پشتیبانی کنند، به KEYCODE_DPAD_CENTER
KeyEvents
به شرح زیر گوش دهید:
mButton.setOnKeyListener((v, keyCode, event) -> { if (keyCode != KEYCODE_DPAD_CENTER) { return false; } if (event.getAction() == ACTION_DOWN) { mButton.setPressed(true); mHandler.post(mRunnable); } else { mButton.setPressed(false); mHandler.removeCallbacks(mRunnable); } return true; });
که در آن mRunnable
عملی را انجام می دهد (مثلاً به عقب) و برنامه ریزی می کند تا پس از تأخیر اجرا شود.
حالت لمسی
کاربران می توانند از یک کنترلر چرخشی برای تعامل با هد یونیت در خودرو به دو روش استفاده کنند، یا با استفاده از کنترلر چرخشی یا با لمس صفحه نمایش. هنگام استفاده از کنترلر چرخشی، یکی از نماهای قابل فوکوس برجسته می شود. هنگام لمس صفحه، هیچ برجسته فوکوس ظاهر نمی شود. کاربر می تواند در هر زمانی بین این حالت های ورودی جابجا شود:
- چرخشی ← لمسی. هنگامی که کاربر صفحه را لمس می کند، برجسته شدن فوکوس ناپدید می شود.
- ← چرخشی را لمس کنید. هنگامی که کاربر دکمه مرکزی را تکان می دهد، می چرخد یا فشار می دهد، برجسته شدن فوکوس ظاهر می شود.
دکمه های Back و Home هیچ تاثیری روی حالت ورودی ندارند.
Piggybacks چرخشی در مفهوم موجود اندروید از حالت لمسی . می توانید از View.isInTouchMode()
استفاده کنید تا مشخص کنید کاربر از کدام حالت ورودی استفاده می کند. برای گوش دادن به تغییرات می توانید از OnTouchModeChangeListener
استفاده کنید. در حالی که این می تواند برای سفارشی کردن رابط کاربری شما برای حالت ورودی فعلی استفاده شود، از هر گونه تغییر عمده اجتناب کنید زیرا ممکن است نگران کننده باشد.
عیب یابی
در اپلیکیشنی که برای لمس طراحی شده است، داشتن نماهای قابل فوکوس تودرتو معمول است. برای مثال، ممکن است یک FrameLayout
در اطراف یک ImageButton
وجود داشته باشد که هر دو قابل فوکوس هستند. این برای لمس ضرری ندارد اما می تواند منجر به تجربه کاربری ضعیف برای چرخش شود زیرا کاربر باید کنترلر را دو بار بچرخاند تا به نمای تعاملی بعدی برود. برای یک تجربه کاربری خوب، گوگل توصیه می کند که نمای بیرونی یا نمای داخلی را قابل فوکوس کنید، اما نه هر دو.
اگر یک دکمه یا سوئیچ با فشار دادن از طریق کنترلر چرخشی فوکوس خود را از دست بدهد، ممکن است یکی از این شرایط اعمال شود:
- دکمه یا سوئیچ به دلیل فشار دادن دکمه (به طور خلاصه یا نامحدود) غیرفعال می شود. در هر صورت، دو راه برای رفع این مشکل وجود دارد:
- حالت
android:enabled
راtrue
بگذارید و از یک حالت سفارشی برای خاکستری کردن دکمه یا سوئیچ همانطور که در حالت سفارشی توضیح داده شده است استفاده کنید. - از یک ظرف برای احاطه کردن دکمه یا سوئیچ استفاده کنید و ظرف را به جای دکمه یا سوئیچ قابل فوکوس کنید. (شنونده کلیک باید روی ظرف باشد.)
- حالت
- دکمه یا سوئیچ در حال تعویض است. برای مثال، اقدامی که هنگام فشار دادن دکمه یا جابجایی کلید انجام میشود، ممکن است باعث بهروزرسانی عملکردهای موجود شود و باعث شود دکمههای جدید جایگزین دکمههای موجود شوند. برای رفع این مشکل دو راه وجود دارد:
- به جای ایجاد یک دکمه یا سوئیچ جدید، نماد و/یا متن دکمه یا سوئیچ موجود را تنظیم کنید.
- مانند بالا، یک ظرف قابل فوکوس در اطراف دکمه یا سوئیچ اضافه کنید.
زمین بازی روتاری
RotaryPlayground
یک برنامه مرجع برای چرخش است. از آن برای یادگیری نحوه ادغام ویژگی های چرخشی در برنامه های خود استفاده کنید. RotaryPlayground
در ساختهای شبیهساز و در ساختهای دستگاههایی که سیستمعامل Android Automotive (AAOS) را اجرا میکنند گنجانده شده است.
- مخزن
RotaryPlayground
:packages/apps/Car/tests/RotaryPlayground/
- نسخه ها: Android 11 QPR3، Android 11 Car و Android 12
برنامه RotaryPlayground
برگه های زیر را در سمت چپ نشان می دهد:
- کارت ها پیمایش در مناطق فوکوس، نادیده گرفتن عناصر غیرقابل تمرکز و ورودی متن را آزمایش کنید.
- دستکاری مستقیم ویجت هایی را تست کنید که از حالت دستکاری مستقیم ساده و پیشرفته پشتیبانی می کنند. این تب به طور خاص برای دستکاری مستقیم در پنجره برنامه است.
- دستکاری UI Sys. ویجتهایی را تست کنید که از دستکاری مستقیم در ویندوزهای سیستم پشتیبانی میکنند که در آن فقط حالت دستکاری مستقیم ساده پشتیبانی میشود.
- شبکه ناوبری چرخشی الگوی z را با اسکرول تست کنید.
- اطلاع رسانی اعلانهای هدآپ را تست کنید.
- اسکرول کنید. پیمایش را در ترکیبی از محتوای قابل تمرکز و غیر قابل تمرکز آزمایش کنید.
- WebView. پیمایش از طریق پیوندها را در
WebView
آزمایش کنید. -
FocusArea
سفارشی. تست سفارشی سازیFocusArea
:- بپیچید.
-
android:focusedByDefault
وapp:defaultFocus
. - اهداف تلنگر آشکار
- میانبرهای تلنگر.
-
FocusArea
بدون نماهای قابل فوکوس.