ساخت لیست های پیچیده با کمک RecyclerView اندروید

ساخت لیست های پیچیده با کمک RecyclerView اندروید


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

RecyclerView دارای الگوی منعطف تری نسبت به ListViewها و GridViewها می باشد، اما آنچه موجب تمایز RecyclerView از نسخه های قبلی خود می شود تمرکز آن بر روی ویوهای ریسایکلینگ است. سایر عملیات برای ساخت یک ویو مانند نحوه نمایش مجموعه داده ها به کلاس های pluggable واگذار شده و این شرایط به انعطاف بیشتری برای این ویوها منجر شده است. در این مقاله نحوه راه اندازی این کلاس ها جهت ساخت یک RecyclerView کارآمد شرح داده شده است.

به منظور استفاده از RecyclerView لازم است مراحل زیر را دنبالکنید:

1. افزودن کتابخانه پشتیبان

2. افزودن RecyclerView در فایل XML لی اوت

3. ساخت یک لی اوت سطری کاستوم

4. ساخت Adapter برای تخصیص داده در RecyclerView

5. ساخت ViewHolder جهت در اختیار قرار دادن یک رفرنس به ویوها برای هر آیتم از داده ها

6. بایند کردن Adapter به RecyclerView در Activity

حال که با مراحل انجام کار آشنا شدید کار با RecyclerView را آغاز می کنیم، پروژه نهایی در GitHub قرار داده شده و در صورت نیاز می توانید آن را مورد استفاده قرار دهید.

افزودن وابستگی ها

Build.gradle را باز کرده و وابستگی های مورد نیاز را به آن بیفزایید.

dependencies {

...

compile 'com.android.support:cardview-v7:23.1.0'

compile 'com.android.support:recyclerview-v7:23.1.0'

}

با سینک کردن Gradle همه چیز برای شروع کار آماده می شود.

RecyclerView را به فایل لی اوت بیفزایید

<RelativeLayout

...

<android.support.v7.widget.RecyclerView

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

android:id="@+id/recyclerview"

android:layout_width="match_parent"

android:layout_height="match_parent"/>

</RelativeLayout>

یک لی اوت سطری کاستوم بسازید

لی اوت سطری نمایش دهنده لی اوت هریک از عناصر نمایش داده شده در RecyclerView می باشد.

یک فایل به نام row_layout.xml ساخته و بخش های زیر را به آن بیفزایید:

<android.support.v7.widget.CardView

android:id="@+id/cardView"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginBottom="@dimen/activity_vertical_margin"

app:cardCornerRadius="@dimen/activity_vertical_margin"

app:cardElevation="@dimen/activity_vertical_margin"

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

xmlns:app="http://schemas.android.com/apk/res-auto">

<RelativeLayout

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:padding="16dp">

<ImageView

android:id="@+id/imageView"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_alignParentTop="true"

android:layout_marginRight="16dp" />

<TextView

android:id="@+id/title"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentTop="true"

android:layout_toRightOf="@+id/imageView"

android:text="Title"

android:textSize="30sp" />

<TextView

android:id="@+id/description"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_below="@+id/title"

android:layout_toRightOf="@+id/imageView"

android:text="Description" />

</RelativeLayout>

</android.support.v7.widget.CardView>

RecyclerView در این نمونه فهرستی از فیلم ها و توضیحات انتخاب شده به صورت تصادفی خواهد بود. در این مرحله به یک کلاس که یک آیتم از داده های RecyclerView منفرد را به نمایش گذارد نیاز داریم، برای این منظور فایلی به نام Data.java بسازید و موارد زیر را به آن بیفزایید.

public class Data {

public String title;

public String description;

public int imageId;

Data(String title, String description, int imageId) {

this.title = title;

this.description = description;

this.imageId = imageId;

}

}

آداپتور RecyclerView

RecyclerView.Adapter مشابه سایر Adapter های استفاده شده در یک ListView است، با این تفاوت که دارای یک ViewHolder به منظور ارتقای کارآیی می باشد. یک ListView دارای آداپتورهایی برای منابع گوناگون مانند ArrayAdapter برای آرایه ها و CursorAdapter برای نتایج پایگاه داده می باشد. RecyclerView.Adpter نیازمند یک پیاده سازی کاستوم جهت پشتیبانی از داده های آداپتور می باشد.

آداپتور دارای سه متد به شرح زیر است:

- ()onCreateViewHolder لی اوت سطری را بوجود آورده و ViewHolder را مقداردهی اولیه می کند و هم زمان با مقداردهی ViewHolder به مدیریت متدهای ()findViewById می پردازد و با یافتن ویوها و ریسایکلینگ آنها، از فراخوانی های تکراری جلوگیری به عمل می آورد.

- ()onBindViewHolder از ViewHolder ساخته شده در متد ()onCreateViewHolder استفاده کرده و داده ها را در سطر کنونی از RecyclerView قرار می دهد.

یک فایل به نام Recycler_View_Adapter.java بسازید که دارای کلاس های زیر باشد:

public class Recycler_View_Adapter extends RecyclerView.Adapter<View_Holder> {

List<Data> list = Collections.emptyList();

Context context;

public Recycler_View_Adapter(List<Data> list, Context context) {

this.list = list;

this.context = context;

}

@Override

public View_Holder onCreateViewHolder(ViewGroup parent, int viewType) {

//Inflate the layout, initialize the View Holder

View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_layout, parent, false);

View_Holder holder = new View_Holder(v);

return holder;

}

@Override

public void onBindViewHolder(View_Holder holder, int position) {

//Use the provided View Holder on the onCreateViewHolder method to populate the current row on the RecyclerView

holder.title.setText(list.get(position).title);

holder.description.setText(list.get(position).description);

holder.imageView.setImageResource(list.get(position).imageId);

//animate(holder);

}

@Override

public int getItemCount() {

//returns the number of elements the RecyclerView will display

return list.size();

}

@Override

public void onAttachedToRecyclerView(RecyclerView recyclerView) {

super.onAttachedToRecyclerView(recyclerView);

}

// Insert a new item to the RecyclerView on a predefined position

public void insert(int position, Data data) {

list.add(position, data);

notifyItemInserted(position);

}

// Remove a RecyclerView item containing a specified Data object

public void remove(Data data) {

int position = list.indexOf(data);

list.remove(position);

notifyItemRemoved(position);

}

}

ساخت ViewHolder

RecyclerView از یک ViewHolder برای ذخیره سازی رفرنس ها به ویوهای مرتبط استفاده می کند. این روش از فراخوانی های متد ()findViewById در آداپتور جهت یافتن ویوها جلوگیری می کند.

یک فایل به نام View_Holder.java با کلاس زیر بسازید:

public class View_Holder extends RecyclerView.ViewHolder {

CardView cv;

TextView title;

TextView description;

ImageView imageView;

View_Holder(View itemView) {

super(itemView);

cv = (CardView) itemView.findViewById(R.id.cardView);

title = (TextView) itemView.findViewById(R.id.title);

description = (TextView) itemView.findViewById(R.id.description);

imageView = (ImageView) itemView.findViewById(R.id.imageView);

}

}

LayoutManager

LayoutManager وظیفه الصاق، اندازه گیری و چیدمان تمامی ویوهای فرزند از RecyclerView به صورت ریل تایم را بر عهده دارد. زمانی که کاربر در ویو اسکرول می کند Layout Manager به تعیین زمان افزودن ویوهای فرزند و جدا شدن و پاک شدن ویوهای فرزند قدیمی می پردازد.

پیاده سازی های پیش فرض زیر در دسترس می باشند:

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

- GridLayoutManager – نمایش آیتم های درون یک گرید.

- StaggeredGridLayoutManager – نمایش آیتم های یک گرید staggered.

با اکستند کردن RecyclerView.LayoutManager و یا استفاده از یکی از این پیاده سازی ها و اورراید کردن متدهای موردنیاز قادر به ساخت یک LayoutManager کاستوم می باشید.

حال که کار ساخت RecyclerView به اتمام رسیده گام بعدی افزودن داده به آن می باشد. در متد ()onCreate از کلاس MainActivity یک نمونه از Recycler_View_Adapter بسازید و یک لیست از داده ها و زمینه را به این آداپتور اختصاص دهید. متد ()getApplication محتوای اپلیکیشن را می گیرد.

List<Data> data = fill_with_data();

RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);

Recycler_View_Adapter adapter = new Recycler_View_Adapter(data, getApplication());

recyclerView.setAdapter(adapter);

recyclerView.setLayoutManager(new LinearLayoutManager(this));

یک داده نمونه نیز برای ادامه کار نیاز است، برای این مثال یک تابع پیش فرض ساخته شده و در اپلیکیشن واقعی این بخش از یک منبع داده بوجود می آید.

public List<Data> fill_with_data() {

List<Data> data = new ArrayList<>();

data.add(new Data("Batman vs Superman", "Following the destruction of Metropolis, Batman embarks on a personal vendetta against Superman ", R.drawable.ic_action_movie));

data.add(new Data("X-Men: Apocalypse", "X-Men: Apocalypse is an upcoming American superhero film based on the X-Men characters that appear in Marvel Comics ", R.drawable.ic_action_movie));

data.add(new Data("Captain America: Civil War", "A feud between Captain America and Iron Man leaves the Avengers in turmoil. ", R.drawable.ic_action_movie));

data.add(new Data("Kung Fu Panda 3", "After reuniting with his long-lost father, Po must train a village of pandas", R.drawable.ic_action_movie));

data.add(new Data("Warcraft", "Fleeing their dying home to colonize another, fearsome orc warriors invade the peaceful realm of Azeroth. ", R.drawable.ic_action_movie));

data.add(new Data("Alice in Wonderland", "Alice in Wonderland: Through the Looking Glass ", R.drawable.ic_action_movie));

return data;

}

توسط این لینک قادر به یافتن فایل های آیکون برای دکمه ic_action_movie می باشید.

این کار فرآیند راه اندازی یک RecyclerView را تکمیل می کند.

متحرک کردن ریسایکل ها با ItemAnimator

تمامی مراحل ساخت یک RecyclerView و هر بخش از ساختار آن شرح داده شد، حال بیایید با متحرک سازی آیتم ها بر جذابیت کار بیفزاییم.

RecyclerView.ItemAnimator کلاسی است که به تعریف انیمیشن هایی که بر روی آیتم ها به اجرا در می آیند می پردازد و تغییرات ViewGroup مانند افزودن/حذف/انتخاب را متحرک می کند. DefaultItemAnimator یک انیمیشن مقدماتی است که به صورت پیش فرض توسط RecyclerView در دسترس می باشد.

به منظور شخصی سازی DefaultAnimator یک آیتم انیمیتور را به RecyclerView بیفزایید. کد زیر به سادگی فرآیند افزودن و حذف آیتم ها از RecyclerView را به نمایش گذاشته است.

این بخش را به آخرین بخش از کد در متد ()onCreate بیفزایید:

RecyclerView.ItemAnimator itemAnimator = new DefaultItemAnimator();

itemAnimator.setAddDuration(1000);

itemAnimator.setRemoveDuration(1000);

recyclerView.setItemAnimator(itemAnimator);

blog_16328_1

blog_16328_2

رویکرد دیگر برای متحرک سازی آیتم های درون RecyclerView استفاده از Android Interpolators می باشد. مبنی بر developer.android.com یک interpolator نرخ تغییر یک انیمیشن را تعیین می کند.

در مثال های زیر دو انیمیشن را به نمایش گذاشته شده که با استفاده از interpolator ساخته شده اند. فایل ها را در /anim/ در پوشه سورس پروژه ذخیره کنید.

anticipateovershoot_interpolator.xml

<?xml version="1.0" encoding="utf-8"?>

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

android:interpolator="@android:anim/anticipate_overshoot_interpolator">

<translate

android:fromYDelta="-50%p"

android:toYDelta="0"

android:duration="2000"

/>

</set>

bounce_interpolator.xml

<?xml version="1.0" encoding="utf-8"?>

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

android:interpolator="@android:anim/bounce_interpolator">

<translate

android:duration="1500"

android:fromYDelta="-150%p"

android:toYDelta="0"

/>

</set>\

حال به RecyclerView باز می گردیم، درون کلاس آداپتور RecyclerView تابع زیر را اضافه کنید:

در این مرحله لازم است RecyclerView را باز گردانیم، در داخل آداپتور RecyclerView تابع زیر را بیفزاییذ:

public void animate(RecyclerView.ViewHolder viewHolder) {

final Animation animAnticipateOvershoot = AnimationUtils.loadAnimation(context, R.anim.bounce_interpolator);

viewHolder.itemView.setAnimation(animAnticipateOvershoot);

}

چنانچه نگاه دقیق تری به متد ()LoadAnimation بیندازید، این متد نیازمند یک پارامتر زمینه است که دلیل تغییر سازنده آداپتور در مرحله اول را توجیه می کند و در این مرحله قادر به متحرک کردن RecyclerView می باشیم. درون متد ()onBindViewHolder تابع ()animate را فراخوانی کرده و پارامتر هولدر از کلاس View_Holder را ارسال کنید.

اپلیکیشن را به اجرا در آورده و انیمیشن را تست کنید، در زیر نحوه کار bounce_interpolator نمایش داده شده است.

blog_16328_3

در مرحله بعدی باید انیمیشن anticipate_overshoot_interpolator را تست کنیم، اما پیش از آن باید لی اوت منیجر RecyclerView را به StaggeredGrid در متد اکتیویتی اصلی با دو اسپن ستون و اسکرولینگ عمودی ست کنیم.

recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL));

blog_16328_4

استفاده از این متد انیمیشن در RecyclerView ساده است، اما استفاده از متدهای انیمیشنی جدید نیازمند تغییر نوع interpolation در مثال بالا می باشد، پارامترها را مطابق با ترجیحات خود ست کنید و با این کار از یک سبک انیمیشن جدید برخوردار خواهید گشت.

جمع بندی

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

 

http://www.sitepoint.com برگرفته از

اینها را هم بخوانید

نظرات کاربران

  1. مریم شفیع زاده
    مریم شفیع زاده
    سلام.من می خواهم در ریسایکلر عمودی من آیتم اول یک ستونه باشه و کل عرض ریسایکلر رو بگیره و بقیه آیتم ها دو ستونه باشن.چطور باید این کار رو انجام بدم لطفا راهنماییم کنید.؟

    به این نظر پاسخ دهید
    1. واننی منصوریان
      واننی منصوریان (ادمین)
      با سلام میتونین داخل recycler view دو تا linear layout افقی تعریف کنین و داخل دومی مجددا دو تا دیگه و بهشون layout_weight بدین تا دو ستونی بشه موفق باشین

      به این نظر پاسخ دهید
  2. avatar
    AssassiN
    سلام، هرچی میکنم fill_with_data رو خطا میده. ممنون میشم اگه راهنمایی کنید.

    به این نظر پاسخ دهید
    1. سیامک سرشوق
      سیامک سرشوق
      سلام به زودی پاسخ مشکل شما و بقیه دوستان عزیز رو میدیم.

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

    به این نظر پاسخ دهید
  4. avatar
    hamed
    ممنون از سایت خوبتون فقط یک مشکلی که داره اینه که من الان مثلا بخش اول را میخوانم از یک مقاله ولی بخش دوم در جلوی چشم نیست تا سریع به بخش دوم برود حداقل من که اصلا پیدا نکردم

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

      به این نظر پاسخ دهید
  5. avatar
    valayar
    می خواستم بدونم تو این آموزشی که گذاشتین اگه بخوام که روی هر یک از آیتم های لیست ویو کلیک کردم بره به یک اکتیوتی دیگه ولی هر راهی رو امتحان کردم نشد که نشد

    به این نظر پاسخ دهید
    1. واننی منصوریان
      واننی منصوریان (ادمین)
      با سلام نحوه انجام این کار در لینک های زیر شرح داده شده است: https://stackoverflow.com/questions/24471109/recyclerview-onclick https://stackoverflow.com/questions/39546767/how-to-handle-both-recyclerview-on-item-click-listener-for-its-rows-and-the-view موفق باشید

      به این نظر پاسخ دهید
  6. avatar
    valayar
    سلام خسته نباشید میتونم قسم بخورم که بیش از پنجاه سایت رو گشتم تا این ریسایکلر ویو رو حلاجی کنم و باهاش کنار بیام ولی نتونستم ... امروز آخرش به این سایت رسیدم که دیدم خیلی روان روان روان توضیح داین و آخرش تونستم که یه ریسایکلر ویو بدون دغدغه بسازم خدارو شکر و از شما دوست عزیز نمی دونم چجوری تشکر کنم ممنون

    به این نظر پاسخ دهید
  7. avatar
    محمد
    با سلام .برا افقی یا عمودی اسکرول شدنشون چکار باید کرد .ممنون

    به این نظر پاسخ دهید
    1. واننی منصوریان
      واننی منصوریان (ادمین)
      با سلام دوست گرامی در این لینک نحوه انجام این کار نشان داده شده است: https://stackoverflow.com/questions/31338400/horizontal-and-vertical-scrolling-in-android-recycler-view موفق باشید

      به این نظر پاسخ دهید
  8. avatar
    میلاد
    توضیحات کامل و واضح بودند و خیلی قشنگ تفاوت RecyclerView و ListView رو بیان کردین برای من که چندماهی بود دنبال کاربرد و تفاوت RecyclerView در اندروید استودیو بودم این مطالب و توضیحات شما بسیار لذت بخش و قابل درک بود. ممنونم ازتون امیدوارم روزبه روز توی کارتون با انرژی تر شاداب تر و موفق تر باشید.

    به این نظر پاسخ دهید
  9. avatar
    عرفان
    سپاس بسیار کاربردی بود

    به این نظر پاسخ دهید
  10. avatar
    مینا
    مرسی از مطالب خوبتون

    به این نظر پاسخ دهید
  11. avatar
    م ج ن
    عالی بود

    به این نظر پاسخ دهید
  12. avatar
    چیا
    جالب بود کاش اضافه کردن هدر رو هم به توضیحاتتون اضافه می کرید

    به این نظر پاسخ دهید