অ্যান্ড্রয়েড জেটপ্যাকের অংশ RecyclerView ব্যবহার করে ডায়নামিক লিস্ট তৈরি করুন।

কম্পোজ পদ্ধতিটি চেষ্টা করুন
অ্যান্ড্রয়েডের জন্য Jetpack Compose হলো প্রস্তাবিত UI টুলকিট। Compose-এ কীভাবে লেআউট নিয়ে কাজ করতে হয় তা শিখুন।

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

নাম থেকেই বোঝা যায়, RecyclerView স্বতন্ত্র উপাদানগুলোকে পুনর্ব্যবহার করে । যখন কোনো আইটেম স্ক্রল করে স্ক্রিনের বাইরে চলে যায়, RecyclerView তার ভিউটি নষ্ট করে না। পরিবর্তে, স্ক্রিনে স্ক্রল করে আসা নতুন আইটেমগুলোর জন্য RecyclerView সেই ভিউটি পুনরায় ব্যবহার করে। RecyclerView আপনার অ্যাপের পারফরম্যান্স ও রেসপন্সিভনেস উন্নত করে এবং বিদ্যুৎ খরচ কমায়।

মূল শ্রেণীগুলি

আপনার ডাইনামিক তালিকাটি তৈরি করতে বেশ কয়েকটি ক্লাস একসাথে কাজ করে।

  • RecyclerView হলো সেই ViewGroup যা আপনার ডেটার সাথে সম্পর্কিত ভিউগুলোকে ধারণ করে। এটি নিজেই একটি ভিউ, তাই আপনি অন্য যেকোনো UI এলিমেন্টের মতোই আপনার লেআউটে RecyclerView যোগ করতে পারেন।

  • তালিকার প্রতিটি উপাদান একটি ভিউ হোল্ডার অবজেক্ট দ্বারা সংজ্ঞায়িত করা হয়। যখন ভিউ হোল্ডারটি তৈরি করা হয়, তখন এর সাথে কোনো ডেটা সংযুক্ত থাকে না। ভিউ হোল্ডারটি তৈরি হওয়ার পরে, RecyclerView এটিকে তার ডেটার সাথে বাইন্ড করে । আপনি RecyclerView.ViewHolder এক্সটেন্ড করে ভিউ হোল্ডারটি সংজ্ঞায়িত করেন।

  • RecyclerView অ্যাডাপ্টারের মেথড কল করার মাধ্যমে ভিউগুলোর জন্য অনুরোধ করে এবং সেগুলোকে তাদের ডেটার সাথে বাইন্ড করে। আপনি RecyclerView.Adapter এক্সটেন্ড করে অ্যাডাপ্টারটি সংজ্ঞায়িত করেন।

  • লেআউট ম্যানেজার আপনার তালিকার প্রতিটি উপাদানকে সাজিয়ে রাখে। আপনি RecyclerView লাইব্রেরি দ্বারা প্রদত্ত লেআউট ম্যানেজারগুলোর মধ্যে একটি ব্যবহার করতে পারেন, অথবা নিজের মতো করে একটি তৈরি করতে পারেন। সমস্ত লেআউট ম্যানেজারই লাইব্রেরির LayoutManager অ্যাবস্ট্রাক্ট ক্লাসের উপর ভিত্তি করে তৈরি।

RecyclerView স্যাম্পল অ্যাপ (Kotlin) অথবা RecyclerView স্যাম্পল অ্যাপ (Java)- তে আপনি দেখতে পারেন কিভাবে সমস্ত অংশগুলো একসাথে কাজ করে।

আপনার RecyclerView বাস্তবায়নের ধাপসমূহ

আপনি যদি RecyclerView ব্যবহার করতে চান, তাহলে আপনাকে কয়েকটি বিষয় করণীয়। পরবর্তী বিভাগগুলোতে সেগুলো বিস্তারিতভাবে ব্যাখ্যা করা হয়েছে।

  1. তালিকা বা গ্রিডটি দেখতে কেমন হবে তা স্থির করুন। সাধারণত, আপনি RecyclerView লাইব্রেরির স্ট্যান্ডার্ড লেআউট ম্যানেজারগুলোর মধ্যে একটি ব্যবহার করতে পারেন।

  2. তালিকার প্রতিটি উপাদানের চেহারা ও আচরণ কেমন হবে তা ডিজাইন করুন। এই ডিজাইনের উপর ভিত্তি করে ViewHolder ক্লাসটি এক্সটেন্ড করুন। আপনার তৈরি ViewHolder আপনার তালিকার আইটেমগুলোর জন্য সমস্ত কার্যকারিতা প্রদান করবে। আপনার ভিউ হোল্ডারটি একটি View এর র‍্যাপার, এবং সেই ভিউটি RecyclerView দ্বারা পরিচালিত হয়।

  3. সেই Adapter নির্ধারণ করুন যা আপনার ডেটাকে ViewHolder ভিউগুলোর সাথে সংযুক্ত করে।

এছাড়াও উন্নত কাস্টমাইজেশন বিকল্প রয়েছে, যা আপনাকে আপনার RecyclerView-কে আপনার সুনির্দিষ্ট প্রয়োজন অনুযায়ী সাজিয়ে নিতে সাহায্য করে।

আপনার বিন্যাস পরিকল্পনা করুন

আপনার RecyclerView-এর আইটেমগুলো একটি LayoutManager ক্লাস দ্বারা সাজানো হয়। RecyclerView লাইব্রেরিটি তিনটি লেআউট ম্যানেজার প্রদান করে, যেগুলো সবচেয়ে সাধারণ লেআউট পরিস্থিতিগুলো সামাল দেয়:

  • LinearLayoutManager আইটেমগুলোকে একটি একমাত্রিক তালিকায় বিন্যস্ত করে।
  • GridLayoutManager আইটেমগুলোকে একটি দ্বি-মাত্রিক গ্রিডে বিন্যস্ত করে:
    • যদি গ্রিডটি উল্লম্বভাবে সাজানো থাকে, তাহলে GridLayoutManager প্রতিটি সারির সমস্ত উপাদানের প্রস্থ এবং উচ্চতা একই রাখার চেষ্টা করে, কিন্তু বিভিন্ন সারির উচ্চতা ভিন্ন হতে পারে।
    • যদি গ্রিডটি আনুভূমিকভাবে সাজানো থাকে, তাহলে GridLayoutManager প্রতিটি কলামের সমস্ত উপাদানের প্রস্থ এবং উচ্চতা একই রাখার চেষ্টা করে, কিন্তু বিভিন্ন কলামের প্রস্থ ভিন্ন হতে পারে।
  • StaggeredGridLayoutManager , GridLayoutManager এর মতোই, কিন্তু এর ক্ষেত্রে একটি সারির আইটেমগুলোর উচ্চতা (উল্লম্ব গ্রিডের জন্য) বা একই কলামের আইটেমগুলোর প্রস্থ (অনুভূমিক গ্রিডের জন্য) একই হতে হয় না। এর ফলে, একটি সারি বা কলামের আইটেমগুলো একে অপরের থেকে কিছুটা সরে থাকতে পারে।

আপনাকে প্রতিটি আইটেমের লেআউটও ডিজাইন করতে হবে। পরবর্তী বিভাগে বর্ণিত ভিউ হোল্ডার ডিজাইন করার সময় আপনার এই লেআউটটির প্রয়োজন হবে।

আপনার অ্যাডাপ্টার এবং ভিউ হোল্ডার প্রয়োগ করুন

একবার আপনার লেআউট নির্ধারণ করা হয়ে গেলে, আপনাকে আপনার Adapter এবং ViewHolder ইমপ্লিমেন্ট করতে হবে। আপনার ডেটা কীভাবে প্রদর্শিত হবে তা নির্ধারণ করতে এই দুটি ক্লাস একসাথে কাজ করে। ViewHolder হলো একটি View -এর র‍্যাপার, যা তালিকার প্রতিটি আইটেমের লেআউট ধারণ করে। Adapter প্রয়োজন অনুযায়ী ViewHolder অবজেক্ট তৈরি করে এবং সেই ভিউগুলোর জন্য ডেটাও সেট করে। ভিউকে তার ডেটার সাথে যুক্ত করার এই প্রক্রিয়াকে বাইন্ডিং (binding) বলা হয়।

যখন আপনি আপনার অ্যাডাপ্টার সংজ্ঞায়িত করেন, তখন আপনি তিনটি মূল পদ্ধতি ওভাররাইড করেন:

  • onCreateViewHolder() : যখনই RecyclerView এর একটি নতুন ViewHolder তৈরি করার প্রয়োজন হয়, তখন এটি এই মেথডটিকে কল করে। এই মেথডটি ViewHolder এবং এর সাথে যুক্ত View তৈরি ও ইনিশিয়ালাইজ করে, কিন্তু ভিউ-এর বিষয়বস্তু পূরণ করে না —কারণ ViewHolder তখনও কোনো নির্দিষ্ট ডেটার সাথে আবদ্ধ হয়নি।

  • onBindViewHolder() : RecyclerView একটি ViewHolder ডেটার সাথে যুক্ত করতে এই মেথডটি কল করে। মেথডটি উপযুক্ত ডেটা সংগ্রহ করে এবং সেই ডেটা ব্যবহার করে ভিউ হোল্ডারের লেআউট পূরণ করে। উদাহরণস্বরূপ, যদি RecyclerView নামের একটি তালিকা প্রদর্শন করে, তাহলে মেথডটি তালিকা থেকে উপযুক্ত নামটি খুঁজে নিয়ে ভিউ হোল্ডারের TextView উইজেটটি পূরণ করতে পারে।

  • getItemCount() : ডেটাসেটের আকার জানার জন্য RecyclerView এই মেথডটি কল করে। উদাহরণস্বরূপ, একটি অ্যাড্রেস বুক অ্যাপে, এটি হতে পারে মোট ঠিকানার সংখ্যা। প্রদর্শনের জন্য আর কোনো আইটেম বাকি নেই, এটি নির্ধারণ করতে RecyclerView এটি ব্যবহার করে।

এখানে একটি নেস্টেড ViewHolder সহ একটি সাধারণ অ্যাডাপ্টারের একটি সাধারণ উদাহরণ দেওয়া হল যা ডেটার একটি তালিকা প্রদর্শন করে। এক্ষেত্রে, RecyclerView টেক্সট এলিমেন্টের একটি সাধারণ তালিকা প্রদর্শন করে। অ্যাডাপ্টারটিকে ViewHolder এলিমেন্টগুলির টেক্সট ধারণকারী স্ট্রিংগুলির একটি অ্যারে পাস করা হয়।

কোটলিন

class CustomAdapter(private val dataSet: Array<String>) :
        RecyclerView.Adapter<CustomAdapter.ViewHolder>() {

    /**
     * Provide a reference to the type of views that you are using
     * (custom ViewHolder)
     */
    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val textView: TextView

        init {
            // Define click listener for the ViewHolder's View
            textView = view.findViewById(R.id.textView)
        }
    }

    // Create new views (invoked by the layout manager)
    override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
        // Create a new view, which defines the UI of the list item
        val view = LayoutInflater.from(viewGroup.context)
                .inflate(R.layout.text_row_item, viewGroup, false)

        return ViewHolder(view)
    }

    // Replace the contents of a view (invoked by the layout manager)
    override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {

        // Get element from your dataset at this position and replace the
        // contents of the view with that element
        viewHolder.textView.text = dataSet[position]
    }

    // Return the size of your dataset (invoked by the layout manager)
    override fun getItemCount() = dataSet.size

}

জাভা

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {

    private String[] localDataSet;

    /**
     * Provide a reference to the type of views that you are using
     * (custom ViewHolder)
     */
    public static class ViewHolder extends RecyclerView.ViewHolder {
        private final TextView textView;

        public ViewHolder(View view) {
            super(view);
            // Define click listener for the ViewHolder's View

            textView = (TextView) view.findViewById(R.id.textView);
        }

        public TextView getTextView() {
            return textView;
        }
    }

    /**
     * Initialize the dataset of the Adapter
     *
     * @param dataSet String[] containing the data to populate views to be used
     * by RecyclerView
     */
    public CustomAdapter(String[] dataSet) {
        localDataSet = dataSet;
    }

    // Create new views (invoked by the layout manager)
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        // Create a new view, which defines the UI of the list item
        View view = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.text_row_item, viewGroup, false);

        return new ViewHolder(view);
    }

    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(ViewHolder viewHolder, final int position) {

        // Get element from your dataset at this position and replace the
        // contents of the view with that element
        viewHolder.getTextView().setText(localDataSet[position]);
    }

    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return localDataSet.length;
    }
}

যথারীতি, প্রতিটি ভিউ আইটেমের লেআউট একটি XML লেআউট ফাইলে সংজ্ঞায়িত করা হয়। এক্ষেত্রে, অ্যাপটিতে এইরকম একটি text_row_item.xml ফাইল রয়েছে:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/list_item_height"
    android:layout_marginLeft="@dimen/margin_medium"
    android:layout_marginRight="@dimen/margin_medium"
    android:gravity="center_vertical">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/element_text"/>
</FrameLayout>

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

নিম্নলিখিত কোড স্নিপেটটি দেখায় যে আপনি কীভাবে RecyclerView ব্যবহার করতে পারেন।

কোটলিন

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val dataset = arrayOf("January", "February", "March")
        val customAdapter = CustomAdapter(dataset)

        val recyclerView: RecyclerView = findViewById(R.id.recycler_view)
        recyclerView.layoutManager = LinearLayoutManager(this)
        recyclerView.adapter = customAdapter

    }

}

জাভা

RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.layoutManager = new LinearLayoutManager(this)
recyclerView.setAdapter(customAdapter);

লাইব্রেরিটি আপনার ইমপ্লিমেন্টেশন কাস্টমাইজ করার জন্য অনেক উপায়ও প্রদান করে। আরও তথ্যের জন্য, অ্যাডভান্সড রিসাইক্লারভিউ কাস্টমাইজেশন দেখুন।

এজ-টু-এজ ডিসপ্লে সক্ষম করুন

একটি RecyclerView জন্য প্রান্ত থেকে প্রান্ত পর্যন্ত প্রদর্শন (edge-to-edge display) সক্ষম করতে এই ধাপগুলি অনুসরণ করুন:

  • enableEdgeToEdge() কল করে একটি পশ্চাৎ সামঞ্জস্যপূর্ণ প্রান্ত-থেকে-প্রান্ত ডিসপ্লে সেট আপ করুন।
  • যদি তালিকার আইটেমগুলো শুরুতে সিস্টেম বারের উপর চলে আসে, তাহলে RecyclerView তে ইনসেট প্রয়োগ করুন। এটি করার জন্য আপনি android:fitsSystemWindows true সেট করতে পারেন অথবা ViewCompat.setOnApplyWindowInsetsListener ব্যবহার করতে পারেন।
  • RecyclerView তে android:clipToPadding কে false সেট করে স্ক্রোল করার সময় তালিকার আইটেমগুলিকে সিস্টেম বারের নিচে প্রদর্শিত হতে দিন।

নিচের ভিডিওটিতে একটি RecyclerView দেখানো হয়েছে যার এজ-টু-এজ ডিসপ্লে নিষ্ক্রিয় (বামে) এবং সক্রিয় (ডানে) অবস্থায় রয়েছে:

উদাহরণ ইনসেট কোড:

কোটলিন

ViewCompat.setOnApplyWindowInsetsListener(
  findViewById(R.id.my_recycler_view)
  ) { v, insets ->
      val innerPadding = insets.getInsets(
          WindowInsetsCompat.Type.systemBars()
                  or WindowInsetsCompat.Type.displayCutout()
          // If using EditText, also add
          // "or WindowInsetsCompat.Type.ime()" to
          // maintain focus when opening the IME
      )
      v.setPadding(
          innerPadding.left,
          innerPadding.top,
          innerPadding.right,
          innerPadding.bottom)
      insets
  }
  

জাভা

ViewCompat.setOnApplyWindowInsetsListener(
  activity.findViewById(R.id.my_recycler_view),
  (v, insets) -> {
      Insets innerPadding = insets.getInsets(
              WindowInsetsCompat.Type.systemBars() |
                      WindowInsetsCompat.Type.displayCutout()
              // If using EditText, also add
              // "| WindowInsetsCompat.Type.ime()" to
              // maintain focus when opening the IME
      );
      v.setPadding(
              innerPadding.left,
              innerPadding.top,
              innerPadding.right,
              innerPadding.bottom
      );
      return insets;
  }
);
  

RecyclerView XML:

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

অতিরিক্ত সম্পদ

অ্যান্ড্রয়েডে টেস্টিং সম্পর্কে আরও তথ্যের জন্য, নিম্নলিখিত রিসোর্সগুলো দেখুন।

নমুনা অ্যাপ