۱. مقدمه
برای اندروید نسخه ۱۰ یا بالاتر، ژستهای ناوبری به عنوان یک حالت جدید پشتیبانی میشوند. این به برنامه شما اجازه میدهد از کل صفحه استفاده کند و تجربه نمایش فراگیرتری را ارائه دهد. وقتی کاربر از لبه پایین صفحه به بالا میکشد، به صفحه اصلی اندروید میرود. وقتی از لبههای چپ یا راست به داخل میکشد، به صفحه قبلی میرود.
با این دو حرکت، برنامه شما میتواند از فضای صفحه نمایش در پایین صفحه استفاده کند. با این حال، اگر برنامه شما از حرکات استفاده میکند یا کنترلهایی در قسمتهای حرکات سیستم دارد، ممکن است با حرکات سراسری سیستم تداخل ایجاد کند.
این آزمایشگاه کد قصد دارد به شما آموزش دهد که چگونه از insets برای جلوگیری از تداخل حرکات استفاده کنید. علاوه بر این، این آزمایشگاه کد قصد دارد به شما آموزش دهد که چگونه از API Gesture Exclusion برای کنترلهایی مانند دستگیرههای کشیدن که باید در مناطق حرکات قرار گیرند، استفاده کنید.
آنچه یاد خواهید گرفت
- نحوه استفاده از شنوندههای درج (inset listeners) در نماها (views)
- نحوه استفاده از API حذف حرکات
- نحوه عملکرد حالت فراگیر هنگام فعال بودن حرکات
این آزمایشگاه کد قصد دارد برنامه شما را با حرکات سیستمی سازگار کند. مفاهیم و بلوکهای کد نامربوط حذف شده و برای کپی و پیست در اختیار شما قرار داده شدهاند.
آنچه خواهید ساخت
پخشکننده موسیقی جهانی اندروید (UAMP) یک برنامه پخش موسیقی نمونه برای اندروید است که با کاتلین نوشته شده است. شما UAMP را برای ناوبری حرکتی تنظیم خواهید کرد.
- از insetها برای دور کردن کنترلها از نواحی حرکتی استفاده کنید
- از API مربوط به Gesture Exclusion برای غیرفعال کردن ژست بازگشت برای کنترلهایی که با هم تداخل دارند استفاده کنید.
- از ساختههای خود برای بررسی تغییرات رفتار حالت فراگیر با ناوبری حرکتی استفاده کنید
آنچه نیاز دارید
- دستگاه یا شبیهساز که اندروید ۱۰ یا بالاتر را اجرا میکند
- اندروید استودیو
۲. مرور کلی برنامه
پخشکننده موسیقی جهانی اندروید (UAMP) یک برنامه پخش موسیقی نمونه برای اندروید است که با زبان کاتلین نوشته شده است. این برنامه از ویژگیهایی مانند پخش در پسزمینه، مدیریت فوکوس صوتی، ادغام با دستیار صوتی و پلتفرمهای مختلف مانند Wear، TV و Auto پشتیبانی میکند.
|
|
|
شکل ۱ : جریانی در UAMP
UAMP یک کاتالوگ موسیقی را از یک سرور راه دور بارگذاری میکند و به کاربر اجازه میدهد آلبومها و آهنگها را مرور کند. کاربر روی یک آهنگ ضربه میزند و آن آهنگ از طریق بلندگوها یا هدفونهای متصل پخش میشود. این برنامه برای کار با حرکات سیستم طراحی نشده است. بنابراین، وقتی UAMP را روی دستگاهی که اندروید ۱۰ یا بالاتر دارد اجرا میکنید، در ابتدا با برخی مشکلات مواجه میشوید.
۳. آماده شوید
برای دریافت برنامه نمونه، مخزن را از GitHub کپی کنید و به شاخه starter بروید:
$ git clone https://github.com/googlecodelabs/android-gestural-navigation/
روش دیگر این است که مخزن را به صورت یک فایل زیپ دانلود کنید، آن را از حالت فشرده خارج کنید و در اندروید استودیو باز کنید.
مراحل زیر را انجام دهید:
- برنامه را در اندروید استودیو باز کنید و بسازید.
- یک دستگاه مجازی جدید ایجاد کنید و سطح API 29 را انتخاب کنید. همچنین میتوانید یک دستگاه واقعی که سطح API 29 یا بالاتر را اجرا میکند، متصل کنید.
- برنامه را اجرا کنید. لیستی که مشاهده میکنید، آهنگها را در زیر گزینههای پیشنهادی و آلبومها گروهبندی میکند.
- روی «توصیهشده» کلیک کنید و آهنگی را از لیست آهنگها انتخاب کنید.
- برنامه شروع به پخش آهنگ میکند.
فعال کردن پیمایش با اشاره
اگر یک نمونه شبیهساز جدید با سطح API 29 اجرا کنید، ممکن است ناوبری حرکتی به طور پیشفرض فعال نباشد. برای فعال کردن ناوبری حرکتی، تنظیمات سیستم > سیستم > ناوبری سیستم > ناوبری حرکتی را انتخاب کنید.
برنامه را با Gesture Navigation اجرا کنید
اگر برنامه را با فعال بودن Gesture Navigation اجرا کنید و شروع به پخش یک آهنگ کنید، ممکن است متوجه شوید که کنترلهای پخشکننده بسیار نزدیک به قسمتهای اشارهای خانه و بازگشت هستند.
۴. لبه به لبه بروید
لبه به لبه چیست؟
برنامههایی که روی اندروید ۱۰ یا بالاتر اجرا میشوند، میتوانند صرف نظر از اینکه حرکات یا دکمهها برای ناوبری فعال باشند، یک تجربه کامل از صفحه نمایش لبه به لبه ارائه دهند. برای ارائه یک تجربه لبه به لبه، برنامههای شما باید از نوارهای ناوبری و وضعیت شفاف استفاده کنند.
پشت نوار ناوبری نقاشی بکشید
برای اینکه برنامه شما بتواند محتوا را در زیر نوار ناوبری رندر کند، ابتدا باید پسزمینه نوار ناوبری را شفاف کنید. سپس باید نوار وضعیت را شفاف کنید. این به برنامه شما اجازه میدهد تا برنامه شما را در تمام ارتفاع صفحه نمایش دهد.
برای تغییر رنگ نوار ناوبری و نوار وضعیت، مراحل زیر را انجام دهید:
- نوار ناوبری:
res/values-29/styles.xmlرا باز کنید وnavigationBarColorرویcolor/transparentتنظیم کنید. - نوار وضعیت: به طور مشابه،
statusBarColorرویcolor/transparentتنظیم کنید.
نمونه کد زیر از res/values-29/styles.xml را بررسی کنید:
<!-- change navigation bar color -->
<item name="android:navigationBarColor">
@android:color/transparent
</item>
<!-- change status bar color -->
<item name="android:statusBarColor">
@android:color/transparent
</item>
پرچمهای قابلیت مشاهده رابط کاربری سیستم
همچنین باید پرچمهای قابلیت مشاهده رابط کاربری سیستم را تنظیم کنید تا به سیستم بگویید برنامه را زیر نوارهای سیستم قرار دهد. APIهای systemUiVisibility در کلاس View امکان تنظیم انواع پرچمها را فراهم میکنند. مراحل زیر را انجام دهید:
- کلاس
MainActivity.ktرا باز کنید و متدonCreate()را پیدا کنید. یک نمونه ازfragmentContainerدریافت کنید. - موارد زیر را به
content.systemUiVisibilityتنظیم کنید:
-
View.SYSTEM_UI_FLAG_LAYOUT_STABLE -
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN -
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
نمونه کد زیر از MainActivity.kt را بررسی کنید:
val content: FrameLayout = findViewById(R.id.fragmentContainer)
content.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
وقتی این پرچمها را کنار هم قرار میدهید، به سیستم میگویید که میخواهید برنامهتان به صورت تمام صفحه نمایش داده شود، انگار که نوارهای ناوبری و وضعیت وجود ندارند. مراحل زیر را انجام دهید:
- برنامه را اجرا کنید و برای رفتن به صفحه پخش، یک آهنگ را برای پخش انتخاب کنید.
- تأیید کنید که کنترلهای پخشکننده زیر نوار ناوبری کشیده شدهاند و دسترسی به آنها را دشوار میکنند:
|
|
- به تنظیمات سیستم بروید، به حالت ناوبری سه دکمهای برگردید و به برنامه برگردید.
- تأیید کنید که استفاده از کنترلها با نوار ناوبری سه دکمهای حتی دشوارتر است: توجه داشته باشید که
SeekBarدر پشت نوار ناوبری پنهان شده است و پخش/مکث عمدتاً توسط نوار ناوبری پوشانده شده است. - کمی کاوش و آزمایش کنید. پس از اتمام کار، به تنظیمات سیستم بروید و دوباره به پیمایش اشارهای برگردید:

اکنون برنامه به صورت لبه به لبه طراحی میشود، اما مشکلات مربوط به قابلیت استفاده، کنترلهای برنامه که با هم تداخل و تداخل دارند، وجود دارد و این موارد باید حل شوند.
۵. طرحهای تودرتو
WindowInsets به برنامه میگوید که رابط کاربری سیستم کجا روی محتوای شما ظاهر شود، و همچنین به برنامه میگوید که کدام قسمتهای صفحه نمایش، حرکات سیستمی نسبت به حرکات درون برنامهای اولویت دارند. Insets توسط کلاس WindowInsets و کلاس WindowInsetsCompat در Jetpack نمایش داده میشوند. ما اکیداً توصیه میکنیم که از WindowInsetsCompat برای داشتن رفتار سازگار در تمام سطوح API استفاده کنید.
درجهای سیستم و درجهای اجباری سیستم
API های inset زیر رایج ترین انواع inset مورد استفاده هستند:
- درج پنجره سیستم: آنها به شما میگویند که رابط کاربری سیستم در کجای برنامه شما نمایش داده میشود. ما در مورد نحوه استفاده از درجهای سیستم برای دور کردن کنترلهای خود از میلههای سیستم بحث خواهیم کرد.
- درج حرکات سیستم: آنها تمام نواحی حرکتی را برمیگردانند. هرگونه کنترل سوایپ درون برنامهای در این نواحی میتواند به طور تصادفی حرکات سیستم را فعال کند.
- درجهای اجباری حرکات: آنها زیرمجموعهای از درجهای حرکات سیستمی هستند و نمیتوان آنها را لغو کرد. آنها به شما میگویند که در چه قسمتهایی از صفحه، رفتار حرکات سیستمی همیشه نسبت به حرکات درون برنامهای اولویت دارد.
استفاده از inset برای جابجایی کنترلهای برنامه
حالا که اطلاعات بیشتری در مورد APIهای درجشده دارید، میتوانید کنترلهای برنامه را همانطور که در مراحل زیر توضیح داده شده است، اصلاح کنید:
- یک نمونه از
playerLayoutاز نمونه شیءviewدریافت کنید. - یک
OnApplyWindowInsetsListenerبهplayerViewاضافه کنید. - دور کردن نما از ناحیه ژست: مقدار inset سیستم برای bottom را پیدا کنید و padding نما را به همان مقدار افزایش دهید. برای بهروزرسانی padding نما بر این اساس، به [مقدار مرتبط با padding پایین برنامه]، [مقدار مرتبط با مقدار inset پایین سیستم] را اضافه کنید.
نمونه کد زیر از NowPlayingFragment.kt را بررسی کنید:
playerView = view.findViewById(R.id.playerLayout)
playerView.setOnApplyWindowInsetsListener { view, insets ->
view.updatePadding(
bottom = insets.systemWindowInsetBottom + view.paddingBottom
)
insets
}
- برنامه را اجرا کنید و یک آهنگ را انتخاب کنید. توجه داشته باشید که به نظر نمیرسد هیچ چیزی در کنترلهای پخشکننده تغییر کند. اگر یک نقطه توقف اضافه کنید و برنامه را در حالت اشکالزدایی اجرا کنید، خواهید دید که شنونده فراخوانی نمیشود.
- برای رفع این مشکل، به
FragmentContainerViewبروید که به طور خودکار این مشکل را مدیریت میکند.activity_main.xmlرا باز کنید وFrameLayoutبهFragmentContainerViewتغییر دهید.
نمونه کد زیر از activity_main.xml را بررسی کنید:
<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fragmentContainer"
tools:context="com.example.android.uamp.MainActivity"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
- برنامه را دوباره اجرا کنید و به صفحه پخش بروید. کنترلهای پخشکننده پایین از ناحیه ژستهای حرکتی پایین جابجا شدهاند.
کنترلهای برنامه اکنون با پیمایش اشارهای کار میکنند، اما کنترلها بیشتر از حد انتظار حرکت میکنند. شما باید این مشکل را حل کنید.
فاصلهگذاری و حاشیهبندی فعلی را حفظ کنید
اگر به برنامههای دیگر بروید یا به صفحه اصلی بروید و بدون بستن برنامه به برنامه برگردید، متوجه خواهید شد که کنترلهای پخشکننده هر بار به سمت بالا حرکت میکنند.
دلیل این امر این است که برنامه هر بار که فعالیت شروع میشود، requestApplyInsets() را فعال میکند. حتی بدون این فراخوانی، WindowInsets میتواند چندین بار در هر زمانی در طول چرخه حیات یک نما ارسال شود.
InsetListener فعلی در playerView اولین باری که مقدار inset bottom را به مقدار padding پایین برنامه که در activity_main.xml تعریف شده است اضافه میکنید، کاملاً کار میکند. با این حال، فراخوانیهای بعدی همچنان مقدار inset bottom را به padding پایین نمای از قبل بهروزرسانی شده اضافه میکنند.
برای رفع این مشکل، مراحل زیر را انجام دهید:
- مقدار اولیهی فاصلهگذاری view را ثبت کنید. یک val جدید ایجاد کنید و مقدار اولیهی فاصلهگذاری view مربوط به
playerViewرا درست قبل از کد شنونده ذخیره کنید.
نمونه کد زیر از NowPlayingFragment.kt را بررسی کنید:
val initialPadding = playerView.paddingBottom
- از این مقدار اولیه برای بهروزرسانی padding پایین نما استفاده کنید، که به شما امکان میدهد از استفاده از مقدار padding پایین فعلی برنامه جلوگیری کنید.
نمونه کد زیر از NowPlayingFragment.kt را بررسی کنید:
playerView.setOnApplyWindowInsetsListener { view, insets ->
view.updatePadding(bottom = insets.systemWindowInsetBottom + initialPadding)
insets
}
- برنامه را دوباره اجرا کنید. بین برنامهها حرکت کنید و به صفحه اصلی بروید. وقتی برنامه را برگردانید، کنترلهای پخشکننده درست بالای ناحیه ژستها قرار دارند.
طراحی مجدد کنترلهای برنامه
نوار جستجو (seebar) پخشکننده خیلی به ناحیهی اشارهی پایینی نزدیک است، به این معنی که کاربر میتواند هنگام کشیدن انگشت افقی، بهطور تصادفی اشارهی خانه را فعال کند. اگر فاصلهی بین دو نقطه را بیشتر کنید، میتواند مشکل را حل کند، اما ممکن است پخشکننده را بالاتر از حد مطلوب نیز حرکت دهد.
استفاده از insetها به شما امکان میدهد تداخل حرکات را برطرف کنید، اما گاهی اوقات با تغییرات کوچک در طراحی، میتوانید از تداخل حرکات به طور کامل جلوگیری کنید. برای طراحی مجدد کنترلهای پخشکننده برای جلوگیری از تداخل حرکات، مراحل زیر را انجام دهید:
-
fragment_nowplaying.xmlرا باز کنید. به نمای طراحی (Design view) بروید وSeekBarرا در پایین صفحه انتخاب کنید:

- به نمای کد بروید.
- برای انتقال
SeekBarبه بالایplayerLayout،layout_constraintTop_toBottomOfمربوط به SeekBar را بهparentتغییر دهید. - برای محدود کردن سایر آیتمها در
playerViewبه پایینSeekBar،layout_constraintTop_toTopOfاز والد به@+id/seekBarدرmedia_button،titleوpositionتغییر دهید.
نمونه کد زیر از fragment_nowplaying.xml را بررسی کنید:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:layout_gravity="bottom"
android:background="@drawable/media_overlay_background"
android:id="@+id/playerLayout">
<ImageButton
android:id="@+id/media_button"
android:layout_width="@dimen/exo_media_button_width"
android:layout_height="@dimen/exo_media_button_height"
android:background="?attr/selectableItemBackground"
android:scaleType="centerInside"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="@+id/seekBar"
app:srcCompat="@drawable/ic_play_arrow_black_24dp"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginStart="@dimen/text_margin"
android:layout_marginEnd="@dimen/text_margin"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.Uamp.Title"
app:layout_constraintTop_toTopOf="@+id/seekBar"
app:layout_constraintLeft_toRightOf="@id/media_button"
app:layout_constraintRight_toLeftOf="@id/position"
tools:text="Song Title" />
<TextView
android:id="@+id/subtitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/text_margin"
android:layout_marginEnd="@dimen/text_margin"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.Uamp.Subtitle"
app:layout_constraintTop_toBottomOf="@+id/title"
app:layout_constraintLeft_toRightOf="@id/media_button"
app:layout_constraintRight_toLeftOf="@id/position"
tools:text="Artist" />
<TextView
android:id="@+id/position"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginStart="@dimen/text_margin"
android:layout_marginEnd="@dimen/text_margin"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.Uamp.Title"
app:layout_constraintTop_toTopOf="@+id/seekBar"
app:layout_constraintRight_toRightOf="parent"
tools:text="0:00" />
<TextView
android:id="@+id/duration"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/text_margin"
android:layout_marginEnd="@dimen/text_margin"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.Uamp.Subtitle"
app:layout_constraintTop_toBottomOf="@id/position"
app:layout_constraintRight_toRightOf="parent"
tools:text="0:00" />
<SeekBar
android:id="@+id/seekBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
- برنامه را اجرا کنید و با پخشکننده و نوار جستجو تعامل داشته باشید.
این تغییرات طراحی حداقلی، برنامه را به طور قابل توجهی بهبود میبخشند.
۶. API حذف ژستهای حرکتی
تداخل کنترلهای بازیکن برای ژستهای حرکتی در ناحیه ژستهای حرکتی خانه برطرف شده است. ناحیه ژستهای حرکتی پشت نیز میتواند با کنترلهای برنامه تداخل ایجاد کند. تصویر زیر نشان میدهد که نوار جستجوی بازیکن در حال حاضر در هر دو ناحیه ژست پشتی راست و چپ قرار دارد:

SeekBar به طور خودکار تداخل ژستها را مدیریت میکند. با این حال، ممکن است لازم باشد از اجزای رابط کاربری دیگری استفاده کنید که باعث تداخل ژستها میشوند. در این موارد، میتوانید Gesture Exclusion API برای غیرفعال کردن جزئی ژست برگشت استفاده کنید.
استفاده از API حذف ژستهای حرکتی
برای ایجاد یک منطقهی استثنای ژست (gesture)، تابع setSystemGestureExclusionRects() را در نمای خود به همراه لیستی از اشیاء rect فراخوانی کنید. این اشیاء rect به مختصات نواحی مستطیلیِ مستثنی شده نگاشت میشوند. این فراخوانی باید در متدهای onLayout() یا onDraw() نمای مورد نظر انجام شود. برای انجام این کار، مراحل زیر را انجام دهید:
- یک بسته جدید با نام
viewایجاد کنید. - برای فراخوانی این API، یک کلاس جدید به نام
MySeekBarایجاد کنید وAppCompatSeekBarارثبری (extend) کنید.
نمونه کد زیر از MySeekBar.kt را بررسی کنید:
class MySeekBar @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = android.R.attr.seekBarStyle
) : androidx.appcompat.widget.AppCompatSeekBar(context, attrs, defStyle) {
}
- یک متد جدید به نام
updateGestureExclusion()ایجاد کنید.
نمونه کد زیر از MySeekBar.kt را بررسی کنید:
private fun updateGestureExclusion() {
}
- برای رد کردن این فراخوانی در سطح API 28 یا پایینتر، تیک اضافه کنید.
نمونه کد زیر از MySeekBar.kt را بررسی کنید:
private fun updateGestureExclusion() {
// Skip this call if we're not running on Android 10+
if (Build.VERSION.SDK_INT < 29) return
}
- از آنجا که API مربوط به Gesture Exclusion محدودیت ۲۰۰ dp دارد، فقط انگشت شست Seekbar را مستثنی کنید. یک کپی از مرزهای Seekbar بگیرید و هر شیء را به یک لیست قابل تغییر اضافه کنید.
نمونه کد زیر از MySeekBar.kt را بررسی کنید:
private val gestureExclusionRects = mutableListOf<Rect>()
private fun updateGestureExclusion() {
// Skip this call if we're not running on Android 10+
if (Build.VERSION.SDK_INT < 29) return
thumb?.also { t ->
gestureExclusionRects += t.copyBounds()
}
}
- تابع
systemGestureExclusionRects()را با لیستهایgestureExclusionRectsکه ایجاد میکنید، فراخوانی کنید.
نمونه کد زیر از MySeekBar.kt را بررسی کنید:
private val gestureExclusionRects = mutableListOf<Rect>()
private fun updateGestureExclusion() {
// Skip this call if we're not running on Android 10+
if (Build.VERSION.SDK_INT < 29) return
thumb?.also { t ->
gestureExclusionRects += t.copyBounds()
}
// Finally pass our updated list of rectangles to the system
systemGestureExclusionRects = gestureExclusionRects
}
- متد
updateGestureExclusion()را ازonDraw()یاonLayout()فراخوانی کنید.onDraw()را بازنویسی کنید و یک فراخوانی بهupdateGestureExclusionاضافه کنید.
نمونه کد زیر از MySeekBar.kt را بررسی کنید:
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
updateGestureExclusion()
}
- شما باید ارجاعات
SeekBarرا بهروزرسانی کنید. برای شروع،fragment_nowplaying.xmlرا باز کنید. -
SeekBarبهcom.example.android.uamp.view.MySeekBarتغییر دهید.
نمونه کد زیر از fragment_nowplaying.xml را بررسی کنید:
<com.example.android.uamp.view.MySeekBar
android:id="@+id/seekBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent" />
- برای بهروزرسانی ارجاعهای
SeekBarدرNowPlayingFragment.kt،NowPlayingFragment.ktرا باز کنید و نوعpositionSeekBarرا بهMySeekBarتغییر دهید. برای تطبیق نوع متغیر، ژنریکهایSeekBarرا برای فراخوانیfindViewByIdبهMySeekBarتغییر دهید.
نمونه کد زیر از NowPlayingFragment.kt را بررسی کنید:
val positionSeekBar: MySeekBar = view.findViewById<MySeekBar>(
R.id.seekBar
).apply { progress = 0 }
- برنامه را اجرا کنید و با
SeekBarتعامل داشته باشید. اگر هنوز با تداخل حرکات مواجه هستید، میتوانید محدودههای انگشت شست را درMySeekBarآزمایش و تغییر دهید. مراقب باشید که یک منطقهی محرومیت از حرکات بزرگتر از حد لازم ایجاد نکنید، زیرا این کار سایر فراخوانیهای محرومیت از حرکات بالقوه را محدود میکند و باعث ایجاد رفتار متناقض برای کاربر میشود.
۷. تبریک
تبریک! شما یاد گرفتید که چگونه از تداخلها با حرکات سیستمی جلوگیری کرده و آنها را حل کنید!
شما با گسترش لبه به لبه و استفاده از inset برای دور کردن کنترلهای برنامه از محدودههای اشاره، باعث شدید برنامهتان به صورت تمام صفحه نمایش داده شود. همچنین یاد گرفتید که چگونه حرکت سیستم به عقب را در کنترلهای برنامه غیرفعال کنید.
اکنون مراحل کلیدی مورد نیاز برای کار کردن برنامههایتان با حرکات سیستمی را میدانید!
مواد اضافی
- WindowInsets - شنوندههای طرحبندیها
- پیمایش با اشاره: رفتن از لبه به لبه
- پیمایش با اشاره: مدیریت همپوشانیهای بصری
- پیمایش با اشاره: مدیریت تداخلهای اشارهای
- اطمینان از سازگاری با ناوبری حرکتی




