MDC-102 Android: উপাদানের গঠন এবং বিন্যাস (কোটলিন)

১. ভূমিকা

logo_components_color_2x_web_96dp.png

ম্যাটেরিয়াল কম্পোনেন্টস (MDC) ডেভেলপারদের ম্যাটেরিয়াল ডিজাইন বাস্তবায়ন করতে সাহায্য করে। গুগলের একদল ইঞ্জিনিয়ার এবং ইউএক্স ডিজাইনার দ্বারা তৈরি, MDC-তে কয়েক ডজন সুন্দর এবং কার্যকরী UI কম্পোনেন্ট রয়েছে এবং এটি অ্যান্ড্রয়েড, আইওএস, ওয়েব এবং ফ্লাটারের জন্য উপলব্ধ। material.io/develop

কোডল্যাব MDC-101-এ, আপনি একটি লগইন পেজ তৈরি করতে দুটি ম্যাটেরিয়াল কম্পোনেন্ট (MDC) ব্যবহার করেছেন: টেক্সট ফিল্ড এবং ইঙ্ক রিপলযুক্ত বাটন। এখন চলুন নেভিগেশন, স্ট্রাকচার এবং ডেটা যোগ করে এই ভিত্তিটিকে আরও বিস্তৃত করি।

আপনি যা তৈরি করবেন

এই কোডল্যাবে, আপনি Shrine নামক একটি অ্যাপের জন্য একটি হোম স্ক্রিন তৈরি করবেন, যেটি পোশাক এবং গৃহস্থালীর সামগ্রী বিক্রি করে এমন একটি ই-কমার্স অ্যাপ। এতে থাকবে:

  • একটি শীর্ষ অ্যাপ বার
  • পণ্যে পূর্ণ একটি গ্রিড তালিকা

249db074eff043f4.png

এই কোডল্যাবে MDC-অ্যান্ড্রয়েড উপাদানসমূহ

  • অ্যাপবারলেআউট
  • ম্যাটেরিয়ালকার্ডভিউ

আপনার যা যা লাগবে

  • অ্যান্ড্রয়েড ডেভেলপমেন্টের প্রাথমিক জ্ঞান
  • অ্যান্ড্রয়েড স্টুডিও (আপনার কাছে না থাকলে এখান থেকে ডাউনলোড করুন)
  • একটি অ্যান্ড্রয়েড এমুলেটর বা ডিভাইস (অ্যান্ড্রয়েড স্টুডিওর মাধ্যমে উপলব্ধ)
  • নমুনা কোড (পরবর্তী ধাপ দেখুন)

অ্যান্ড্রয়েড অ্যাপ তৈরিতে আপনার অভিজ্ঞতার স্তরকে আপনি কীভাবে মূল্যায়ন করবেন?

শিক্ষানবিশ মধ্যবর্তী দক্ষ

২. আপনার ডেভেলপমেন্ট এনভায়রনমেন্ট সেট আপ করুন।

MDC-101 এর ধারাবাহিকতায়?

আপনি যদি MDC-101 সম্পন্ন করে থাকেন, তাহলে আপনার কোড এই কোডল্যাবের জন্য প্রস্তুত থাকা উচিত। সরাসরি ধাপ ৩-এ যান: একটি টপ অ্যাপ বার যোগ করুন

একেবারে নতুন করে শুরু করছেন?

স্টার্টার কোডল্যাব অ্যাপটি ডাউনলোড করুন

স্টার্টার অ্যাপটি material-components-android-codelabs-102-starter/kotlin ডিরেক্টরিতে অবস্থিত। কাজ শুরু করার আগে অবশ্যই ওই ডিরেক্টরিতে cd

...অথবা গিটহাব থেকে এটি ক্লোন করুন

গিটহাব থেকে এই কোডল্যাবটি ক্লোন করতে, নিম্নলিখিত কমান্ডগুলো চালান:

git clone https://github.com/material-components/material-components-android-codelabs
cd material-components-android-codelabs/
git checkout 102-starter

অ্যান্ড্রয়েড স্টুডিওতে স্টার্টার কোড লোড করুন।

  1. সেটআপ উইজার্ড শেষ হয়ে গেলে এবং ' Welcome to Android Studio' উইন্ডোটি দেখা গেলে, 'Open an existing Android Studio project'-এ ক্লিক করুন। যে ডিরেক্টরিতে আপনি স্যাম্পল কোডটি ইনস্টল করেছিলেন সেখানে যান এবং শিপিং প্রজেক্টটি খোলার জন্য 'kotlin -> shrine' নির্বাচন করুন (অথবা আপনার কম্পিউটারে 'shrine' লিখে সার্চ করুন)।
  2. অ্যান্ড্রয়েড স্টুডিও উইন্ডোর নিচের দিকে অ্যাক্টিভিটি ইন্ডিকেটরগুলোতে যেমনটা দেখানো হচ্ছে, প্রজেক্টটি বিল্ড ও সিঙ্ক হওয়ার জন্য কিছুক্ষণ অপেক্ষা করুন।
  3. এই পর্যায়ে, অ্যান্ড্রয়েড স্টুডিও কিছু বিল্ড এরর দেখাতে পারে, কারণ আপনার কাছে অ্যান্ড্রয়েড এসডিকে বা বিল্ড টুলস নেই, যেমনটি নিচে দেখানো হয়েছে। এগুলো ইনস্টল/আপডেট করতে এবং আপনার প্রজেক্ট সিঙ্ক করতে অ্যান্ড্রয়েড স্টুডিওর নির্দেশাবলী অনুসরণ করুন।

KzoYWC1S7Se7yL8igi1vXF_mbVxAdl2lg5kb7RODrsVpEng0G6U3NK1Qnn0faBBZd2u71yMXioy9tD-7fv3NXvVO4N3EtMMeWDTmqBMMl6egd9R5uXX0T_SKmahbmRor3wZZHX0ByA

প্রকল্পের নির্ভরতা যোগ করুন

প্রজেক্টটির জন্য MDC অ্যান্ড্রয়েড সাপোর্ট লাইব্রেরির উপর নির্ভরতা প্রয়োজন। আপনার ডাউনলোড করা স্যাম্পল কোডে এই নির্ভরতাটি আগে থেকেই তালিকাভুক্ত থাকার কথা, কিন্তু তা নিশ্চিত করার জন্য নিম্নলিখিত পদক্ষেপগুলো অনুসরণ করা ভালো।

  1. app মডিউলের build.gradle ফাইলে যান এবং নিশ্চিত করুন যে dependencies ব্লকে MDC Android-এর উপর একটি ডিপেন্ডেন্সি অন্তর্ভুক্ত আছে:
api 'com.google.android.material:material:1.1.0-alpha06'
  1. (ঐচ্ছিক) প্রয়োজনে, build.gradle ফাইলটি সম্পাদনা করে নিম্নলিখিত ডিপেন্ডেন্সিগুলো যোগ করুন এবং প্রজেক্টটি সিঙ্ক করুন।
dependencies {
    api 'com.google.android.material:material:1.1.0-alpha06'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'com.android.volley:volley:1.1.1'
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21"
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:core:1.1.0'
    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
    androidTestImplementation 'androidx.test:runner:1.2.0-alpha05'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha05'
}

স্টার্টার অ্যাপটি চালান

  1. নিশ্চিত করুন যে রান / প্লে বাটনের বাম দিকের বিল্ড কনফিগারেশনটি app হিসেবে সেট করা আছে।
  2. অ্যাপটি বিল্ড ও রান করতে সবুজ রান / প্লে বাটনটি চাপুন।
  3. 'Select Deployment Target' উইন্ডোতে, আপনার উপলব্ধ ডিভাইসগুলোর তালিকায় যদি আগে থেকেই কোনো অ্যান্ড্রয়েড ডিভাইস তালিকাভুক্ত থাকে, তাহলে সরাসরি ধাপ ৮- এ চলে যান। অন্যথায়, 'Create New Virtual Device'-এ ক্লিক করুন।
  4. হার্ডওয়্যার নির্বাচন স্ক্রিনে, পিক্সেল ২-এর মতো একটি ফোন ডিভাইস নির্বাচন করুন এবং তারপরে পরবর্তী (Next) ক্লিক করুন।
  5. সিস্টেম ইমেজ স্ক্রিনে, একটি সাম্প্রতিক অ্যান্ড্রয়েড সংস্করণ নির্বাচন করুন, বিশেষত সর্বোচ্চ এপিআই লেভেলেরটি। যদি এটি ইনস্টল করা না থাকে, তবে প্রদর্শিত ডাউনলোড লিঙ্কে ক্লিক করুন এবং ডাউনলোডটি সম্পূর্ণ করুন।
  6. পরবর্তী ধাপে যান।
  7. অ্যান্ড্রয়েড ভার্চুয়াল ডিভাইস (AVD) স্ক্রিনে, সেটিংস অপরিবর্তিত রেখে ফিনিশ-এ ক্লিক করুন।
  8. ডেপ্লয়মেন্ট টার্গেট ডায়ালগ থেকে একটি অ্যান্ড্রয়েড ডিভাইস নির্বাচন করুন।
  9. Ok ক্লিক করুন।
  10. অ্যান্ড্রয়েড স্টুডিও অ্যাপটি বিল্ড করে, ডেপ্লয় করে এবং টার্গেট ডিভাইসে স্বয়ংক্রিয়ভাবে খুলে দেয়।

সফল! আপনি MDC-101 কোডল্যাব থেকে Shrine লগইন পেজটি দেখতে পাবেন।

4cb0c218948144b4.png

এখন যেহেতু লগইন স্ক্রিনটি দেখতে ভালো লাগছে, চলুন অ্যাপটিতে কিছু পণ্য যুক্ত করা যাক।

৩. একটি টপ অ্যাপ বার যোগ করুন

লগইন পেজটি বন্ধ করলে হোম স্ক্রিনটি দেখা যায়, যেখানে লেখা থাকে "আপনি পেরেছেন!"। এটা দারুণ! কিন্তু এখন আমাদের ব্যবহারকারীর করার মতো কোনো কাজ নেই, বা অ্যাপের মধ্যে তিনি কোথায় আছেন, সে সম্পর্কেও কোনো ধারণা নেই। এই সমস্যা সমাধানে, এখন নেভিগেশন যোগ করার সময় এসেছে।

ম্যাটেরিয়াল ডিজাইন এমন নেভিগেশন প্যাটার্ন প্রদান করে যা উচ্চ মাত্রার ব্যবহারযোগ্যতা নিশ্চিত করে। এর সবচেয়ে দৃশ্যমান উপাদানগুলোর মধ্যে একটি হলো টপ অ্যাপ বার।

নেভিগেশনের সুবিধা দিতে এবং ব্যবহারকারীদের অন্যান্য কাজে দ্রুত অ্যাক্সেস করার জন্য, চলুন একটি টপ অ্যাপ বার যোগ করি।

একটি অ্যাপবার উইজেট যোগ করুন

shr_product_grid_fragment.xml ফাইলে, "You did it!" TextView টি থাকা <LinearLayout> ব্লকটি মুছে ফেলুন এবং এর পরিবর্তে নিম্নলিখিত কোডটি ব্যবহার করুন:

shr_product_grid_fragment.xml

<com.google.android.material.appbar.AppBarLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content">

   <androidx.appcompat.widget.Toolbar
       android:id="@+id/app_bar"
       style="@style/Widget.Shrine.Toolbar"
       android:layout_width="match_parent"
       android:layout_height="?attr/actionBarSize"
       app:title="@string/shr_app_name" />
</com.google.android.material.appbar.AppBarLayout>

আপনার shr_product_grid_fragment.xml এখন নিম্নরূপ দেখতে হবে:

shr_product_grid_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".ProductGridFragment">

   <com.google.android.material.appbar.AppBarLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content">

       <androidx.appcompat.widget.Toolbar
           android:id="@+id/app_bar"
           style="@style/Widget.Shrine.Toolbar"
           android:layout_width="match_parent"
           android:layout_height="?attr/actionBarSize"
           app:title="@string/shr_app_name" />
   </com.google.android.material.appbar.AppBarLayout>
  
</FrameLayout>

অনেক অ্যাপ বারে শিরোনামের পাশে একটি বাটন থাকে। চলুন আমাদেরটিতে একটি মেনু আইকন যোগ করি।

একটি নেভিগেশন আইকন যোগ করুন

shr_product_grid_fragment.xml ফাইলে থাকা অবস্থায়, আপনার লেআউটে এইমাত্র যোগ করা Toolbar XML কম্পোনেন্টটিতে নিম্নলিখিত কোডটি যোগ করুন:

shr_product_grid_fragment.xml

app:navigationIcon="@drawable/shr_menu"

আপনার shr_product_grid_fragment.xml দেখতে নিম্নলিখিতের মতো হওয়া উচিত:

shr_product_grid_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".ProductGridFragment">
  
   <com.google.android.material.appbar.AppBarLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content">

       <androidx.appcompat.widget.Toolbar
           android:id="@+id/app_bar"
           style="@style/Widget.Shrine.Toolbar"
           android:layout_width="match_parent"
           android:layout_height="?attr/actionBarSize"
           app:navigationIcon="@drawable/shr_menu"
           app:title="@string/shr_app_name" />
   </com.google.android.material.appbar.AppBarLayout>
  
</FrameLayout>

অ্যাকশন বাটন যোগ করুন এবং টপ অ্যাপ বারটি স্টাইল করুন।

আপনি অ্যাপ বারের শেষ প্রান্তে বাটন যোগ করতে পারেন। অ্যান্ড্রয়েডে, এগুলোকে অ্যাকশন বাটন বলা হয়। আমরা টপ অ্যাপ বারটিকে স্টাইল করব এবং প্রোগ্রাম্যাটিকভাবে এর মেনুতে অ্যাকশন বাটন যোগ করব।

ProductGridFragment.kt এর onCreateView ফাংশনে, setSupportActionBar ব্যবহার করে activity Toolbar ActionBar হিসেবে সেট করুন। inflater দিয়ে ভিউটি তৈরি করার পর আপনি এটি করতে পারেন।

ProductGridFragment.kt

override fun onCreateView(
       inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
   // Inflate the layout for this fragment with the ProductGrid theme
   val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)

   // Set up the toolbar.
   (activity as AppCompatActivity).setSupportActionBar(view.app_bar)

   return view;
}

এরপরে, টুলবার সেট আপ করার জন্য আমরা যে মেথডটি এইমাত্র পরিবর্তন করেছি, তার ঠিক নিচে shr_toolbar_menu.xml এর কন্টেন্টগুলো টুলবারে ইনফ্লেট করার জন্য onCreateOptionsMenu ওভাররাইড করা যাক:

ProductGridFragment.kt

override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
   menuInflater.inflate(R.menu.shr_toolbar_menu, menu)
   super.onCreateOptionsMenu(menu, menuInflater)
}

অবশেষে, ProductGridFragment.ktonCreate() ওভাররাইড করুন, এবং super() কল করার পর, setHasOptionMenu true দিয়ে কল করুন:

ProductGridFragment.kt

override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   setHasOptionsMenu(true)
}

উপরের কোড স্নিপেটগুলো আমাদের XML লেআউট থেকে অ্যাপ বারটিকে এই অ্যাক্টিভিটির অ্যাকশন বার হিসেবে সেট করে। onCreateOptionsMenu কলব্যাকটি অ্যাক্টিভিটিকে বলে দেয় যে মেনু হিসেবে কী ব্যবহার করতে হবে। এক্ষেত্রে, এটি R.menu.shr_toolbar_menu থেকে মেনু আইটেমগুলো অ্যাপ বারে রাখবে। মেনু ফাইলটিতে দুটি আইটেম রয়েছে: "সার্চ" এবং "ফিল্টার"।

shr_toolbar_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto">
   <item
       android:id="@+id/search"
       android:icon="@drawable/shr_search"
       android:title="@string/shr_search_title"
       app:showAsAction="always" />
   <item
       android:id="@+id/filter"
       android:icon="@drawable/shr_filter"
       android:title="@string/shr_filter_title"
       app:showAsAction="always" />
</menu>

এই পরিবর্তনগুলোর পর, আপনার ProductGridFragment.kt ফাইলটি দেখতে নিচের মতো হবে:

ProductGridFragment.kt

package com.google.codelabs.mdc.kotlin.shrine

import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import com.google.codelabs.mdc.kotlin.shrine.network.ProductEntry
import kotlinx.android.synthetic.main.shr_product_grid_fragment.view.*

class ProductGridFragment : Fragment() {

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setHasOptionsMenu(true)
   }

   override fun onCreateView(
           inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
       // Inflate the layout for this fragment with the ProductGrid theme
       val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)

       // Set up the tool bar
       (activity as AppCompatActivity).setSupportActionBar(view.app_bar)

       return view;
   }

   override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
       menuInflater.inflate(R.menu.shr_toolbar_menu, menu)
       super.onCreateOptionsMenu(menu, menuInflater)
   }
}

বিল্ড করুন এবং চালান। আপনার হোম স্ক্রিনটি দেখতে এইরকম হবে:

d04e8aa3b27f4754.png

এখন টুলবারের ডানদিকে একটি নেভিগেশন আইকন, একটি শিরোনাম এবং দুটি অ্যাকশন আইকন রয়েছে। টুলবারটি একটি হালকা ছায়ার মাধ্যমে উচ্চতাও প্রদর্শন করে, যা দেখায় যে এটি কন্টেন্ট থেকে ভিন্ন একটি লেয়ারে রয়েছে।

৪. একটি কার্ড যোগ করুন

এখন যেহেতু আমাদের অ্যাপটির একটি কাঠামো তৈরি হয়েছে, চলুন এর বিষয়বস্তুগুলোকে কার্ডে সাজিয়ে নিই।

একটি কার্ড যোগ করুন

টপ অ্যাপ বারের নিচে একটি কার্ড যোগ করার মাধ্যমে শুরু করা যাক। একটি কার্ডে ছবির জন্য একটি জায়গা, একটি শিরোনাম এবং অতিরিক্ত লেখার জন্য একটি লেবেল থাকা উচিত। shr_product_grid_fragment.xml ফাইলে AppBarLayout নিচে নিম্নলিখিত কোডটি যোগ করুন।

shr_product_grid_fragment.xml

<com.google.android.material.card.MaterialCardView
   android:layout_width="160dp"
   android:layout_height="180dp"
   android:layout_marginBottom="16dp"
   android:layout_marginLeft="16dp"
   android:layout_marginRight="16dp"
   android:layout_marginTop="70dp"
   app:cardBackgroundColor="?attr/colorPrimaryDark"
   app:cardCornerRadius="4dp">

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_gravity="bottom"
       android:background="#FFFFFF"
       android:orientation="vertical"
       android:padding="8dp">

       <TextView
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:padding="2dp"
           android:text="@string/shr_product_title"
           android:textAppearance="?attr/textAppearanceHeadline6" />

       <TextView
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:padding="2dp"
           android:text="@string/shr_product_description"
           android:textAppearance="?attr/textAppearanceBody2" />
   </LinearLayout>
</com.google.android.material.card.MaterialCardView>

নির্মাণ ও পরিচালনা:

f6184a55ccb5f920.png

এই প্রিভিউতে আপনি দেখতে পাচ্ছেন যে, কার্ডটি বাম প্রান্ত থেকে কিছুটা ভেতরের দিকে বসানো, এবং এর কোণাগুলো গোলাকার ও একটি ছায়া রয়েছে (যা কার্ডটির উচ্চতা প্রকাশ করে)। সম্পূর্ণ এলিমেন্টটিকে "কন্টেইনার" বলা হয়। কন্টেইনারটি ছাড়া এর ভেতরের বাকি সব এলিমেন্ট ঐচ্ছিক।

আপনি একটি কন্টেইনারে নিম্নলিখিত উপাদানগুলি যোগ করতে পারেন: হেডার টেক্সট, একটি থাম্বনেইল বা অ্যাভাটার, সাবহেড টেক্সট, ডিভাইডার, এবং এমনকি বাটন ও আইকন। উদাহরণস্বরূপ, আমরা এইমাত্র যে কার্ডটি তৈরি করেছি, তাতে একটি LinearLayout মধ্যে দুটি TextView (একটি শিরোনামের জন্য এবং অন্যটি সেকেন্ডারি টেক্সটের জন্য) রয়েছে, যা কার্ডটির একেবারে নিচে অ্যালাইন করা আছে।

কার্ডগুলো সাধারণত অন্যান্য কার্ডের সাথে একটি সংগ্রহে দেখানো হয়। এই কোডল্যাবের পরবর্তী অংশে, আমরা সেগুলোকে একটি গ্রিডে সংগ্রহ হিসেবে সাজিয়ে রাখব।

৫. কার্ড দিয়ে একটি গ্রিড তৈরি করুন।

যখন একটি স্ক্রিনে একাধিক কার্ড থাকে, তখন সেগুলোকে এক বা একাধিক সংগ্রহে একত্রিত করা হয়। একটি গ্রিডের কার্ডগুলো সমতলীয় হয়, অর্থাৎ তাদের স্থির উচ্চতা একে অপরের সমান থাকে (যদি না সেগুলোকে তুলে নেওয়া বা টেনে নিয়ে যাওয়া হয়, কিন্তু আমরা এই কোডল্যাবে সে বিষয়টি আলোচনা করব না)।

তাসের গ্রিডটি সাজিয়ে নিন।

আমরা আপনাকে যে shr_product_card.xml ফাইলটি দিয়েছি, সেটি দেখুন:

shr_product_card.xml

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   app:cardBackgroundColor="@android:color/white"
   app:cardElevation="2dp"
   app:cardPreventCornerOverlap="true">

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="vertical">

       <com.android.volley.toolbox.NetworkImageView
           android:id="@+id/product_image"
           android:layout_width="match_parent"
           android:layout_height="@dimen/shr_product_card_image_height"
           android:background="?attr/colorPrimaryDark"
           android:scaleType="centerCrop" />

       <LinearLayout
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:orientation="vertical"
           android:padding="16dp">

           <TextView
               android:id="@+id/product_title"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:text="@string/shr_product_title"
               android:textAppearance="?attr/textAppearanceHeadline6" />

           <TextView
               android:id="@+id/product_price"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:text="@string/shr_product_description"
               android:textAppearance="?attr/textAppearanceBody2" />
       </LinearLayout>
   </LinearLayout>
</com.google.android.material.card.MaterialCardView>

এই কার্ড লেআউটটিতে একটি ছবিসহ একটি কার্ড (এই ক্ষেত্রে, একটি NetworkImageView , যা আমাদেরকে একটি URL থেকে ছবি লোড ও প্রদর্শন করতে দেয়) এবং দুটি TextViews রয়েছে।

এরপর, আমরা আপনার জন্য যে ProductCardRecyclerViewAdapter দিয়েছি, সেটি দেখুন। এটি ProductGridFragment এর একই প্যাকেজে রয়েছে।

ProductCardRecyclerViewAdapter.kt

package com.google.codelabs.mdc.kotlin.shrine

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView

import com.google.codelabs.mdc.kotlin.shrine.network.ProductEntry

/**
* Adapter used to show a simple grid of products.
*/
class ProductCardRecyclerViewAdapter(private val productList: List<ProductEntry>) : RecyclerView.Adapter<ProductCardViewHolder>() {

   override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductCardViewHolder {
       val layoutView = LayoutInflater.from(parent.context).inflate(R.layout.shr_product_card, parent, false)
       return ProductCardViewHolder(layoutView)
   }

   override fun onBindViewHolder(holder: ProductCardViewHolder, position: Int) {
       // TODO: Put ViewHolder binding code here in MDC-102
   }

   override fun getItemCount(): Int {
       return productList.size
   }
}

উপরের অ্যাডাপ্টার ক্লাসটি আমাদের গ্রিডের বিষয়বস্তু পরিচালনা করে। প্রতিটি ভিউ তার প্রদত্ত বিষয়বস্তু নিয়ে কী করবে, তা নির্ধারণ করার জন্য আমরা শীঘ্রই onBindViewHolder() এর কোড লিখব।

একই প্যাকেজে আপনি ProductCardViewHolder ও দেখতে পারেন। এই ক্লাসটি সেই ভিউগুলোকে সংরক্ষণ করে যেগুলো আমাদের কার্ডের বিন্যাসকে প্রভাবিত করে, ফলে আমরা পরবর্তীতে সেগুলোকে পরিবর্তন করতে পারি।

ProductCardViewHolder.kt

package com.google.codelabs.mdc.kotlin.shrine

import android.view.View
import androidx.recyclerview.widget.RecyclerView

class ProductCardViewHolder(itemView: View) //TODO: Find and store views from itemView
   : RecyclerView.ViewHolder(itemView)

আমাদের গ্রিড সেট আপ করার জন্য, প্রথমে আমাদের shr_product_grid_fragment.xml থেকে প্লেসহোল্ডার MaterialCardView সরিয়ে ফেলতে হবে। এরপর, আমাদের কার্ডের গ্রিডকে প্রতিনিধিত্বকারী কম্পোনেন্টটি যোগ করতে হবে। এক্ষেত্রে, আমরা একটি RecyclerView ব্যবহার করব। আপনার shr_product_grid_fragment.xml ফাইলে AppBarLayout XML কম্পোনেন্টের নিচে RecyclerView কম্পোনেন্টটি যোগ করুন:

shr_product_grid_fragment.xml

<androidx.core.widget.NestedScrollView
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:layout_marginTop="56dp"
   android:background="@color/productGridBackgroundColor"
   android:paddingStart="@dimen/shr_product_grid_spacing"
   android:paddingEnd="@dimen/shr_product_grid_spacing"
   app:layout_behavior="@string/appbar_scrolling_view_behavior">

   <androidx.recyclerview.widget.RecyclerView
       android:id="@+id/recycler_view"
       android:layout_width="match_parent"
       android:layout_height="match_parent" />

</androidx.core.widget.NestedScrollView>

আপনার shr_product_grid_fragment.xml দেখতে নিম্নলিখিতের মতো হওয়া উচিত:

shr_product_grid_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".ProductGridFragment">

   <com.google.android.material.appbar.AppBarLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content">

       <androidx.appcompat.widget.Toolbar
           android:id="@+id/app_bar"
           style="@style/Widget.Shrine.Toolbar"
           android:layout_width="match_parent"
           android:layout_height="?attr/actionBarSize"
           app:navigationIcon="@drawable/shr_menu"
           app:title="@string/shr_app_name" />
   </com.google.android.material.appbar.AppBarLayout>

   <androidx.core.widget.NestedScrollView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:layout_marginTop="56dp"
       android:background="@color/productGridBackgroundColor"
       android:paddingStart="@dimen/shr_product_grid_spacing"
       android:paddingEnd="@dimen/shr_product_grid_spacing"
       app:layout_behavior="@string/appbar_scrolling_view_behavior">

       <androidx.recyclerview.widget.RecyclerView
           android:id="@+id/recycler_view"
           android:layout_width="match_parent"
           android:layout_height="match_parent" />

   </androidx.core.widget.NestedScrollView>

</FrameLayout>

অবশেষে, onCreateView() ফাংশনে, setUpToolbar(view) কল করার পরে এবং return স্টেটমেন্টের আগে ProductGridFragment.kt ফাইলে RecyclerView ইনিশিয়ালাইজেশন কোডটি যোগ করুন:

ProductGridFragment.kt

override fun onCreateView(
       inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
   // Inflate the layout for this fragment with the ProductGrid theme
   val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)

   // Set up the toolbar.
   (activity as AppCompatActivity).setSupportActionBar(view.app_bar)

   // Set up the RecyclerView
   view.recycler_view.setHasFixedSize(true)
   view.recycler_view.layoutManager = GridLayoutManager(context, 2, RecyclerView.VERTICAL, false)
   val adapter = ProductCardRecyclerViewAdapter(
           ProductEntry.initProductEntryList(resources))
   view.recycler_view.adapter = adapter
   val largePadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing)
   val smallPadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small)
   view.recycler_view.addItemDecoration(ProductGridItemDecoration(largePadding, smallPadding))

   return view;
}

উপরের কোড স্নিপেটটিতে একটি RecyclerView সেট আপ করার জন্য প্রয়োজনীয় প্রারম্ভিক ধাপগুলো রয়েছে। এর মধ্যে RecyclerView এর লেআউট ম্যানেজার সেট করা এবং এর RecyclerView ইনিশিয়ালাইজ ও সেট করা অন্তর্ভুক্ত।

আপনার ProductGridFragment.kt ফাইলটি এখন নিম্নরূপ দেখতে হবে:

ProductGridFragment .kt

package com.google.codelabs.mdc.kotlin.shrine

import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.codelabs.mdc.kotlin.shrine.network.ProductEntry
import kotlinx.android.synthetic.main.shr_product_grid_fragment.view.*

class ProductGridFragment : Fragment() {

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setHasOptionsMenu(true)
   }

   override fun onCreateView(
           inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
       // Inflate the layout for this fragment with the ProductGrid theme
       val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)

       // Set up the toolbar.
       (activity as AppCompatActivity).setSupportActionBar(view.app_bar)

       // Set up the RecyclerView
       view.recycler_view.setHasFixedSize(true)
       view.recycler_view.layoutManager = GridLayoutManager(context, 2, RecyclerView.VERTICAL, false)
       val adapter = ProductCardRecyclerViewAdapter(
               ProductEntry.initProductEntryList(resources))
       view.recycler_view.adapter = adapter
       val largePadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing)
       val smallPadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small)
       view.recycler_view.addItemDecoration(ProductGridItemDecoration(largePadding, smallPadding))

       return view;
   }

   override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
       menuInflater.inflate(R.menu.shr_toolbar_menu, menu)
       super.onCreateOptionsMenu(menu, menuInflater)
   }
}

নির্মাণ ও পরিচালনা:

f9aeab846fc3bb4c.png

কার্ডগুলো এখন সেখানে আছে! এগুলোতে এখনও কিছু দেখা যাচ্ছে না, তাই চলুন কিছু পণ্যের তথ্য যোগ করা যাক।

ছবি এবং লেখা যোগ করুন

প্রতিটি কার্ডের জন্য একটি ছবি, পণ্যের নাম এবং মূল্য যোগ করুন। আমাদের ViewHolder অ্যাবস্ট্রাকশনটি প্রতিটি কার্ডের ভিউ ধারণ করে। আমাদের ViewHolder এ, নিম্নলিখিতভাবে তিনটি ভিউ যোগ করুন।

ProductCardViewHolder.kt

package com.google.codelabs.mdc.kotlin.shrine

import android.view.View
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView

import com.android.volley.toolbox.NetworkImageView

class ProductCardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

   var productImage: NetworkImageView = itemView.findViewById(R.id.product_image)
   var productTitle: TextView = itemView.findViewById(R.id.product_title)
   var productPrice: TextView = itemView.findViewById(R.id.product_price)
}

নিচে দেখানো অনুযায়ী প্রতিটি প্রোডাক্ট ভিউয়ের জন্য টাইটেল, প্রাইস এবং প্রোডাক্ট ইমেজ সেট করতে ProductCardRecyclerViewAdapter এর onBindViewHolder() মেথডটি আপডেট করুন:

ProductCardRecyclerViewAdapter.kt

override fun onBindViewHolder(holder: ProductCardViewHolder, position: Int) {
   if (position < productList.size) {
       val product = productList[position]
       holder.productTitle.text = product.title
       holder.productPrice.text = product.price
       ImageRequester.setImageFromUrl(holder.productImage, product.url)
   }
}

উপরের কোডটি একটি ViewHolder ব্যবহার করে আমাদের RecyclerView এর অ্যাডাপ্টারকে বলে দেয় যে প্রতিটি কার্ডের সাথে কী করতে হবে।

এখানে, এটি ViewHolder এর প্রতিটি TextView তে টেক্সট ডেটা সেট করে এবং একটি URL থেকে ছবি পাওয়ার জন্য ImageRequester কে কল করে। ImageRequester হলো একটি ক্লাস যা আমরা আপনার সুবিধার জন্য দিয়েছি এবং এটি Volley লাইব্রেরি ব্যবহার করে (এটি এই কোডল্যাবের আওতার বাইরের একটি বিষয়, তবে আপনি নিজে থেকে কোডটি অন্বেষণ করতে পারেন)।

নির্মাণ ও পরিচালনা:

249db074eff043f4.png

আমাদের পণ্যগুলো এখন অ্যাপে দেখা যাচ্ছে!

৬. পুনরালোচনা

আমাদের অ্যাপটির একটি সাধারণ কার্যপ্রণালী রয়েছে, যা ব্যবহারকারীকে লগইন স্ক্রিন থেকে হোম স্ক্রিনে নিয়ে যায়, যেখানে পণ্যগুলো দেখা যায়। মাত্র কয়েকটি কোডের লাইনে, আমরা একটি শিরোনাম ও তিনটি বাটনসহ একটি টপ অ্যাপ বার এবং আমাদের অ্যাপের বিষয়বস্তু উপস্থাপনের জন্য কার্ডের একটি গ্রিড যুক্ত করেছি। আমাদের হোম স্ক্রিনটি এখন একটি সাধারণ কাঠামো এবং ব্যবহারযোগ্য বিষয়বস্তুসহ সহজ ও কার্যকরী।

পরবর্তী পদক্ষেপ

টপ অ্যাপ বার, কার্ড, টেক্সট ফিল্ড এবং বাটনের মাধ্যমে আমরা এখন MDC-Android লাইব্রেরি থেকে চারটি মূল ম্যাটেরিয়াল ডিজাইন কম্পোনেন্ট ব্যবহার করেছি! আপনি MDC-Android ক্যাটালগ পরিদর্শন করে আরও অনেক কম্পোনেন্ট দেখতে পারেন।

যদিও আমাদের অ্যাপটি সম্পূর্ণরূপে কার্যকরী, এটি এখনও কোনো নির্দিষ্ট ব্র্যান্ড বা শৈলী প্রকাশ করে না। MDC-103: Material Design Theming with Color, Shape, Elevation and Type কোর্সে , আমরা একটি প্রাণবন্ত ও আধুনিক ব্র্যান্ড ফুটিয়ে তোলার জন্য এই উপাদানগুলোর শৈলী কাস্টমাইজ করব।

আমি যুক্তিসঙ্গত সময় ও শ্রম দিয়ে এই কোডল্যাবটি সম্পন্ন করতে পেরেছি।

দৃঢ়ভাবে একমত একমত নিরপেক্ষ দ্বিমত তীব্রভাবে দ্বিমত পোষণ করি।

আমি ভবিষ্যতে ম্যাটেরিয়াল কম্পোনেন্টস ব্যবহার করা চালিয়ে যেতে চাই।

দৃঢ়ভাবে একমত একমত নিরপেক্ষ দ্বিমত তীব্রভাবে দ্বিমত পোষণ করি।