ساخت لیست های پیچیده با کمک 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);
رویکرد دیگر برای متحرک سازی آیتم های درون 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 نمایش داده شده است.
در مرحله بعدی باید انیمیشن anticipate_overshoot_interpolator را تست کنیم، اما پیش از آن باید لی اوت منیجر RecyclerView را به StaggeredGrid در متد اکتیویتی اصلی با دو اسپن ستون و اسکرولینگ عمودی ست کنیم.
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL));
استفاده از این متد انیمیشن در RecyclerView ساده است، اما استفاده از متدهای انیمیشنی جدید نیازمند تغییر نوع interpolation در مثال بالا می باشد، پارامترها را مطابق با ترجیحات خود ست کنید و با این کار از یک سبک انیمیشن جدید برخوردار خواهید گشت.
جمع بندی
RecyclerView یک الگوی انعطاف پذیر برای ریسایکلینگ ویو می باشد که با تقلید از ListView و GridView متحرک سازی آیتم ها را ممکن می سازد. جهت تسلط بر نحوه کار با RecyclerView به تمرین نیاز دارید، اما این کار با توجه به کاربردهای گسترده آن ارزش صرف زمان را دارد.
به این نظر پاسخ دهید
به این نظر پاسخ دهید
به این نظر پاسخ دهید
به این نظر پاسخ دهید
به این نظر پاسخ دهید
به این نظر پاسخ دهید
به این نظر پاسخ دهید
به این نظر پاسخ دهید
به این نظر پاسخ دهید
به این نظر پاسخ دهید
به این نظر پاسخ دهید
به این نظر پاسخ دهید
به این نظر پاسخ دهید
به این نظر پاسخ دهید
به این نظر پاسخ دهید
به این نظر پاسخ دهید
به این نظر پاسخ دهید
به این نظر پاسخ دهید