1. ভূমিকা
Android সংস্করণ 10 বা উচ্চতর জন্য, নেভিগেশন অঙ্গভঙ্গি একটি নতুন মোড হিসাবে সমর্থিত। এটি আপনার অ্যাপটিকে সম্পূর্ণ স্ক্রীন ব্যবহার করতে দেয় এবং আরও নিমজ্জিত প্রদর্শনের অভিজ্ঞতা প্রদান করে৷ ব্যবহারকারী যখন স্ক্রিনের নীচের প্রান্ত থেকে উপরে সোয়াইপ করেন, তখন এটি তাদের Android হোম স্ক্রিনে নিয়ে যায়। যখন তারা বাম বা ডান প্রান্ত থেকে ভিতরের দিকে সোয়াইপ করে, এটি ব্যবহারকারীকে পূর্ববর্তী স্ক্রিনে নিয়ে যায়।
এই দুটি অঙ্গভঙ্গির সাহায্যে, আপনার অ্যাপটি স্ক্রিনের নীচে স্ক্রিনের রিয়েল এস্টেটের সুবিধা নিতে পারে। যাইহোক, যদি আপনার অ্যাপ অঙ্গভঙ্গি ব্যবহার করে বা সিস্টেম অঙ্গভঙ্গি এলাকায় নিয়ন্ত্রণ থাকে, তাহলে এটি সিস্টেম-ব্যাপী অঙ্গভঙ্গির সাথে দ্বন্দ্ব তৈরি করতে পারে।
এই কোডল্যাবের লক্ষ্য হল অঙ্গভঙ্গির দ্বন্দ্ব এড়াতে কীভাবে ইনসেটগুলি ব্যবহার করতে হয় তা শেখানো। অতিরিক্তভাবে, এই কোডল্যাবগুলির লক্ষ্য হল কীভাবে নিয়ন্ত্রণের জন্য জেসচার এক্সক্লুশন API ব্যবহার করতে হয়, যেমন টেনে আনতে হ্যান্ডেলগুলি, যেগুলিকে জেসচার জোনে থাকতে হবে।
আপনি কি শিখবেন
- ভিউতে ইনসেট শ্রোতাদের কীভাবে ব্যবহার করবেন
- জেসচার এক্সক্লুশন এপিআই কীভাবে ব্যবহার করবেন
- ইমারসিভ মোড কেমন আচরণ করে যখন অঙ্গভঙ্গি সক্রিয় থাকে
এই কোডল্যাবের লক্ষ্য আপনার অ্যাপকে সিস্টেম জেসচারের সাথে সামঞ্জস্যপূর্ণ করা। অপ্রাসঙ্গিক ধারণা এবং কোড ব্লকগুলি চকচকে করা হয়েছে এবং আপনাকে কপি এবং পেস্ট করার জন্য সরবরাহ করা হয়েছে।
আপনি কি নির্মাণ করবেন
ইউনিভার্সাল অ্যান্ড্রয়েড মিউজিক প্লেয়ার (ইউএএমপি) কোটলিনে লেখা অ্যান্ড্রয়েডের জন্য একটি উদাহরণ মিউজিক প্লেয়ার অ্যাপ। আপনি অঙ্গভঙ্গি নেভিগেশন জন্য UAMP সেট আপ করবেন।
- অঙ্গভঙ্গি এলাকা থেকে নিয়ন্ত্রণ দূরে সরাতে ইনসেট ব্যবহার করুন
- দ্বন্দ্ব নিয়ন্ত্রণের জন্য পিছনের অঙ্গভঙ্গি থেকে অপ্ট আউট করতে অঙ্গভঙ্গি বর্জন API ব্যবহার করুন৷
- অঙ্গভঙ্গি নেভিগেশন সহ নিমগ্ন মোড আচরণ পরিবর্তনগুলি অন্বেষণ করতে আপনার বিল্ডগুলি ব্যবহার করুন৷
আপনি কি প্রয়োজন হবে
- একটি ডিভাইস বা এমুলেটর যা Android 10 বা উচ্চতর সংস্করণ চালায়
- অ্যান্ড্রয়েড স্টুডিও
2. অ্যাপ ওভারভিউ
ইউনিভার্সাল অ্যান্ড্রয়েড মিউজিক প্লেয়ার (ইউএএমপি) কোটলিনে লেখা অ্যান্ড্রয়েডের জন্য একটি নমুনা মিউজিক প্লেয়ার অ্যাপ। এটি ব্যাকগ্রাউন্ড প্লেব্যাক, অডিও ফোকাস হ্যান্ডলিং, সহকারী ইন্টিগ্রেশন এবং একাধিক প্ল্যাটফর্ম যেমন পরিধান, টিভি এবং অটো অন্তর্ভুক্ত বৈশিষ্ট্যগুলিকে সমর্থন করে৷
চিত্র 1 : UAMP-এ একটি প্রবাহ
UAMP একটি দূরবর্তী সার্ভার থেকে একটি সঙ্গীত ক্যাটালগ লোড করে এবং ব্যবহারকারীকে অ্যালবাম এবং গানগুলি ব্রাউজ করার অনুমতি দেয়। ব্যবহারকারী একটি গানে ট্যাপ করে এবং এটি সংযুক্ত স্পিকার বা হেডফোনের মাধ্যমে বাজায়। অ্যাপটি সিস্টেম জেসচারের সাথে কাজ করার জন্য ডিজাইন করা হয়নি। অতএব, আপনি যখন Android 10 বা তার বেশি সংস্করণে চালিত একটি ডিভাইসে UAMP চালান, প্রাথমিকভাবে আপনি কিছু সমস্যার সম্মুখীন হন।
3. সেট আপ করুন
নমুনা অ্যাপ্লিকেশন পেতে, GitHub থেকে সংগ্রহস্থল ক্লোন করুন এবং স্টার্টার শাখায় স্যুইচ করুন:
$ git clone https://github.com/googlecodelabs/android-gestural-navigation/
বিকল্পভাবে, আপনি সংগ্রহস্থলটিকে একটি জিপ ফাইল হিসাবে ডাউনলোড করতে পারেন, এটি আনজিপ করতে পারেন এবং এটি অ্যান্ড্রয়েড স্টুডিওতে খুলতে পারেন।
নিম্নলিখিত পদক্ষেপগুলি সম্পূর্ণ করুন:
- অ্যান্ড্রয়েড স্টুডিওতে অ্যাপটি খুলুন এবং তৈরি করুন।
- একটি নতুন ভার্চুয়াল ডিভাইস তৈরি করুন এবং API স্তর 29 নির্বাচন করুন। বিকল্পভাবে, আপনি একটি বাস্তব ডিভাইস সংযোগ করতে পারেন যা API স্তর 29 বা উচ্চতর চালায়।
- অ্যাপটি চালান। আপনি যে তালিকাটি দেখেন তা প্রস্তাবিত এবং অ্যালবাম নির্বাচনের অধীনে গানগুলিকে গোষ্ঠীভুক্ত করে৷
- প্রস্তাবিত ক্লিক করুন এবং গানের তালিকা থেকে একটি গান নির্বাচন করুন।
- অ্যাপটি গানটির প্লেব্যাক শুরু করে।
অঙ্গভঙ্গি নেভিগেশন সক্ষম করুন
আপনি API স্তর 29 এর সাথে একটি নতুন এমুলেটর উদাহরণ চালালে, অঙ্গভঙ্গি নেভিগেশন ডিফল্টরূপে চালু নাও হতে পারে। অঙ্গভঙ্গি নেভিগেশন সক্ষম করতে, সিস্টেম সেটিংস > সিস্টেম > সিস্টেম নেভিগেশন > অঙ্গভঙ্গি নেভিগেশন নির্বাচন করুন।
জেসচার নেভিগেশন দিয়ে অ্যাপটি চালান
আপনি যদি জেসচার নেভিগেশন সক্ষম করে অ্যাপটি চালান এবং একটি গানের প্লেব্যাক শুরু করেন, আপনি লক্ষ্য করতে পারেন যে প্লেয়ার নিয়ন্ত্রণগুলি বাড়ির এবং পিছনের অঙ্গভঙ্গি অঞ্চলগুলির খুব কাছাকাছি রয়েছে৷
4. প্রান্ত থেকে প্রান্ত যান
প্রান্ত থেকে প্রান্ত কি?
যে অ্যাপগুলি Android 10 বা উচ্চতর সংস্করণে চালিত হয়, সেগুলি নেভিগেশনের জন্য অঙ্গভঙ্গি বা বোতামগুলি সক্ষম করা হোক না কেন, একটি সম্পূর্ণ প্রান্ত থেকে প্রান্তের স্ক্রিন অভিজ্ঞতা দিতে পারে। এজ-টু-এজ অভিজ্ঞতা অফার করতে, আপনার অ্যাপগুলিকে অবশ্যই স্বচ্ছ নেভিগেশন এবং স্ট্যাটাস বারগুলির পিছনে আঁকতে হবে।
নেভিগেশন বারের পিছনে আঁকুন
আপনার অ্যাপটি নেভিগেশন বারের অধীনে বিষয়বস্তু রেন্ডার করতে, আপনাকে প্রথমে নেভিগেশন বার পটভূমি স্বচ্ছ করতে হবে। তারপর আপনি স্ট্যাটাস বার স্বচ্ছ করতে হবে. এটি আপনার অ্যাপটিকে স্ক্রিনের সম্পূর্ণ উচ্চতার জন্য আপনার অ্যাপ প্রদর্শন করতে দেয়।
নেভিগেশন বার এবং স্ট্যাটাস বারের রঙ পরিবর্তন করতে, নিম্নলিখিত পদক্ষেপগুলি সম্পাদন করুন:
- নেভিগেশন বার:
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>
সিস্টেম UI দৃশ্যমানতা পতাকা
সিস্টেম বারগুলির নীচে অ্যাপটি রাখতে সিস্টেমকে বলার জন্য আপনাকে অবশ্যই সিস্টেম UI দৃশ্যমানতা পতাকা সেট করতে হবে৷ View
ক্লাসে systemUiVisibility
এপিআই বিভিন্ন ধরনের পতাকা সেট করতে দেয়। নিম্নলিখিত পদক্ষেপগুলি সম্পাদন করুন:
-
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
নেভিগেশন বারের পিছনে লুকানো আছে এবং প্লে/পজ বেশিরভাগ নেভিগেশন বার দ্বারা আচ্ছাদিত। - অন্বেষণ এবং একটি বিট পরীক্ষা. আপনার কাজ শেষ হওয়ার পরে, সিস্টেম সেটিংসে নেভিগেট করুন এবং জেসচার নেভিগেশনে ফিরে যান:
অ্যাপটি এখন এজ-টু-এজ আঁকছে, কিন্তু ব্যবহারযোগ্যতার সমস্যা আছে, অ্যাপ নিয়ন্ত্রণ করে কোন দ্বন্দ্ব এবং ওভারল্যাপ, এবং এগুলো অবশ্যই সমাধান করা উচিত।
5. ইনসেট
WindowInsets
অ্যাপটিকে বলে যে যেখানে সিস্টেম UI আপনার সামগ্রীর উপরে প্রদর্শিত হয়, সেই সাথে স্ক্রিনের কোন অঞ্চলগুলি সিস্টেম অঙ্গভঙ্গিগুলি অ্যাপ-মধ্যস্থ অঙ্গভঙ্গির চেয়ে অগ্রাধিকার নেয়৷ Jetpack- এ WindowInsets
ক্লাস এবং WindowInsetsCompat
ক্লাস দ্বারা ইনসেটগুলিকে উপস্থাপন করা হয়। আমরা দৃঢ়ভাবে সুপারিশ করি যে আপনি সমস্ত API স্তর জুড়ে সামঞ্জস্যপূর্ণ আচরণ করতে WindowInsetsCompat
ব্যবহার করুন৷
সিস্টেম ইনসেট এবং বাধ্যতামূলক সিস্টেম ইনসেট
নিম্নলিখিত ইনসেট APIগুলি হল সবচেয়ে বেশি ব্যবহৃত ইনসেট প্রকার:
- সিস্টেম উইন্ডো ইনসেট: তারা আপনাকে বলে যে আপনার অ্যাপে সিস্টেম UI কোথায় প্রদর্শিত হবে। আমরা আলোচনা করি কিভাবে আপনি সিস্টেম বার থেকে আপনার নিয়ন্ত্রণগুলি সরাতে সিস্টেম ইনসেটগুলি ব্যবহার করতে পারেন।
- সিস্টেম অঙ্গভঙ্গি ইনসেট: তারা সমস্ত অঙ্গভঙ্গি এলাকা ফেরত দেয়। এই অঞ্চলে যেকোনো ইন-অ্যাপ সোয়াইপ কন্ট্রোল ঘটনাক্রমে সিস্টেম জেসচার ট্রিগার করতে পারে।
- বাধ্যতামূলক অঙ্গভঙ্গি ইনসেট: এগুলি সিস্টেম জেসচার ইনসেটগুলির একটি উপসেট এবং ওভাররাইড করা যায় না৷ তারা আপনাকে স্ক্রিনের সেই ক্ষেত্রগুলি বলে যেখানে সিস্টেম জেসচারের আচরণ সবসময় অ্যাপ-মধ্যস্থ অঙ্গভঙ্গির চেয়ে অগ্রাধিকার নেবে৷
অ্যাপ নিয়ন্ত্রণ সরাতে ইনসেট ব্যবহার করুন
এখন যেহেতু আপনি ইনসেট API সম্পর্কে আরও জানেন, আপনি অ্যাপ নিয়ন্ত্রণগুলি ঠিক করতে পারেন, যেমনটি নিম্নলিখিত ধাপে বর্ণনা করা হয়েছে:
-
view
অবজেক্ট ইনস্ট্যান্স থেকেplayerLayout
একটি উদাহরণ পান। -
playerView
একটিOnApplyWindowInsetsListener
যোগ করুন। - দৃষ্টিভঙ্গি এলাকা থেকে দূরে সরান: নীচের জন্য সিস্টেম ইনসেট মান খুঁজুন এবং সেই পরিমাণ দ্বারা ভিউ প্যাডিং বাড়ান। সেই অনুযায়ী ভিউয়ের প্যাডিং আপডেট করতে, [অ্যাপের নিচের প্যাডিংয়ের সাথে যুক্ত মান] যোগ করুন [সিস্টেমের ইনসেট নিচের মানের সাথে যুক্ত মান]।
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
একাধিকবার প্রেরণ করা যেতে পারে।
playerView
এ বর্তমান InsetListener
প্রথমবার পুরোপুরি কাজ করে যখন আপনি অ্যাপ্লিকেশানের নীচের প্যাডিং মানের সাথে activity_main.xml
এ ঘোষিত ইনসেট নীচের মানের পরিমাণ যোগ করেন। পরবর্তী কলগুলি, যাইহোক, ইতিমধ্যে আপডেট করা ভিউয়ের নীচের প্যাডিংয়ে ইনসেট নীচের মান যোগ করা চালিয়ে যায়।
এটি প্রতিকার করতে, নিম্নলিখিত পদক্ষেপগুলি সম্পাদন করুন:
- প্রারম্ভিক ভিউ প্যাডিং মান রেকর্ড করুন। একটি নতুন ভ্যাল তৈরি করুন এবং শ্রোতা কোডের ঠিক আগে
playerView
এর প্রাথমিক ভিউ প্যাডিং মান সংরক্ষণ করুন।
NowPlayingFragment.kt
এর নিম্নলিখিত কোড নমুনা পর্যালোচনা করুন:
val initialPadding = playerView.paddingBottom
- দৃশ্যের নীচের প্যাডিং আপডেট করতে এই প্রাথমিক মানটি ব্যবহার করুন, যা আপনাকে অ্যাপের বর্তমান নীচের প্যাডিং মান ব্যবহার এড়াতে দেয়৷
NowPlayingFragment.kt
এর নিম্নলিখিত কোড নমুনা পর্যালোচনা করুন:
playerView.setOnApplyWindowInsetsListener { view, insets ->
view.updatePadding(bottom = insets.systemWindowInsetBottom + initialPadding)
insets
}
- আবার অ্যাপটি চালান। অ্যাপগুলির মধ্যে নেভিগেট করুন এবং হোম স্ক্রিনে যান। আপনি যখন অ্যাপটি ফেরত দেন, প্লেয়ার নিয়ন্ত্রণগুলি অঙ্গভঙ্গি এলাকার ঠিক জায়গায় থাকে৷
অ্যাপ কন্ট্রোল রিডিজাইন করুন
প্লেয়ারের সিকবার নীচের অঙ্গভঙ্গি এলাকার খুব কাছাকাছি, যার মানে ব্যবহারকারীরা একটি অনুভূমিক সোয়াইপ সম্পূর্ণ করার সময় ভুলবশত হোম জেসচার ট্রিগার করতে পারে। আপনি যদি আরও বেশি প্যাডিং বাড়ান, তবে এটি সমস্যাটির সমাধান করতে পারে, তবে এটি প্লেয়ারটিকে পছন্দের চেয়ে বেশি স্থানান্তর করতে পারে।
ইনসেটগুলির ব্যবহার আপনাকে অঙ্গভঙ্গি দ্বন্দ্বগুলি ঠিক করতে দেয়, তবে কখনও কখনও ছোট নকশার পরিবর্তনের সাথে, আপনি সম্পূর্ণরূপে অঙ্গভঙ্গি দ্বন্দ্ব এড়াতে পারেন। অঙ্গভঙ্গি দ্বন্দ্ব এড়াতে প্লেয়ার নিয়ন্ত্রণগুলি পুনরায় ডিজাইন করতে, নিম্নলিখিত পদক্ষেপগুলি সম্পাদন করুন:
-
fragment_nowplaying.xml
খুলুন। ডিজাইন ভিউতে স্যুইচ করুন এবং খুব নীচেSeekBar
নির্বাচন করুন:
- কোড ভিউতে স্যুইচ করুন।
-
SeekBar
playerLayout
শীর্ষে নিয়ে যেতে, SeekBar-এরlayout_constraintTop_toBottomOf
কেparent
পরিবর্তন করুন। -
playerView
-এর অন্যান্য আইটেমগুলিকেSeekBar
নীচে সীমাবদ্ধ করতে,media_button
,title
এবংposition
layout_constraintTop_toTopOf
প্যারেন্ট থেকে@+id/seekBar
এ পরিবর্তন করুন।
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>
- অ্যাপটি চালান এবং প্লেয়ার এবং সিকবারের সাথে ইন্টারঅ্যাক্ট করুন।
এই ন্যূনতম ডিজাইন পরিবর্তনগুলি অ্যাপটিকে উল্লেখযোগ্যভাবে উন্নত করে।
6. অঙ্গভঙ্গি বর্জন API
বাড়ির অঙ্গভঙ্গি এলাকায় অঙ্গভঙ্গি দ্বন্দ্বের জন্য প্লেয়ার নিয়ন্ত্রণগুলি স্থির করা হয়েছে৷ পিছনের অঙ্গভঙ্গি এলাকাটি অ্যাপ নিয়ন্ত্রণের সাথে দ্বন্দ্ব তৈরি করতে পারে। নিম্নলিখিত স্ক্রিনশটটি দেখায় যে প্লেয়ার সিকবার বর্তমানে ডান এবং বাম পিছনের অঙ্গভঙ্গি উভয় ক্ষেত্রেই থাকে:
SeekBar
স্বয়ংক্রিয়ভাবে অঙ্গভঙ্গি দ্বন্দ্ব পরিচালনা করে। তবুও আপনাকে অন্যান্য UI উপাদানগুলি ব্যবহার করতে হতে পারে যা অঙ্গভঙ্গি দ্বন্দ্ব ট্রিগার করে। এই ক্ষেত্রে, আপনি আংশিকভাবে পিছনের অঙ্গভঙ্গি থেকে অপ্ট আউট করতে Gesture Exclusion API
ব্যবহার করতে পারেন৷
জেসচার এক্সক্লুশন API ব্যবহার করুন
একটি অঙ্গভঙ্গি বর্জন অঞ্চল তৈরি করতে, rect
অবজেক্টের একটি তালিকা সহ আপনার ভিউতে setSystemGestureExclusionRects()
এ কল করুন। এই rect
বস্তুগুলি বাদ দেওয়া আয়তক্ষেত্রগুলির স্থানাঙ্কে মানচিত্র তৈরি করে। এই কলটি অবশ্যই দৃশ্যের onLayout()
বা onDraw()
পদ্ধতিতে করা উচিত। এটি করার জন্য, নিম্নলিখিত পদক্ষেপগুলি সম্পাদন করুন:
-
view
নামে একটি নতুন প্যাকেজ তৈরি করুন। - এই API কল করতে,
MySeekBar
নামে একটি নতুন ক্লাস তৈরি করুন এবংAppCompatSeekBar
প্রসারিত করুন।
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-এর সীমা 200 ডিপি, শুধুমাত্র সিকবারের থাম্ব বাদ দিন। সিকবারের সীমার একটি অনুলিপি পান এবং প্রতিটি বস্তুকে একটি পরিবর্তনযোগ্য তালিকায় যুক্ত করুন।
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()
}
}
- আপনার তৈরি করা
gestureExclusionRects
তালিকা সহsystemGestureExclusionRects()
কল করুন।
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
}
-
onDraw()
বাonLayout()
থেকেupdateGestureExclusion()
পদ্ধতিতে কল করুন।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" />
NowPlayingFragment.kt
এSeekBar
রেফারেন্স আপডেট করতে,NowPlayingFragment.kt
খুলুন এবংpositionSeekBar
এর ধরন পরিবর্তন করেMySeekBar
করুন। ভেরিয়েবল টাইপের সাথে মেলাতে,findViewById
কলের জন্যSeekBar
জেনেরিক পরিবর্তন করুনMySeekBar
এ।
NowPlayingFragment.kt
এর নিম্নলিখিত কোড নমুনা পর্যালোচনা করুন:
val positionSeekBar: MySeekBar = view.findViewById<MySeekBar>(
R.id.seekBar
).apply { progress = 0 }
- অ্যাপটি চালান এবং
SeekBar
সাথে ইন্টারঅ্যাক্ট করুন। আপনি যদি এখনও অঙ্গভঙ্গি দ্বন্দ্ব অনুভব করেন, আপনিMySeekBar
এ থাম্ব বাউন্ড পরীক্ষা এবং সংশোধন করতে পারেন। সতর্কতা অবলম্বন করুন যাতে প্রয়োজনের চেয়ে বড় একটি অঙ্গভঙ্গি বর্জন অঞ্চল তৈরি না হয়, কারণ এটি অন্যান্য সম্ভাব্য অঙ্গভঙ্গি বর্জন কলগুলিকে সীমিত করে এবং ব্যবহারকারীর জন্য অসামঞ্জস্যপূর্ণ আচরণ তৈরি করে৷
7. অভিনন্দন
অভিনন্দন! আপনি শিখেছেন কিভাবে সিস্টেম জেসচারের সাথে দ্বন্দ্ব এড়াতে এবং সমাধান করতে হয়!
আপনি যখন এজ-টু-এজ প্রসারিত করেছেন এবং অঙ্গভঙ্গি অঞ্চল থেকে অ্যাপ নিয়ন্ত্রণগুলিকে দূরে সরানোর জন্য ইনসেটগুলি ব্যবহার করেছেন তখন আপনি আপনার অ্যাপটিকে পূর্ণ-স্ক্রীন ব্যবহার করেছেন৷ অ্যাপ কন্ট্রোলে সিস্টেম ব্যাক জেসচার কিভাবে অক্ষম করতে হয় তাও আপনি শিখেছেন।
আপনার অ্যাপগুলিকে সিস্টেম জেসচারের সাথে কাজ করতে প্রয়োজনীয় মূল পদক্ষেপগুলি আপনি এখন জানেন!
অতিরিক্ত উপকরণ
- WindowInsets — লেআউটের শ্রোতা
- অঙ্গভঙ্গি নেভিগেশন: প্রান্ত থেকে প্রান্ত যাচ্ছে
- অঙ্গভঙ্গি নেভিগেশন: চাক্ষুষ ওভারল্যাপ পরিচালনা করা
- অঙ্গভঙ্গি নেভিগেশন: অঙ্গভঙ্গি দ্বন্দ্ব পরিচালনা করা
- অঙ্গভঙ্গি নেভিগেশন সঙ্গে সামঞ্জস্য নিশ্চিত করুন