একটি অ্যাপ্লিকেশন ডিজাইন করা হয়ে থাকে কামশlőd এবং অধিকাংশ সময় একটি হোয়াইটবোর্ড থাকে যেখান থেকে ভিন্ন পয়েন্ট থেকে অন্যগুলোর দিকে অ্যারো পয়েন্ট করে।
আপনি যা প্রাথমিকভাবে ভাবতেন একটি বা দুটি অ্যাক্টিভিটির অ্যাপ্লিকেশন, হঠাৎ একাধিক ফ্লো, ফ্র্যাগমেন্ট এবং ব্যাপক ইউজার ইন্টারঅ্যাকশন দিয়ে দেখায়। তখন কতটা ভালো হতো, যদি আমরা হোয়াইটবোর্ডে যা আছে সেটি কোডে সহজে রিপ্লিকেট করতে পারতাম?
Navigation Component-কে বলুন হ্যালো।
অপরিচিতদের জন্য, Navigation Component আরেকটি UI ক্লাস নয় যা আপনি আপনার অ্যাক্টিভিটি/ফ্র্যাগমেন্টের লেআউটের বদলে রাখবেন। এটি একটি ম্যাপের মতো চিন্তা করুন, যেখানে কন্টিনেন্টের বদলে আপনার ফ্র্যাগমেন্ট আছে, এবং আপনাকে কন্টিনেন্ট থেকে কন্টিনেন্টে যেতে directions দরকার। এটি আপনার ফ্র্যাগমেন্ট এবং তাদের মধ্যে কানেকশনকে টপ-ডাউন ম্যানারে প্রেজেন্ট করে। এই আর্টিকেলে, আমরা এই কম্পোনেন্টের মূল দিকগুলো দেখব এবং শিখব কীভাবে আমাদের অ্যাপ্লিকেশনে এটি ইন্টিগ্রেট করতে পারি।
প্রস্থান করার জন্য প্রস্তুত? ⛵️
Learning The Ropes
Navigation component Android Studio 3.3 এবং তারপর থেকে উপলব্ধ। এটি ব্যবহার করতে, আপনার প্রজেক্টে নিচের dependency যোগ করুন:
android { ... } dependencies { implementation 'androidx.navigation:navigation-fragment-ktx:2.0.0' implementation 'androidx.navigation:navigation-ui-ktx:2.0.0' }
কিছু কাজ করার জন্য, ধরি আমরা একটি অ্যাপ্লিকেশন ডিজাইন করেছি নিচের স্ট্রাকচারের সাথে:
- Start Fragment
- Fragment A
- Fragment B
ব্যবহারকারী Start fragment থেকে Fragment A বা Fragment B-এ যেতে পারে।
যদি আমরা Navigation Component ছাড়া এই সব করতে চাই, তবে আমাদের সেই সবচেয়ে পরিচিত কোড লিখতে হবে যখন বাটন ক্লিক হলে একটি ফ্র্যাগমেন্ট ওপেন করতে।
val myFragment : MyFragment = MyFragment() supportFragmentManager.beginTransaction().add(R.id.container, myFragment).commit()
আমাদের এই ছোট উদাহরণে, এটি কিছু ছোট লাইন এবং কিছুটা অজটিল, কিন্তু আমরা সবাই সেম্মত হব যে এটি উপযুক্তভাবে স্কেল করবে না যদি আমাদের অ্যাপ্লিকেশন বড় হয় এবং আরও কমপ্লেক্স ইউজার ফ্লো থাকে।
All Aboard
Navigation Component ব্যবহার শুরু করতে, আমাদের একটি navigation graph তৈরি করতে হবে। এই গ্রাফ আমাদের ম্যাপ হিসেবে কাজ করবে, আমাদের অ্যাপ্লিকেশনে ইউজার ফ্লো আউटलাইন করবে। একটি তৈরি করতে, res ফোল্ডারে রাইট ক্লিক করুন এবং একটি নতুন রিসোর্স ফাইল তৈরি করুন। আমরা আমাদের নাম দিব: user_flow_graph.xml। ফাইল টাইপ Navigation হিসেবে মার্ক করা নিশ্চিত করুন।
প্রতিটি যাত্রা একটি হোম বেস থেকে শুরু হয় এবং আমারও অপवाद নয়। আমাদের হোমকে NavHost বলা হয়। এটি ডেস্টিনেশনের জন্য একটি প্লেসহোল্ডার হিসেবে কাজ করবে যেগুলো স্ব্যাপ হবে যখন ইউজার আমাদের UI-র সাথে ইন্টারঅ্যাক্ট করবে। আমাদের NavHostকে আমাদের অ্যাক্টিভিটির মেইন লেআউটে যোগ করতে হবে:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:tools="https://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="https://schemas.android.com/apk/res-auto" tools:context=".MainActivity"> <fragment android:id="@+id/nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:defaultNavHost="true" app:navGraph="@navigation/user_flow_graph" /> </androidx.constraintlayout.widget.ConstraintLayout>
আমরা একটি fragment element যোগ করলাম যা হাউজ করবে যেখানে আমাদের ফ্র্যাগমেন্ট ডিসপ্লে এবং স্ব্যাপ হবে। navGraph অ্যাট্রিবিউটে ফোকাস করুন, যা আমরা আমাদের পূর্বে তৈরি XML ফাইলের সাথে লিংক করেছি।
এখন আমাদের একটি স্টার্টিং ডেস্টিনেশন যোগ করতে হবে, কারণ আমাদের অ্যাপ্লিকেশন কম্পাইল হবে না যদি না করি।
user_flow_graph.xml খোলার সাথে, আমাদের Navigation Editor-এ ছোট প্লাস আইকনে ক্লিক করতে হবে:
আপনি পপ-আপ মেনুতে দেখতে পাচ্ছেন, আমরা হয় একটি 플레이스হোল্ডার তৈরি করতে পারি যা পরে ফিল আপ করতে হবে অথবা আমাদের যেকোনো ফ্র্যাগমেন্ট চয়ন করতে পারি:
আমাদের ইউজার ফ্লো Start Fragment থেকে শুরু হয়, তাই প্রথমে সেটি চয়ন করি।
আমাদের অন্য দুটি ফ্র্যাগমেন্ট, fragment A এবং fragment B যোগ করি।
দুই ডেস্টিনেশন কানেক্ট করতে ডটে ক্লিক করুন যা হোভার করলে ডেস্টিনেশনের ওপর দেখায় এবং অন্য ডেস্টিনেশনে ড্র্যাগ করুন।
আমরা Start fragment এবং fragment A ও B-এর মধ্যে যা তৈরি করলাম, সেগুলো হলো actions।
Shiver me Timbers
আপনি হয়তো নিজে থেকে জিজ্ঞেস করেছেন, কি শুধু ডেস্টিনেশন কানেক্ট করলে আমাদের কাজ এখানেই শেষ এবং যাদুকরিভাবে সব কিছু কাজ করবে।
তবে, সেটি হবে না।
আমাদের কোডকে বলতে হবে একটি ডেস্টিনেশনে নেভিগেট করতে। তাহলে, আমরা কীভাবে সেটি করব? প্রসেসে কিছু ম্যাজিক জড়িত।
প্রথম কাজ আমরা করব, একটি gradle plugin আড করব যাকে Safe Args বলা হয়। এটি নেভিগেট করার সময় ডেস্টিনেশনের মাঝপথে টাইপ সেফটি নিশ্চিত করবে।
buildscript { /... } dependencies { ... classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.0.0" } }
আমাদের অ্যাপ্লিকেশনের build.gradle-এ নিচের প্লাগইনও যোগ করতে হবে:
apply plugin: "androidx.navigation.safeargs.kotlin"
এছাড়া, নিশ্চিত করুন android.useAndroidX=true আপনার gradle.properties ফাইলে।
আগে বড়তে যাওয়ার আগে, বুঝি কেন আমাদের এই সকল কনফিগারেশন যোগ করতে হয়েছিল। বেসিক্যালি, যখন আমরা actions তৈরি করলাম, পর্দার পেছনে Android Studio কোড জেনারেট করে যা আমরা actions এক্টিভেট করতে ব্যবহার করব। এই কোড মেথড এবং ক্লাস নিয়ে গঠিত যা প্রতিটি action রিপ্রেজেন্ট করে। আমাদের Start fragment নিই উদাহরণ হিসেবে। আমরা যা actions ডিক্লেয়ার করলাম তার জন্য জেনারেটেড কোডে একটি ক্লাস থাকবে StartFragmentDirections। এই ক্লাসের মেথডগুলো আগে তৈরি করা actions রিপ্রেজেন্ট করে। আমাদের দুটি ফ্র্যাগমেন্টের জন্য আমরা পাব:
- StartFragmentDirections.actionStartFragmentToFragmentA()
- StartFragmentDirections.actionStartFragmentToFragmentB()
এখন আমাদের actions কোডে অনুবাদ হয়েছে, চলুন সেগুলো ব্যবহার করি:
val action = StartFragmentDirections.actionStartFragmentToFragmentA()
এই প্রসেসের লাস্ট স্টেপ হচ্ছে NavController ব্যবহার করা। এই অবজেক্ট আমাদের NavHost-এ নেভিগেশন ম্যানেজ করার দায়বদ্ধ। আপনি এটিকে এই তিনটি মেথডের যেকোনো একটითে অ্যাক্সেস করতে পারেন:
- Fragment.findNavController()
- View.findNavController()
- Activity.findNavController(viewId: Int)
তাহলে, সব মিলিয়ে আমরা পাব:
fragmentABtn.setOnClickListener { button -> val action = StartFragmentDirections.actionStartFragmentToFragmentA() button.findNavController().navigate(action) }
Trim Your Sails
যদি আমরা আমাদের ডেস্টিনেশনের মাঝপথে ডেটা পাস করতে চাই? একটি সিনেরিও কল্পনা করুন যেখানে ইউজার কোনো নির্দিষ্ট আইটেমে ক্লিক করলে, আমরা সেই আইটেমের সাথে আমাদের নেক্সট ডেস্টিনেশনে কিছু করতে চাই। সেটির জন্য ডেস্টিনেশন আর্গুমেন্ট আছে। user_flow_graph.xml খুলুন এবং Fragment A-এ ক্লিক করুন। ডান পাশে আপনি Fragment A-এর বিভিন্ন অ্যাট্রিবিউট ডিটেইলস জানতে পারবেন একটি মেনু। তার মধ্যে একটি হবে Arguments।
আর্গুমেন্ট যোগ করতে, শুধু ➕ আইকনে ক্লিক করুন। একটি পপ-আপ উইন্ডো খুলবে এবং সেটিতে আমরা আমাদের আর্গুমেন্ট কনফিগার করতে পারব। আপনি এটিকে একটি নাম দিতে পারেন, এর টাইপ চয়ন করতে পারেন এবং একটি ডিফল্ট ভ্যালু যোগ করতে পারেন। চলুন Fragment A-এ একটি String টাইপ আর্গুমেন্ট যোগ করি, যা Start fragment থেকে পাস করা মেসেজ হবে।
আমাদের Start fragment-এ, যেখানে আমরা আমাদের action ডিফাইন করলাম এবং জেনারেটেড মেথড কল করছি, সেখানে আমরা আমাদের আর্গুমেন্ট পাস করব।
fragmentABtn.setOnClickListener { button -> val action = StartFragmentDirections.actionStartFragmentToFragmentA("Hello From Start Fragment") button.findNavController().navigate(action) }
Fragment A-এ এটি অ্যাক্সেস করতে, আমাদের হয়:
- bundle অ্যাক্সেস করে আমাদের মেসেজ ভ্যালু পেতে
class FragmentA: Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val bundle = arguments val root = inflater.inflate(R.layout.fragment_a, container, false) val textView : TextView = root.findViewById(R.id.textView) textView.text = bundle?.getString("message") return root } }
- navArgs ব্যবহার করুন যদি আমরা -ktx dependencies ব্যবহার করি
class FragmentA: Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val args : FragmentAArgs by navArgs() val root = inflater.inflate(R.layout.fragment_a, container, false) val textView : TextView = root.findViewById(R.id.textView) textView.text = args.message return root } }
✋ navArgs ব্যবহার করার সময়, আপনাকে আপনার build.gradle ফাইলে Java8 সাপোর্ট যোগ করতে হবে।
এখানে দেখানো সকল কোড এই GitHub রিপোজিটরিতে পাওয়া যাবে।