سبد (0)

کار با ‏grid‏ و ‏list‏ با ‏RecyclerView ‏

کار با ‏grid‏ و ‏list‏ با ‏RecyclerView ‏

استفاده از ابزار (widget) Recycler-view در اندروید

این آموزش نحوه ی استفاده از Recycler-view همراه با activity ها و fragment ها را در اندروید تشریح می کند. مبحث پیش رو بر پایه ی Eclipse 4.4، Java 1.7 و Android 5.0 نوشته شده است.

فهرست محتوا

1. List ها و grid ها در اندروید

استفاده از grid ها و list ها در اندروید

استفاده از کلاس Recyclerview جهت مدیریت لیست ها

Input-type های احتمالی برای اداپتور Recyclerview

چرا باید از کلاس Recyclerview استفاده کنیم؟

چه کلاس هایی برای پیاده سازی Recycler-view مورد نیاز می باشد؟   

2. بکارگیری Recycler-view جهت نمایش مجموعه ای از داده ها

چگونگی استفاده از کلاس Recycler-view

Adapter

چرا باید از کلاس Viewholder استفاده کرد؟

فیلتر کردن و مرتب سازی داده ها

بروز رسانی داده ها در adapter

3. تمرین : بکارگیری RecyclerView

هدف از این تمرین چیست؟

ایجاد پروژه

وارد کردن RecyclerView support JAR به پروژه

ایجاد فایل های layout

1. List ها و grid ها در اندروید

استفاده از grid ها و list ها در اندروید

نمایش المان ها در قالب list یا grid در اندروید الگویی معمول و پرکاربرد می باشد. اگرچه توضیحاتی که در این بخش عرضه شده واژه ی " list " را بکار می برد، اما درباره ی الگوی grid نیز صحت دارد.

در نمای فهرست وار (list) کاربر لیستی از آیتم ها را پیش روی خود می بیند که به وی اجازه می دهد با استفاده از قابلیت اسکرول صفحه را بالا و پایین ببرد و کلیه ی درایه های لیست را مشاهده کند.

کاربر با استفاده از نوارابزار (toolbar) با لیست مربوطه تعامل برقرار می کند. تک تک آیتم های لیست برای کاربر قابل گزینش می باشد. آیتم انتخابی ممکن است نوارابزار را بروز رسانی کرده یا صفحه ی جامعی برای انتخاب نمایش دهد.

استفاده از کلاس Recycler-view جهت مدیریت لیست ها

کلاس Recyclerview، که به عنوان جزئی از مجموعه کتابخانه های پشتیبان (support library suite) v7 عرضه شده، در حقیقت نسخه ی بهبود یافته ی همان کلاس های ListView و gridview می باشد.

Input-type های احتمالی برای اداپتور Recyclerview

ورودی اداپتور RecyclerView می تواند هر شئ قراردادی یا دلخواه جاوا (java object) باشد. اداپتور RecyclerView داده های مورد نظر را از data object مربوطه استخراج کرده، سپس داده های مذکور را  به آیتم های مرتبط در list یا grid تخصیص می دهد.

چرا باید از کلاس Recyclerview استفاده کنیم؟

 Recyclerview تعداد زیادی از مشکلاتی که ListView با آن مواجه می شوید را اصلاح کرده و همچنین با animation های پیش فرضی عرضه می گردد که ویژه ی افزودن و حذف عناصر طراحی شده است. به علاوه با امکاناتی جدیدی که دارد قادر است خود به صورت مستقیم view ها را بازیابی (recycle) کند.

Recyclerview جهت قرار دهی آیتم ها در مکان مناسب layout manager و به منظور انجام عملیات معمول و متعارفی همچون افزودن و حذف کردن درایه ها، انیمیشن های پیش فرض را ارائه می دهد.

چه کلاس هایی برای پیاده سازی Recyclerview مورد نیاز می باشد ؟   

جهت پیاده سازی Recyclerview به تعداد محدودی کلاس نیاز داریم. همان طور که مشاهده می کنید مهمترین کلاس ها در جدول ذیل فهرست شده. ستون سوم مشخص می کند آیا خود شما باید کلاس مربوطه را پیاده سازی کنید یا این آیا این امکان برای شما وجود دارد.

جدول 1. مهمترین کلاس های رابط برنامه سازی (API) RecyclerView

کلاس

به چه منظوری به کار می رود

اختیاری یا الزامی

Adapter

داده های مورد نیاز را فراهم می کند و مسئولیت ایجاد view ها برای ورودی های فردی را بر عهده دارد.

الزامی

ViewHolder

دربردارنده ی ارجاعتی است ویژه ی تمامی view هایی که با داده های entry ها (درایه( پر شده.

الزامی

LayoutManager

مسئول چیدمان و آرایش view container ها برای entry در فضای موجود می باشد.

گرچه الزامی است ولی پیاده سازی های پیش فرض نیز موجود می باشد.

ItemDecoration

مسئولیت تنظیم دکور و تزیینات اطراف و همچنین قسمت فوقانی view container یک درایه (entry) را بر عهده دارد. 

رفتار یا عملکرد پیش فرض، ولی قابل بازنویسی (override) می باشد

ItemAnimator

مسئول تعریف انیمیشن لازم در صورت حذف و اضافه شدن یا مرتب سازی مجدد درایه ها می باشد. 

رفتار یا عملکرد پیش فرض، ولی قابل بازنویسی (override) می باشد

البته این قابلیت وجود دارد که پیاده سازی اختصاصی و سفارشی خود را ویژه ی layout manager ها و انیمیشن ها ارائه دهید.

2. بکارگیری Recycler-view جهت نمایش مجموعه ای از داده ها

چگونگی استفاده از کلاس Recycleriew

میدانید که  که ابزار (widget) RecyclerView بخشی از کتابخانه ی پشتیبانی v7 می باشد. جهت بکارگیری آن لازم است یک اداپتور بر پایه ی کلاس RecyclerView.Adapter و layout manager مشخص کنید. ابزار بیان شده (RecyclerView) دارای اداپتورهای زیر هست.

LinearLayoutManager که آیتم ها را در لیستی افقی یا عمودی حاوی اسکرول نمایش می دهد.

GridLayoutManager که المان ها را طبق الگوی grid به نمایش می گذارد.

StaggeredGridLayoutManager عناصر مورد نظر را طبق الگوی staggered grid نمایش می دهد.(که قابلیت پشتیبانی از چندین ستون با اندازه های متفاوت را دارد)   

به منظور تنظیم یا اختصاصی سازی انیمیشن ها در RecyclerView، کافی است انیمیشن خود را با به ارث بردن ((extend کلاس RecyclerView.ItemAnimator و استفاده از متد RecyclerView.setItemAnimator() به ابزار مربوطه اختصاص دهید.

Adapter

یک adapter مدل داده (data model) را مدیریت کرده و آن را متناسب با ورودی (entry) های فردی در ابزار تطبیق (adapt) می دهد.  

Adapterبه مثابه ی یک پل بین Adapter view (به طور مثال listview) و داده های زیربنا آن view عمل می کند (به عبارتی دیگر، یک پیوند یا پل ارتباطی بین مجموعه داده و adapterview می باشد. adapterview نیز وظیفه ی نمایش داده های نام برده را بر عهده دارد ). اداپتور کلاس RecyclerView.Adapter را extend (به ارث می برد) می کند.

اداپتور باید شمار یا تعداد آیتم ها را به وسیله ی متد getItemCount () برگرداند. هر درایه یا المان موجود در ابزار RecyclerView در حقیقت داده ی ویژه ی هر مدل داده (data model) را نشان می دهد. اداپتور هر فایل layout مربوط و همخوان را ظاهر کرده، سپس داده را به layout (ظاهر شده) تخصیص می دهد. (منظور از ظاهر شدن در اینجا inflate می باشد = به این معنا که XML layout را گرفته، view های مشخص شده در آن را ایجاد می کنیم سپس view های مذکور را به ViewGroup پدر اضافه می کنیم).

یک خط متعارف در لیست، به طور معمول متشکل از تصویری است که در سمت چپ آن قرار می گیرد و دو خط حاوی متن که در وسط آن جای می گیرد.

به محتویات فایل layout زیر توجه کنید.

 

     ‎<relativelayout ‎xmlns:android="http://schemas.android.com/apk/res/android" ‎

                     ‎ android:layout_width="fill_parent" ‎

                     ‎ android:layout_height="?android:attr/listPreferredItemHeight" ‎

                     ‎ android:padding="6dip">

    ‎    ‎    <imageview‎ ‎ android:id="@+id/icon" ‎

                     ‎ android:layout_width="wrap_content" ‎

                     ‎ android:layout_height="fill_parent" ‎

                     ‎ android:layout_alignparentbottom="true" ‎

                     ‎ android:layout_alignparenttop="true" ‎

                     ‎ android:layout_marginright="6dip" ‎

‎ android:contentdescription="TODO" ‎

                     ‎ android:src="@drawable/ic_launcher" />‎

    ‎    <textview‎ ‎ android:id="@+id/secondLine" ‎

                    ‎ android:layout_width="fill_parent" ‎

                    ‎ android:layout_height="26dip" ‎

                    ‎ android:layout_alignparentbottom="true" ‎

                    ‎ android:layout_alignparentright="true" ‎

                    ‎ android:layout_torightof="@id/icon" ‎

                    ‎ android:ellipsize="marquee" ‎

                    ‎ android:singleline="true" ‎

                    ‎ android:text="Description" ‎

                    ‎ android:textsize="12sp" />‎

    ‎    <textview‎ ‎ android:id="@+id/firstLine" ‎

                    ‎ android:layout_width="fill_parent" ‎

                    ‎ android:layout_height="wrap_content" ‎

                    ‎ android:layout_above="@id/secondLine" ‎

                    ‎ android:layout_alignparentright="true" ‎

                    ‎ android:layout_alignparenttop="true" ‎

                    ‎ android:layout_alignwithparentifmissing="true" ‎

                    ‎ android:layout_torightof="@id/icon" ‎

                    ‎ android:gravity="center_vertical" ‎

                    ‎ android:text="Example application" ‎

                    ‎ android:textsize="16sp" />‎

</relativelayout> ‎

متد onCreateViewHolder، شمای کلی (layout) را ظاهر (inflate) کرده و نمونه ای از کلاس ViewHolder ایجاد می کند. به وسیله ی نمونه ی ذکر شده می توان به view های ظاهر شده (inflated) در فایل layout دسترسی پیدا کرد. تنها کافی است متد onCreateViewHolder فراخوانده شود، به دنبال آن یک view جدید باید ایجاد گردد.

onBindViewHolder متدی است که در آن داده ی مورد نظر را به viewهای مربوطه تخصیص می دهید.

اداپتور هم به وسیله ی متد setAdapter به RecyclerView اختصاص می یابد.

 چرا باید از کلاس Viewholder استفاده کرد؟

با پیاده سازی ViewHolderمی توان از بکارگیری متد findViewById () در اداپتور اجتناب کرد.

کلاس ViewHolder به طور معمول کلاس داخلی ایستا (static inner class) در اداپتور است که حامل ارجاعاتی به view های مربوطه می باشد.

اگرچه این امر کمی پیچیده بنظر می رسد، اما در حقیقت %15 سریع تر از پیاده سازی متد findViewById () عمل می کند.

فیلتر کردن و مرتب سازی داده ها

فرایند فیلتر (filtering) و مرتب سازی (sorting) داده ها توسط اداپتور مدیریت می شود. کافی است منطق لازمه را در پیاده سازی سفارشی یا اختصاصی اداپتور مزبور بکار ببرید.

بروز رسانی داده ها در adapter

متد notifyItemInserted(position) باید در صورت درج ورودی جدید (در موقعیت یا مکان تعریف شده) در اداپتور، فراخوانی شود.

متد notifyItemRemoved(position) نیز لازم است مجرد حذف شدن داده های مورد نظر از این موقعیت، صدا زده شود.

3. تمرین : بکارگیری RecyclerView

هدف از این تمرین چیست؟

در تمرین پیشه رو پروژه ای ایجاد می کنیم که در آن کلاس RecyclerView، برای کتابخانه ی پشتیبانی (support lib) بکار می رود.

ایجاد پروژه

پروژه جدیدی به نام com.vogella.android.recyclerview ایجاد کنید.

وارد کردن RecyclerView support JAR به پروژه 

RecyclerView یک فایل ساده ی JAR می باشد. بنابراین لازم است کتابخانه ی پشتیبانی مورد نیاز را به کمک SDK manager از اندروید دانلود کنید. سپس به مسیر sdk/extras/android/support/v7/recyclerview مراجعه کرده و فایل JAR را داخل پوشه ی lib واقع در پروژه جای گذاری کنید.

ایجاد فایل های layout

باید فایل layout ای که دربردارنده ی RecyclerView می باشد ایجاد کنید. فایل زیر activity_main.xmlخوانده می شود.

 

<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" ‎

                 ‎ xmlns:tools="http://schemas.android.com/tools" ‎

                 ‎ android:layout_width="match_parent" ‎

                 ‎ android:layout_height="match_parent" ‎

                 ‎ tools:context="${relativePackage}.${activityClass}">

    ‎    <!-- A RecyclerView with some commonly used attributes -->‎

    ‎    <android.support.v7.widget.recyclerview ‎ android:id="@+id/my_recycler_view" ‎

                                                 ‎ android:layout_width="match_parent" ‎

                                                 ‎ android:layout_height="match_parent" ‎

                                                 ‎ android:scrollbars="vertical" />‎

    ‎    <imageview‎ ‎ android:id="@+id/imageView1" ‎

                     ‎ android:layout_width="wrap_content" ‎

                     ‎ android:layout_height="wrap_content" ‎

                     ‎ android:layout_alignparentbottom="true" ‎

                     ‎ android:layout_alignparentright="true" ‎

                     ‎ android:layout_marginbottom="12dp" ‎

                     ‎ android:layout_marginright="12dp" ‎

                     ‎ android:elevation="2dp" ‎

                     ‎ android:src="@drawable/ic_add_circle" />‎

</relativelayout> ‎

 همچنین لازم است یک layout ایجاد کرده تا در هر یک از آیتم ها بکار ببرید.

 

<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" ‎

                 ‎ android:layout_width="fill_parent" ‎

                 ‎ android:layout_height="?android:attr/listPreferredItemHeight" ‎

                 ‎ android:padding="6dip">

    ‎    <imageview‎ ‎ android:id="@+id/icon" ‎

                     ‎ android:layout_width="wrap_content" ‎

                     ‎ android:layout_height="fill_parent" ‎

                     ‎ android:layout_alignparentbottom="true" ‎

                     ‎ android:layout_alignparenttop="true" ‎

                     ‎ android:layout_marginright="6dip" ‎

                     ‎ android:contentdescription="TODO" ‎

                     ‎ android:src="@drawable/ic_launcher" />‎

    ‎    <textview‎ ‎ android:id="@+id/secondLine" ‎

                    ‎ android:layout_width="fill_parent" ‎

                    ‎ android:layout_height="26dip" ‎

                    ‎ android:layout_alignparentbottom="true" ‎

                    ‎ android:layout_alignparentright="true" ‎

                    ‎ android:layout_torightof="@id/icon" ‎

                    ‎ android:ellipsize="marquee" ‎

                    ‎ android:singleline="true" ‎

                    ‎ android:text="Description" ‎

                    ‎ android:textsize="12sp" />‎

    ‎    <textview‎ ‎ android:id="@+id/firstLine" ‎

                    ‎ android:layout_width="fill_parent" ‎

                    ‎ android:layout_height="wrap_content" ‎

                    ‎ android:layout_above="@id/secondLine" ‎

                    ‎ android:layout_alignparentright="true" ‎

                    ‎ android:layout_alignparenttop="true" ‎

                    ‎ android:layout_alignwithparentifmissing="true" ‎

                    ‎ android:layout_torightof="@id/icon" ‎

                    ‎ android:gravity="center_vertical" ‎

                    ‎ android:text="Example application" ‎

                    ‎ android:textsize="16sp" />‎

 </relativelayout> ‎

توجه

در حال حاضر نمایش RecyclerView در پیش نمایش گرافیکی پشتیبانی نمی شود (قابلیت نمایش RecyclerView در پیش نمایش گرافیکی وجود ندارد).

توجه داشته باشید باید اداپتوری جهت ارائه ی داده ها ایجاد کنید.

 

package com.vogella.android.recyclerview;‎
import java.util.ArrayList;‎
import android.support.v7.widget.RecyclerView;‎
import android.view.LayoutInflater;‎
import android.view.View;‎
import android.view.View.OnClickListener;‎
import android.view.ViewGroup;‎
import android.widget.TextView;‎
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {‎
‎  private ArrayList<String> mDataset;‎
‎  // Provide a reference to the views for each data item‎
‎  // Complex data items may need more than one view per item، and‎
‎  // you provide access to all the views for a data item in a view holder‎
‎  public class ViewHolder extends RecyclerView.ViewHolder {‎
‎    // each data item is just a string in this case‎
‎    public TextView txtHeader;‎
‎    public TextView txtFooter;‎
‎    public ViewHolder(View v) {‎
‎      super(v);‎
‎      txtHeader = (TextView) v.findViewById(R.id.firstLine);‎
‎      txtFooter = (TextView) v.findViewById(R.id.secondLine);‎
‎    }‎
‎  }‎
‎  public void add(int position، String item) {‎
‎    mDataset.add(position، item);‎
‎    notifyItemInserted(position);‎
‎  }‎
‎  public void remove(String item) {‎
‎    int position = mDataset.indexOf(item);‎
‎    mDataset.remove(position);‎
‎    notifyItemRemoved(position);‎
‎  }‎
‎  // Provide a suitable constructor (depends on the kind of dataset)‎
‎  public MyAdapter(ArrayList<String> myDataset) {‎
‎    mDataset = myDataset;‎
‎  }‎
‎  // Create new views (invoked by the layout manager)‎
‎  @Override
‎  public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent،‎
‎      int viewType) {‎
‎    // create a new view‎
‎    View v = ‎LayoutInflater.from(parent.getContext()).inflate(R.layout.rowlayout، parent، ‎false);‎
‎    // set the view's size، margins، paddings and layout parameters‎
‎    ViewHolder vh = new ViewHolder(v);‎
‎    return vh;‎
‎  }‎
‎  // Replace the contents of a view (invoked by the layout manager)‎
‎  @Override
‎  public void onBindViewHolder(ViewHolder holder، int position) {‎
‎    // - get element from your dataset at this position
‎    // - replace the contents of the view with that element
‎    final String name = mDataset.get(position);‎
‎    holder.txtHeader.setText(mDataset.get(position));‎
‎    holder.txtHeader.setOnClickListener(new OnClickListener() {‎
‎            @Override
‎            public void onClick(View v) {‎
‎              remove(name);‎
‎            }‎
‎        });‎
‎    holder.txtFooter.setText("Footer: " + mDataset.get(position));‎
‎  }‎
‎  // Return the size of your dataset (invoked by the layout manager)‎
‎  @Override
‎  public int getItemCount() {‎
‎    return mDataset.size();‎
‎  }‎
‎} ‎
public class MyActivity extends Activity {‎
‎    private RecyclerView mRecyclerView;‎
‎    private RecyclerView.Adapter mAdapter;‎
‎    private RecyclerView.LayoutManager mLayoutManager;‎
‎    @Override
‎    protected void onCreate(Bundle savedInstanceState) {‎
‎        super.onCreate(savedInstanceState);‎
‎        setContentView(R.layout.my_activity);‎
‎        mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);‎

‎        // use this setting to improve performance if you know that changes‎
‎        // in content do not change the layout size of the RecyclerView
‎        mRecyclerView.setHasFixedSize(true);‎
‎        // use a linear layout manager‎
‎        mLayoutManager = new LinearLayoutManager(this);‎
‎        mRecyclerView.setLayoutManager(mLayoutManager);‎
‎        // specify an adapter (see also next example)‎
‎        mAdapter = new MyAdapter(myDataset);‎
‎        mRecyclerView.setAdapter(mAdapter);‎
‎    }‎
‎}
تمامی محصولات و خدمات این وبسایت، حسب مورد دارای مجوزهای لازم از مراجع مربوطه می‌باشند و فعالیت‌های این سایت تابع قوانین و مقررات جمهوری اسلامی ایران است.
logo-samandehiمجوز نشر دیجیتال از وزرات فرهنگ و ارشاد اسلامیپرداخت آنلاین -  بانک ملتمعرفی بیاموز در شبکه سهپرداخت آنلاین - بانک اقتصاد نوینپرداخت آنلاین - بانک سامان