کار کردن با RecyclerView در اندروید
Android RecyclerView نمونه پیشرفته تری از ListView با عملکرد بهبود یافته و افزون بر آن دارای مزیت بیشتری است. با استفاده از RecyclerView و CardView با هم، می توان لیست و شبکه های پیشرفته تری ایجاد نمود که کاربر در استفاده از آنها احساس راحتری بیشتری داشته باشد. در این نوشته قصد داریم در مورد این عنوان اطلاعات بیشتری را در اختیار دوستان قرار دهیم . در این آموزش شما خواهید آموخت که چگونه یک RecyclerView ساده را با یک طرح سفارشی ایجاد کنید. همچنين یاد خواهيد گرفت که چگونه می توان يک کلاس آداپتور را به آن اضافه کرد، همچنین نحوه استفاده و اضافه کردن لیست تقسيم کننده divider و oncliklistener را به سادگی یاد خواهید گرفت . در مثالی که ارائه خواهیم داد شما خواهید توانست لیستی از انواع الگوهای پیشفرض را به منظور راهنمایی کاربران ارائه کنید بطوری که کاربر با کلیک کردن بر روی هریک از آیتم ها قادر خواهد بود به محتوای مورد نظر آن آیتم راهنمایی شود.
قبل از ارائه مثال لازم است که برای ایجاد RecyclerView در لایوت xml از دستور زیر استفاده می کنیم:
<android.support.v7.widget.RecyclerView android:id="@+id/myrecycler_view" android:scrollbars="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
اگر در داخل برنامه اکلیپس یا اندروید استودیو قرار دارید پروژه جدیدی را ایجاد کنید
اکلیپس :File ⇒ New Android ⇒ Application Project
اندروید استودیو :File ⇒ New ⇒ New Project
اما اگر هنوز برنامه خود را باز نکرده اید یکی از برنامه های فوق را باز نموده و بعد از تعیین مشخصات(نامگذاری) ، تعیین حداقل sdk و نوع اکتیویتی (blank یا Empty) ، نام اکتیویتی ابتدایی و اصلی خود را همان MainActivity قرار دهید.
در اولین گام فایلbuild.gradle را باز کرده و وابستگی زیر را
compile ‘com.android.support:recyclerview-v7:+’
را به شکل زیر به آن اضافه کنید و سپس پروژه را sync کنید :
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
buildToolsVersion "26.0.0"
defaultConfig {
applicationId "ir.psrd.recyclerview.myapplication"
minSdkVersion 15
targetSdkVersion 27
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:25.0.0'
compile 'com.android.support:design:25.0.0'
compile 'com.android.support:recyclerview-v7:+'
}
بعد از کامپایل کردن کتابخانه، در مسیر res ⇒layout لایه متناظر اکتیوتی اصلی یعنی activity_main را پیدا نمود و کدهای مندرج و پیش فرض آن را پاک کرده و کدهای xml زیر را به آن اضافه کنید:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:showIn="@layout/activity_main" tools:context=".MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/myrecycler_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbars="vertical" /> </RelativeLayout>
سپس کلاس جدیدی را به منظور تعریف متغیرها و دسترسی به getter / setter با نام book تعریف می کنیم.
package ir.psrd.recyclerview.myapplication; /** * Created by hamed on 8/24/2018. */ public class Book { private String title, categeroie, year; public Book() { } public Book(String title, String genre, String year) { this.title = title; this.categeroie = categeroie; this.year = year; } public String getTitle() { return title; } public void setTitle(String name) { this.title = name; } public String getYear() { return year; } public void setYear(String year) { this.year = year; } public String getcategeroie() { return categeroie; } public void setcategeroie(String genre) { this.categeroie = genre; } } public void setGenre(String genre) { this.genre = genre; } }
در مرحله بعد فایل XML جدیدی را در فایل مربوط به لایوت با نام book_list_row.xml ایجاد کنید. این صفحه اطلاعات مربوط به کتاب ها را بصورت ردیف بندی شده برای کاربران نمایش خواهد داد که شامل اطلاعات مربوط به عنوان ، سال نشر و دسته بندی مربوط به آن کتاب خواهد بود.
<?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="wrap_content" android:background="?android:attr/selectableItemBackground" android:clickable="true" android:focusable="true" android:orientation="vertical" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" > <TextView android:id="@+id/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:textSize="16dp" android:textStyle="bold" /> <TextView android:id="@+id/categeroie" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/title" /> <TextView android:id="@+id/year" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" /> </RelativeLayout>
حالا یک کلاس به نام BookAdapter.java ایجاد کنید و کد زیر را به ان اضافه کنید. در این کلاس متد () methodCreateViewHolder فایل مربوط به booklist_row.xml را inflates می کند و متد ()onBindViewHolder اطلاعات مربوط به کتاب (عنوان، دسته بندی و سال نشر) برای هر ردیف تعیین می کند.
package ir.psrd.recyclerview.myapplication; /** * Created by hamed on 8/24/2018. */ import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import java.util.List; public class BooksAdapter extends RecyclerView.Adapter<BooksAdapter.MyViewHolder> { private List<Book> booksList; public class MyViewHolder extends RecyclerView.ViewHolder { public TextView title, year, categore; public MyViewHolder(View view) { super(view); title = (TextView) view.findViewById(R.id.title); categore = (TextView) view.findViewById(R.id.categeroie); year = (TextView) view.findViewById(R.id.year); } } public BooksAdapter(List<Book> booksList) { this.booksList = booksList; } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()) .inflate(R.layout.book_list_row, parent, false); return new MyViewHolder(itemView); } @Override public void onBindViewHolder(MyViewHolder holder, int position) { Book book = booksList.get(position); holder.title.setText(book.getTitle()); holder.categore.setText(book.getcategeroie()); holder.year.setText(book.getYear()); } @Override public int getItemCount() { return booksList.size(); } }
در گام بعدی لازم است خط تقسیم بین سطرها را با استفاده از DividerItemDecoration به پروژه خود اضافه کنید . از این رو کلاس جدیدی با نام MyDividerItemDecoration ایجاد کرده و آن را به نوع RecyclerView.ItemDecoration که دکوراسیون لازم را برای RecyclerView فراهم می کند گسترش دهید.
package ir.psrd.recyclerview.myapplication; /** * Created by hossin on 8/24/2018. */ import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.TypedValue; import android.view.View; public class MyDividerItemDecoration extends RecyclerView.ItemDecoration { private static final int[] ATTRS = new int[]{ android.R.attr.listDivider }; public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; private Drawable mDivider; private int mOrientation; private Context context; private int margin; public MyDividerItemDecoration(Context context, int orientation, int margin) { this.context = context; this.margin = margin; final TypedArray a = context.obtainStyledAttributes(ATTRS); mDivider = a.getDrawable(0); a.recycle(); setOrientation(orientation); } public void setOrientation(int orientation) { if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) { throw new IllegalArgumentException("invalid orientation"); } mOrientation = orientation; } @Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { if (mOrientation == VERTICAL_LIST) { drawVertical(c, parent); } else { drawHorizontal(c, parent); } } public void drawVertical(Canvas c, RecyclerView parent) { final int left = parent.getPaddingLeft(); final int right = parent.getWidth() - parent.getPaddingRight(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child .getLayoutParams(); final int top = child.getBottom() + params.bottomMargin; final int bottom = top + mDivider.getIntrinsicHeight(); mDivider.setBounds(left + dpToPx(margin), top, right - dpToPx(margin), bottom); mDivider.draw(c); } } public void drawHorizontal(Canvas c, RecyclerView parent) { final int top = parent.getPaddingTop(); final int bottom = parent.getHeight() - parent.getPaddingBottom(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child .getLayoutParams(); final int left = child.getRight() + params.rightMargin; final int right = left + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top + dpToPx(margin), right, bottom - dpToPx(margin)); mDivider.draw(c); } } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { if (mOrientation == VERTICAL_LIST) { outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); } else { outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); } } private int dpToPx(int dp) { Resources r = context.getResources(); return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics())); } }
نمایش پیمایش افقی RecyclerView
اگر می خواهید RecyclerView را به صورت Horizontal نمایش دهید، می توانید این کار را فقط با تغییر یک خط کد انجام دهید. تنها کاری که باید انجام دهید این است که کد مربوط به LinearLayoutManager.HORIZONTAL را در داخل پارامتر کلاس LinearLayoutManagerکه در زیر نشان داده شده است قرار دهید. همچنین فراموش نکنید که عرض طرح ردیف خود را تا WRAP_CONTENT حفظ کنید.
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.HORIZONTAL, false);
کلاس جدیدی به نام RecyclerTouchListener.java ایجاد کنید و آن را به نوع RecyclerView.OnItemTouchListener گسترش دهید. در واقع با استفاده از این کلاس می توانید از رابط ClickListener در پروژه خود استفاده کنید.
package ir.psrd.recyclerview.myapplication; /** * Created by hamed on 8/24/2018. */ import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; public class RecyclerTouchListener implements RecyclerView.OnItemTouchListener { private GestureDetector gestureDetector; private ClickListener clickListener; public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ClickListener clickListener) { this.clickListener = clickListener; gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onSingleTapUp(MotionEvent e) { return true; } @Override public void onLongPress(MotionEvent e) { View child = recyclerView.findChildViewUnder(e.getX(), e.getY()); if (child != null && clickListener != null) { clickListener.onLongClick(child, recyclerView.getChildPosition(child)); } } }); } @Override public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { View child = rv.findChildViewUnder(e.getX(), e.getY()); if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) { clickListener.onClick(child, rv.getChildPosition(child)); } return false; } @Override public void onTouchEvent(RecyclerView rv, MotionEvent e) { } @Override public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { } public interface ClickListener { void onClick(View view, int position); void onLongClick(View view, int position); } }
در نهایت کلاس MainActivity.Class کدهای زیر را قرار دهید.
package ir.psrd.recyclerview.myapplication; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.DividerItemDecoration; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.Toast; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private List<Book> booksList = new ArrayList<>(); private RecyclerView recyclerView; private BooksAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); recyclerView = (RecyclerView) findViewById(R.id.myrecycler_view); mAdapter = new BooksAdapter(booksList); recyclerView.setHasFixedSize(true); // vertical RecyclerView // keep movie_list_row.xml width to `match_parent` RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext()); // horizontal RecyclerView // keep movie_list_row.xml width to `wrap_content` // RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.HORIZONTAL, false); recyclerView.setLayoutManager(mLayoutManager); // adding inbuilt divider line recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL)); // adding custom divider line with padding 16dp // recyclerView.addItemDecoration(new MyDividerItemDecoration(this, LinearLayoutManager.VERTICAL, 16)); recyclerView.setItemAnimator(new DefaultItemAnimator()); recyclerView.setAdapter(mAdapter); // row click listener recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getApplicationContext(), recyclerView, new RecyclerTouchListener.ClickListener() { @Override public void onClick(View view, int position) { Book book = booksList.get(position); Toast.makeText(getApplicationContext(), book.getTitle() + " is selected!", Toast.LENGTH_SHORT).show(); } @Override public void onLongClick(View view, int position) { } })); prepareMovieData(); } /** * Prepares sample data to provide data set to adapter */ private void prepareMovieData() { Book book = new Book("کتاب اول", " & آموزشی ", "1394"); booksList.add(book); book = new Book("کناب دوم", "اجتماعی", "1395"); booksList.add(book); book = new Book("کتاب سوم", "رمان", "1396"); booksList.add(book); book = new Book("کتاب جهارم", "روانشناسی", "1397"); booksList.add(book); book = new Book("کتاب پنحم", "مهندسی مکانیک", "1397"); booksList.add(book); // notify adapter about data set changes // so that it will render the list with new data mAdapter.notifyDataSetChanged(); } }
حال پروژه را اجرا کرده و از آن در آموزش هر چه بیشتر خود استفاده کنید. اگر مشکلی در اجرای کدها وجود دارد یا سوال مشخصی از نویسنده سایت دارید سوالات خود را در قسمت دیدگاه ها بیان کنید.
کپی برداری از محتوای سایت psrd، ممنوع بوده و پیگرد قانونی دارد. (تنها استفاده شخصی کاربران ، مجاز است) (کپی برداری توسط سایر وب سایت ها غیرقانونی بوده و در صورت رویت به ستادسازماندهی اطلاع داده خواهد شد.
0 دیدگاه