- دوره طراحی رابط کاربری و طراحی متریال Android قسمت اول: مفاهیم اولیه
- دوره طراحی رابط کاربری و طراحی متریال Android قسمت دوم: RecyclerView
- دوره طراحی متریال Android قسمت سوم: تولبار و منو Navigation Drawer
- دوره طراحی رابط کاربری و طراحی متریال Android قسمت چهارم: ViewPager و TabLayout
- دوره طراحی رابط کاربری و طراحی متریال Android قسمت پنجم: لایه طراحی CoordinatorLayout
در اکثر نرم افزارها لیستی از آیتمها وجود دارد، مانند لیستی از نام کاربران، لیستی از خدمات و یا لیستی از تصاویر.
با استفاده از RecyclerView تنها آیتم هایی که در حال نمایش هستند در حافظه بارگذاری میشوند و به محض اسکرول کردن صفحه محتویات قدیمی با محتویات جدید جایگزین میشوند.
پس اگر با استفاده از RecyclerView یک لیست از هزار تصویر 1 مگابایتی دارید و کاربر در حال مشاهده 3 تصویر است کل فضای استفاده شده توسط RecyclerView برابر 3 مگابایت خواهد بود.
پیاده سازی یک لیست با RecyclerView
برای بهره برداری از RecyclerView به یک کتابخانه جدید نیازمندید. از منو فایل Project Structure را انتخاب و Dependencies را انتخاب کنید.
بر روی علامت + کلیک کرده و Library Dependency را انتخاب و در کادر عبارت RecyclerView را جستجو کنید. از بین کتابخانه ها com.android.support:recyclerview را یافته و اضافه کنید و اجازه بدید Gradle به صورت کامل Sync شود.
برای ایجاد یک لیست با RecyclerView باید یک لایه برای فرم دهی به آیتمها ایجاد کرد، بدین منظور که تمام آیتمهای این لیست باید با استفاده از این لایه مرجع ساخته شوند. مثلا لایه زیر را با نام recycler_view_item ایجاد میکنیم:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/title"
tools:text="Title"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/intro"
tools:text="Intro Intro Intro Intro Intro Intro Intro Intro Intro Intro Intro Intro Intro Intro Intro Intro Intro Intro Intro Intro Intro Intro Intro Intro"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/date"
tools:text="2017/05/06"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#000000"/>
</LinearLayout>
نکته: همانطور که در کدهای بالا دیدید از خاصیت tools استفاده شده است. این خاصیت بدین منظور است که در مراحل طراحی و در اندروید استودیو بتوانیم برخی از مشخصات را مشاهده ولی در حین کامپایل برنامه این خواص حذف میشوند. مثلا از tools:text برای اختصاص دادن متن به کامپوننت جاری استفاده میشود.
سطر 7: در این سطر یک TextView با شناسه Title برای نمایش تیتر مطلب ایجاد کردیم.
سطر 13: در این سطر یک TextView با شناسه Intro برای نمایش خلاصهای از مطلب ایجاد کردیم.
سطر 19: در این سطر یک TextView با شناسه date برای نمایش زمان انتشار مطلب ایجاد کردیم.
سطر 26: در این سطر یک TextView با background مشکی و بدون متن برای ایجاد فاصله بین آیتم های RecyclerView قرار دادیم.
از آن جا که برای پیاده سازی این RecyclerView نیازمند داده نمایشی هستیم مثال موجود در آموزش ساختار دادهها و Data Modelها در اندروید را استفاده میکنیم.
در آموزش ایجاد Data Modelها یک کلاس به نام Posts ایجاد کردیم. در کنار این کلاس یک کلاس DataFakeGenerator نیز داشتیم که وظیفه ایجاد اطلاعات نمایشی را بر عهده داشت.
یک کلاس به شکل زیر ایجاد کنید:
package ir.hitos.hitos;
import android.support.v7.widget.RecyclerView;
public class PostsAdapter extends RecyclerView.Adapter{
}
یک سازنده به شکل زیر برای این کلاس ایجاد میکنیم:
private Context context;
private List<Posts> posts;
public PostsAdapter(Context context, List<Posts> posts){
this.context = context;
this.posts = posts;
}
متد سازنده فوق دو ورودی دارد که اولی Context و دومی Listای بر اساس کلاس Posts میباشد. بدلیل نیاز به ورودیهای این متد سازنده در خارج این متد آنها را در سطح کلاس ایجاد میکنیم.
یک کلاس به نام PostsViewHolder درون کلاس فوق مانند زیر ایجاد میکنیم:
package ir.hitos.hitos;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import java.util.List;
import ir.hitos.models.Posts;
public class PostsAdapter extends RecyclerView.Adapter<PostsAdapter.PostsViewHolder>{
private Context context;
private List<Posts> posts;
public PostsAdapter(Context context, List<Posts> posts){
this.context = context;
this.posts = posts;
}
public class PostsViewHolder extends RecyclerView.ViewHolder{
private TextView title;
private TextView intro;
private TextView date;
public PostsViewHolder(View itemView){
super(itemView);
title= (TextView)itemView.findViewById(R.id.title);
intro= (TextView)itemView.findViewById(R.id.intro);
date= (TextView)itemView.findViewById(R.id.date);
}
}
}
وظیفه کلاس PostsViewHolder ایجاد کردن View هاست، در این کلاس باید تمام کامپوننتهای لایه نمایش recycler_view_item را فراخوانی کنیم.
در سطرهای 20 تا 22 متغیری به نام کامپوننتهای لایه نمایش ایجاد میکنیم.
در سطرهای 26 تا 28 نیز این متغیرها را با کامپوننتهای لایه نمایش متصل میکنیم.
اگر خوب دقت کنید در نام کلاس نیز تغییراتی ایجاد کردیم و عبارت <PostsAdapter.PostsViewHolder>
را به انتهای نام کلاس اضافه کردیم تا ViewHolder را به کلاس متصل کنیم.
روی نام کلاس کلیک کرده و Ctrl + Enter را فشار دهید و implement methods را انتخاب کنید. سه متد جدید اضافه میشود که کارکرد آنها به شرح زیر است:
PostsViewHolder: این متد باعث فراخوانی سازنده بخش نمایش با اجرای ViewHolder مربوطه میشود. در این متد باید View مربوط به این RecyclerView که در این مثال recycler_view_item نام دارد را به اصطلاح inflate کنیم. این متد را به شرح زیر ویرایش میکنیم:
@Override
public PostsViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
View view= LayoutInflater.from(context).inflate(R.layout.recycler_view_item, parent, false);
return new PostsViewHolder(view);
}
همانطور که در سطر سوم میبینید یکی از ورودیهای inflate لایه نمایش recycler_view_item است.
onBindViewHolder: این تابع دادهها را از منابع مربوطه دریافت کرده و درون لایه نمایش جای گذاری میکند. این تابع را به شکل زیر ویرایش میکنیم:
@Override
public void onBindViewHolder(PostsViewHolder holder, int position) {
Posts post= posts.get(position);
holder.title.setText(post.getTitle());
holder.intro.setText(post.getIntro());
holder.date.setText(post.getDate());
}
از آن جا که posts به کلاس Posts متصل است از getTitle و getIntro و getDate برای دریافت اطلاعات بهره میبریم.
getItemCount: تعداد آیتمهای RecyclerView را مشخص میکند. بدین منظور این متد را به شکل زیر ویرایش میکنیم:
@Override
public int getItemCount() {
return posts.size();
}
خروجی قبلی این متد عدد صفر بود ولی خروجی جدید این متد تعداد کل postsها است.
بهره برداری از RecyclerView
لایه نمایشی recycler_view_item برای تشکیل نمونه اصلی هر آیتم ایجاد شد. حال باید در لایه نمایشی اصلی خود یک RecyclerView ایجاد کنیم و با استفاده از کلاس PostsAdapter کلیه اطلاعات را در این لایه نمایش جایگذاری کنیم.
لایه اصلی نمایش خود را به شکل زیر ویرایش میکنیم:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_height="wrap_content"
android:layout_width="match_parent" />
</RelativeLayout>
در سطر هفتم یک شناسه برای دسترسی به این RecyclerView ایجاد کردیم.
به متد onCreate اکتیویتی اصلی نرم افزار خود سورس کدهای زیر را اضافه کنید:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler);
PostsAdapter postsAdapter= new PostsAdapter(this, DataFakeGenerator.getData());
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
recyclerView.setAdapter(postsAdapter);
}
سطر 6: RecyclerView را فراخوانی کردیم.
سطر 7: PostAdapter را صدا زده و با استفاده از DataFakeGenerator مقادیر را فراخوانی میکنیم.
سطر 8: نمایش RecyclerView را آماده میکند که setLayoutManager یک ورودی دارد که این ورودی خود ورودی دیگری به نام LinearLayoutManager دارد. این متد درون خود سه ورودی دارد، اولی متعلق به Context، دومی متعلق به شیوه نمایش و سوم ترتیب نمایش عناصر را مشخص میکند، که اگر false باشد عناصر به ترتیب نمایش داده میشوند.
سطر 9: کار ایجاد و اجرا کردن RecyclerView در این سطر شروع میشود.
نتیجه اجرای این RecyclerView مانند زیر است:
نتیجه اجرای RecyclerView فوق تابع تنظیم setLayoutManager است. بنابر این این متد را میتوان به گونههای دیگری نیز ویرایش کرد، که در پایین چند روش را میآوریم:
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
در روش بالا مانند آن چه در تصویر میبینید آیتمها به صورت افقی در کنار هم قرار میگیرند و باید صفحه را به سمت راست اسکرول کنیم تا ما بقی آیتمها را ببینیم:
recyclerView.setLayoutManager(new GridLayoutManager(this, 2, LinearLayoutManager.VERTICAL, false));
در مثال بالا داخل متد setLayoutManager متد GridLayoutManager را قرار دادیم که چهار ورودی دارد، اولی Context، دومی تعداد ستون ها، سوم جهت نمایش و چهارم ترتیب نمایش. در پایین تصویر این نمایش را میبینید:
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
نمایش فوق الذکر کمی پیچیده است، فرض کنید یک نمایش دو ستونه دارید که در هر آیتم یک عکس وجود دارد و هر عکس ارتفاق متفاوتی دارد، StaggeredGridLayoutManager در این جا به کار میآید.
پیمایش صفحات با RecyclerView
طبیعتا هدف از نمایش لیست RecyclerView دیدن لیستی از آیتمها است که با کلیک روی هر آیتم وارد توضیحات مربوطه شویم.
مثلا فرض کنید لیست RecyclerViewای از مخاطبین دارید که تنها نام افراد را نشان میدهد و با کلیک بر روی نام وارد مشخصات تفصیلی من جمله شمارههای تلفن و دیگر موارد می شوید.
کلاس سازنده اطلاعات که DataFakeGenerator نام داشت آیتمهای عنوان، خلاصه، متن کامل و تاریخ را ایجاد میکرد.
در لایه نمایش recycler_view_item سه مورد از چهار مورد نمایش داده شدند. در این جا قصد داریم متن کامل که fullPost نام داشت را در صفحهای جداگانه و با استفاده از یک Activity دیگر به نمایش در بیاوریم.
متد onBindViewHolder کلاس PostsAdapter را به شرح زیر ویرایش میکنیم:
@Override
public void onBindViewHolder(PostsViewHolder holder, int position) {
final Posts post= posts.get(position);
holder.title.setText(post.getTitle());
holder.intro.setText(post.getIntro());
holder.date.setText(post.getDate());
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent= new Intent(context, fullPostAcitivty.class);
intent.putExtra("fullPost", post.getFullPost());
context.startActivity(intent);
}
});
}
این متد تنها در سطر سوم و سطرهای 8 الی 15 با سورس قبل متفاوت است.
در سطر سوم کلمه کلیدی final را اضافه کردیم، در سطرهای 8 الی 15 نیز با استفاده از دستور itemView قابلیت مشاهده اطلاعات درون هر آیتم RecyclerView را به برنامه خود اضافه کردیم. دستور setOnClickListener برنامه را در انتظار کلیک نگاه میدارد، دستورات درون متد onClick نیز عملیات اجرا کردن اکتیویتی جدید و ارسال متن fullPost به این اکتیویتی را انجام میدهند.
مبحث مربوط به انتقال از یک اکتیویتی به اکتیویتی دیگر را در این قسمت فرا گرفته بودیم.
همانطور که در سطر 11 میبینید جریان برنام از context که مربوط به اکتیویتی اصلی MainAcitivity به یک اکتیویتی جدید به نام fullPostAcitivty منتقل میشود.
یک اکتیویتی جدید با نام fullPostAcitivty ایجاد میکنیم و آن را به AndroidManifest اضافه میکنیم.
سورس اکتیویتی fullPostAcitivty به شرح زیر است:
public class fullPostAcitivty extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fullpost);
Intent intent= getIntent();
String fullPost = intent.getStringExtra("fullPost");
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(fullPost);
}
}
سورسهای بالا با توجه به آموزشهایی که قبلا آموخته بودیم به سادگی متن دریافت شده را در یک TextView با شناسه textView در لایه نمایش activity_fullpost به نمایش در میآورد.
سورس activity_fullpost نیز به سادگی به شرح زیر است:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:text="TextView" />
</RelativeLayout>
شاید مطالب این قسمت کمی پیچیده باشند، ولی با کمی تمرین و مرور، میتوانید به آن مسلط شوید.
تگ ها: Responsive Designandroid / اندرویدandroid studioطراحی متریال