רשת Android ו־כרטיס Android הושקו ב־Android Lollipop עם עיצוב חומרי. עבור אלה שאינם מכירים את עיצוב חומרי, זהו מדריך מקיף של רכיבי ממשק משתמש שהושקו מאז Android 5.0 ושמשפר את המראה הוויזואלי של היישומים.
רשת Android
רשת Android היא גרסה מתקדמת, חזקה וגמישה יותר של רשימת התצוגה. רשת Android דומה ל־ListView אלא שהיא מכריחה אותנו להשתמש במחלקת RecyclerView.ViewHolder כדי להחזיק את הרכיבים שאינו התחייבות ב־ListView. כפי שהשם מרמז, רשת Android משמשת לשימוש מחדש של תאים בגלילה למעלה ולמטה על ידי מחזור מפריטי הרשימה. עוד שיפור ברשת Android הוא שהיא מאפשרת לנו להגדיר את מנהלי העימודים דינמי בזמן ריצה, להבדיל מ־ListView שהיה זמין רק ברשימת גלילה אנכית. רשת Android מאפשרת לנו להגדיר את סוגי העימודים הבאים בזמן ריצה.
- LinearLayoutManager: זה תומך ברשימות אנכיות ואופקיות גם כן
- StaggeredLayoutManager: הוא תומך ברשימות עקופות
- GridLayoutManager: הוא תומך בתצוגת רשתות כפי שנראה ב- GalleryView בעבר
קבוצות RecyclerView של אנדרואיד
- המחלקה RecyclerView.ItemAnimator מספקת תמיכה טובה יותר בהנפשת התצוגות לעומת ListView
- המחלקה RecyclerView.ItemDecorator מספקת תמיכה טובה יותר בהוספת גבולות ומחיצים ולכן נותנת שליטה רבה לנו
לכן RecyclerView הוא יותר התאמתי בהשוואה ל- ListView ונותן שליטה גדולה יותר למשתמשים. RecyclerView זמין בספריית התמיכה, כך שעלינו לשנות את סקריפט ה- gradle שלנו כדי להוסיף את התלות הבאה.
dependencies {
compile 'com.android.support:recyclerview-v7:21.0.0-rc1'
}
קרטיסיית Android
רכיב ה- Android CardView מציג מידע בתוך כרטיסים. רכיב זה נהוג להשתמש בו כדי להציג מידע על קשרים. רכיב זה זמין בספריית התמיכה אחרת, לכן עלינו להוסיף את התלות שלו גם.
dependencies {
compile 'com.android.support:cardview-v7:21.0.0-rc1'
compile 'com.android.support:recyclerview-v7:21.0.0-rc1'
}
הווידג'ט CardView של Android מאפשר לנו לשלוט בצבע הרקע, בצל, רדיוס פינה, גובה ועוד. כדי להשתמש בתכונות מותאמות ב-XML, אנו צריכים להוסיף את ההצהרת האיזור הבא לפריט האב. הנה ההצהרת איזור עם כמה תכונות מפרויקט שלנו.
<android.support.v7.widget.CardView
android:id="@+id/card_view"
xmlns:card_view="https://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardBackgroundColor="@color/grey_300"
card_view:cardCornerRadius="10dp"
card_view:cardElevation="5dp"
card_view:cardUseCompatPadding="true">
התכונות החשובות שנעשה שימוש בהן מעלה הן:
- card_view:cardCornerRadius: משמש להגדרת רדיוס הפינה במערכות שלנו
- card_view:cardBackgroundColor: משמש להגדרת צבע הרקע של התצוגה
בפרויקט הדוגמה שלנו, נוסיף RecyclerView כדי להציג רשימת CardViews המכילה שמות ומספרי גרסאות Android יחד עם לוגו לדוגמה. ה-onclick
של ה-CardView מתוכנת כך שיסיר את הקלף הזה מהרשימה. הוספנו אפשרות תפריט ב-ActionBar כדי להוסיף חזרה את הקלפים ההוסרים בסדר. לתשומת הלב: תמונות הלוגו נלקחות באופן אקראי מ-Google. לכן הגדלים עשויים להשתנות.
דוגמה ל-Android RecyclerView ול-CardView
הפרויקט מורכב ממחלקת
MainActivity
שמציגה את ה-RecyclerView
. ה-CardView מתווספת ל-RecyclerView מתוך מחלקת CustomAdapter. מודל הנתונים משמש לקבלת הנתונים לכל CardView דרך פעולות ה-getters. מחלקת MyData מחזיקה במערכות של טקסטווים ו-drawables יחד עם המזהה שלהם.
דוגמא לקוד של Android RecyclerView ו-CardView
הקובץ activity_main.xml
מכיל את ה-RecyclerView בתוך RelativeLayout כפי שמוצג למטה. קוד של activity_main.xml:
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:background="@color/grey_300"
>
<android.support.v7.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
/>
</RelativeLayout>
קובץ הפריסה של Android CardView מוגדר למטה: קוד של cards_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:tag="cards main container">
<android.support.v7.widget.CardView
android:id="@+id/card_view"
xmlns:card_view="https://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardBackgroundColor="@color/color_white"
card_view:cardCornerRadius="10dp"
card_view:cardElevation="5dp"
card_view:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<ImageView
android:id="@+id/imageView"
android:tag="image_tag"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="1"
android:src="@drawable/ic_launcher"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_weight="2"
android:orientation="vertical"
>
<TextView
android:id="@+id/textViewName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:text="Android Name"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<TextView
android:id="@+id/textViewVersion"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:text="Android Version"
android:textAppearance="?android:attr/textAppearanceMedium"/>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
Android CardView מכילה ImageView יחד עם שני TextViews בתוך LinearLayout מקונן. קובץ התפריט menu_main.xml
מכיל פריט יחיד להוספת הקלפים שהוסרו. קוד של menu_main.xml:
<menu xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
tools:context=".MainActivity">
<item android:id="@+id/add_item"
android:title="Add"
android:orderInCategory="100"
app:showAsAction="always"/>
</menu>
מחלקת MainActivity.java
מוגדרת למטה:
package com.journaldev.recyclerviewcardview;
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private static RecyclerView.Adapter adapter;
private RecyclerView.LayoutManager layoutManager;
private static RecyclerView recyclerView;
private static ArrayList data;
static View.OnClickListener myOnClickListener;
private static ArrayList removedItems;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myOnClickListener = new MyOnClickListener(this);
recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
data = new ArrayList();
for (int i = 0; i < MyData.nameArray.length; i++) {
data.add(new DataModel(
MyData.nameArray[i],
MyData.versionArray[i],
MyData.id_[i],
MyData.drawableArray[i]
));
}
removedItems = new ArrayList();
adapter = new CustomAdapter(data);
recyclerView.setAdapter(adapter);
}
private static class MyOnClickListener implements View.OnClickListener {
private final Context context;
private MyOnClickListener(Context context) {
this.context = context;
}
@Override
public void onClick(View v) {
removeItem(v);
}
private void removeItem(View v) {
int selectedItemPosition = recyclerView.getChildPosition(v);
RecyclerView.ViewHolder viewHolder
= recyclerView.findViewHolderForPosition(selectedItemPosition);
TextView textViewName
= (TextView) viewHolder.itemView.findViewById(R.id.textViewName);
String selectedName = (String) textViewName.getText();
int selectedItemId = -1;
for (int i = 0; i < MyData.nameArray.length; i++) {
if (selectedName.equals(MyData.nameArray[i])) {
selectedItemId = MyData.id_[i];
}
}
removedItems.add(selectedItemId);
data.remove(selectedItemPosition);
adapter.notifyItemRemoved(selectedItemPosition);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
if (item.getItemId() == R.id.add_item) {
//בדוק אם יש פריטים להוסיף
if (removedItems.size() != 0) {
addRemovedItemToList();
} else {
Toast.makeText(this, "Nothing to add", Toast.LENGTH_SHORT).show();
}
}
return true;
}
private void addRemovedItemToList() {
int addItemAtListPosition = 3;
data.add(addItemAtListPosition, new DataModel(
MyData.nameArray[removedItems.get(0)],
MyData.versionArray[removedItems.get(0)],
MyData.id_[removedItems.get(0)],
MyData.drawableArray[removedItems.get(0)]
));
adapter.notifyItemInserted(addItemAtListPosition);
removedItems.remove(0);
}
}
השיטה removeItems()
מתוחזקת מהשיטת האזינה כדי להסיר את ה-CardView שנלחץ. ה- id המתאים שלו מאוחסן במערך כדי לאחזר אותו מאוחר יותר. כדי להוסיף מחדש את התצוגה, יש לנו שיטה נוספת בשם addRemovedItemToList()
. בשיטה זו, אנו מוסיפים את התצוגה הזו במיקום מוגדר מראש ברשימה ומסירים את ה- id שלה מהמערך removedItems
. המתאים המותאם אישית מודיע בשני המקרים. המחלקה CustomeAdapter.java מוגדרת למטה:
package com.journaldev.recyclerviewcardview;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.MyViewHolder> {
private ArrayList<DataModel> dataSet;
public static class MyViewHolder extends RecyclerView.ViewHolder {
TextView textViewName;
TextView textViewVersion;
ImageView imageViewIcon;
public MyViewHolder(View itemView) {
super(itemView);
this.textViewName = (TextView) itemView.findViewById(R.id.textViewName);
this.textViewVersion = (TextView) itemView.findViewById(R.id.textViewVersion);
this.imageViewIcon = (ImageView) itemView.findViewById(R.id.imageView);
}
}
public CustomAdapter(ArrayList<DataModel> data) {
this.dataSet = data;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.cards_layout, parent, false);
view.setOnClickListener(MainActivity.myOnClickListener);
MyViewHolder myViewHolder = new MyViewHolder(view);
return myViewHolder;
}
@Override
public void onBindViewHolder(final MyViewHolder holder, final int listPosition) {
TextView textViewName = holder.textViewName;
TextView textViewVersion = holder.textViewVersion;
ImageView imageView = holder.imageViewIcon;
textViewName.setText(dataSet.get(listPosition).getName());
textViewVersion.setText(dataSet.get(listPosition).getVersion());
imageView.setImageResource(dataSet.get(listPosition).getImage());
}
@Override
public int getItemCount() {
return dataSet.size();
}
}
בקוד לעיל, מימשנו את ViewHolder האישי שלנו על ידי הרחבת RecyclerView.ViewHolder. התצוגה מוכנת לשימוש מ- cards_layout.xml
שהגדרנו בספריית התצורות. מאזין ללחיצה ב- MainActivity מצורף לתצוגה זו בחתימה הבאה.
view.setOnClickListener(MainActivity.myOnClickListener);
ArrayList מאחסן את כל הנתונים בצורת אובייקט DataModel ב ArrayList ומוסיף אותם לכרטיסים המתאימים ברשימה. המחלקות DataModel.java ו- MyData.java שמכילות את הנתונים הספציפיים ליישום זה נתונות להלן:
package com.journaldev.recyclerviewcardview;
public class DataModel {
String name;
String version;
int id_;
int image;
public DataModel(String name, String version, int id_, int image) {
this.name = name;
this.version = version;
this.id_ = id_;
this.image=image;
}
public String getName() {
return name;
}
public String getVersion() {
return version;
}
public int getImage() {
return image;
}
public int getId() {
return id_;
}
}
package com.journaldev.recyclerviewcardview;
public class MyData {
static String[] nameArray = {"Cupcake", "Donut", "Eclair", "Froyo", "Gingerbread", "Honeycomb", "Ice Cream Sandwich","JellyBean", "Kitkat", "Lollipop", "Marshmallow"};
static String[] versionArray = {"1.5", "1.6", "2.0-2.1", "2.2-2.2.3", "2.3-2.3.7", "3.0-3.2.6", "4.0-4.0.4", "4.1-4.3.1", "4.4-4.4.4", "5.0-5.1.1","6.0-6.0.1"};
static Integer[] drawableArray = {R.drawable.cupcake, R.drawable.donut, R.drawable.eclair,
R.drawable.froyo, R.drawable.gingerbread, R.drawable.honeycomb, R.drawable.ics,
R.drawable.jellybean, R.drawable.kitkat, R.drawable.lollipop,R.drawable.marsh};
static Integer[] id_ = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
}
למטה יש פלט הנפרס על ידי יישום הדוגמה שלנו לאפליקציית RecyclerView ו-CardView של אנדרואיד. כפי שניתן לראות, הפריט המסורק מתווסף תמיד באינדקס השלישי (מקום הרביעי ברשימה). זה מסיים את המדריך על RecyclerView ו- CardView של אנדרואיד. ניתן להוריד את פרויקט הדוגמה של אנדרואיד RecyclerView CardView מהקישור למטה.