RecyclerView and CardView 建國科技大學 資管系 饒瑞佶 2017/10 V1
CardView
CardView A CardView is a ViewGroup. Like any other ViewGroup, it can be added to yourActivity or Fragment using a layout XML file. To create an empty CardView, you would have to add the following code to your layout XML as shown in the following snippet CardView是一個物件容器,後續可以配合RecyclerView做資料 顯示 <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content"> </android.support.v7.widget.CardView>
設定向下相容 因為RecyclerView與CardView是Android Lollipop(5.0)才導入 所以需要設定向下相容 build.gradle中的dependencies段落加入下面設定: compile 'com.android.support:cardview-v7:21.0.+' compile 'com.android.support:recyclerview-v7:21.0.+'
建立CardView Layout 可以設定圓角與陰影 create a LinearLayout and place a CardView inside it. The CardView contain the following: a TextView to display the name of the person an ImageView to display the person's photo
設定圓角與底色 <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" android:id="@+id/cv" card_view:cardCornerRadius="4dp" card_view:cardBackgroundColor="#ffff00" android:layout_width="500sp" android:layout_height="wrap_content"> 設定緊密區塊顯示 card_view:cardUseCompatPadding="true"
這個等一下在後面可以結合recyclerview來使用 所以部分物件名稱是配合後面範例 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" android:id="@+id/cv" card_view:cardCornerRadius="4dp" card_view:cardBackgroundColor="#ffff00" card_view:cardElevation="5dp" card_view:cardUseCompatPadding="true" android:layout_height="wrap_content"> <RelativeLayout android:layout_width="fill_parent" android:background="@color/cardview_light_background" android:layout_height="40dp"> <ImageView android:id="@+id/item_icon" android:layout_width="64dp" android:layout_height="64dp" android:layout_alignParentLeft="true" android:layout_marginBottom="1dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginTop="1dp" android:contentDescription="icon" android:src="@mipmap/ic_launcher" /> <TextView android:id="@+id/item_title" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/item_icon" android:layout_marginTop="8dp" android:layout_toRightOf="@+id/item_icon" android:textColor="@android:color/darker_gray" android:textSize="22dp" /> </RelativeLayout> </android.support.v7.widget.CardView> </LinearLayout> 這個等一下在後面可以結合recyclerview來使用 所以部分物件名稱是配合後面範例
RecyclerView
RecyclerView Android Lollipop新導入元件 ListView進階版 To use the RecyclerView widget, you have to specify an adapter and a layout manager. To create an adapter, extend the RecyclerView.Adapter class. The details of the implementation depend on the specifics of your dataset and the type of views. A layout manager positions item views inside a RecyclerView and determines when to reuse item views that are no longer visible to the user.
LayoutManager LayoutManager屬於RecyclerView的內部元件之一,其目的用來 決定RecyclerView當一個view不再顯示給使用者,要怎麼重新使 用這些view資源。 無論是要重覆使用(reuse)或資源回收(recycle)一個view, LayoutManager都會從數據集(Dataset)去讀取岀需要的資料,並 且取代原view來顯示給使用者。然用這種方式去更換view能避免 創建一些不需要的view、也能增進使用findViewById找資源的效 能。
建立RecyclerView define it in a layout as follows: <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:scrollbars="vertical" android:layout_width="match_parent" android:layout_height="match_parent"/> activity_my.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="match_parent" android:background="@color/cardview_dark_background" android:paddingLeft="16dp" android:paddingRight="16dp" android:paddingTop="16dp" android:paddingBottom="16dp"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:scrollbars="vertical" /> </RelativeLayout>
Using a LayoutManager Unlike a ListView, a RecyclerView needs a LayoutManager to manage the positioning of its items. You could define your own LayoutManager by extending the RecyclerView.LayoutManager class. However, in most cases, you could simply use one of the predefined LayoutManager subclasses: LinearLayoutManager GridLayoutManager StaggeredGridLayoutManager
Defining the Data Just like a ListView, a RecyclerView needs an adapter to access its data. But before we create an adapter, let us create data that we can work with. Create a simple class to represent a person and then write a method to initialize a List of Person objects:
定義資料class ItemData 文字與網路圖檔URL public class ItemData { private String title; private String imageUrl; public ItemData(String title, String imageUrl){ this.title = title; this.imageUrl = imageUrl; } public String getTitle() { return title; } public String getImageUrl() { return imageUrl; } public void setTitle(String title) { this.title = title; } public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; } } 文字與網路圖檔URL
Creating an Adapter adapter follows the view holder design pattern, which means that it you to define a custom class that extends RecyclerView.ViewHolder.
Adapter View holdder 資料 建構子 建立ViewHolder 綁定資料 下一頁 綁定recyclerview與Click事件
資料呈現介面Layout 使用到3rd party元件Picasso @Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { // 建立一個要呈現的畫面,來自R.layout.item_layout View itemLayoutView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_layout, null); // 建立ViewHolder ViewHolder viewHolder = new ViewHolder(itemLayoutView); return viewHolder; } 資料呈現介面Layout @Override public void onBindViewHolder(ViewHolder viewHolder, int position) { // 將資料填入view viewHolder.txtViewTitle.setText(itemsData[position].getTitle()); // 圖片 Picasso.with(viewHolder.imgViewIcon.getContext()).cancelRequest(viewHolder.imgViewIcon); Picasso.with(viewHolder.imgViewIcon.getContext()).load(itemsData[position].getImageUrl()).into(viewHolder.imgViewIcon); } // Return the size of your itemsData (invoked by the layout manager) @Override public int getItemCount() { return itemsData.length; } 使用到3rd party元件Picasso compile 'com.squareup.picasso:picasso:2.5.2'
private ItemData[] itemsData; public MyAdapter(ItemData[] itemsData) { this.itemsData = itemsData; } @Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { // 建立一個要呈現的畫面,來自R.layout.item_layout View itemLayoutView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_layout, null); // 建立ViewHolder ViewHolder viewHolder = new ViewHolder(itemLayoutView); return viewHolder; public void onBindViewHolder(ViewHolder viewHolder, int position) { // 將資料填入view viewHolder.txtViewTitle.setText(itemsData[position].getTitle()); // 圖片 Picasso.with(viewHolder.imgViewIcon.getContext()).cancelRequest(viewHolder.imgViewIcon); Picasso.with(viewHolder.imgViewIcon.getContext()).load(itemsData[position].getImageUrl()).into(viewHolder.imgViewIcon); public int getItemCount() { return itemsData.length;
public static class ViewHolder extends RecyclerView public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public TextView txtViewTitle; public ImageView imgViewIcon; public ViewHolder(View itemLayoutView) { super(itemLayoutView); itemLayoutView.setOnClickListener(this); txtViewTitle = (TextView) itemLayoutView.findViewById(R.id.item_title); imgViewIcon = (ImageView) itemLayoutView.findViewById(R.id.item_icon); } @Override public void onClick(View view) { Toast.makeText(view.getContext(), "position = " + getPosition(), Toast.LENGTH_SHORT).show();
item_layout.xml (顯示資料的實際layout設定) <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="40dp" android:background="@drawable/border2_combine" > <!-- icon --> <ImageView android:id="@+id/item_icon" android:layout_width="64dp" android:layout_height="64dp" android:layout_alignParentLeft="true" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginTop="1dp" android:layout_marginBottom="1dp" android:contentDescription="icon" android:src="@drawable/ic_launcher" /> <!-- title --> <TextView android:id="@+id/item_title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_toRightOf="@+id/item_icon" android:layout_alignBaseline="@+id/item_icon" android:textColor="@android:color/darker_gray" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginTop="8dp" android:textSize="22dp" /> </RelativeLayout> 圖 文字
<RelativeLayout xmlns:android="http://schemas. android android:layout_width="fill_parent" android:background="@color/cardview_light_background" android:layout_height="40dp"> <ImageView android:id="@+id/item_icon" android:layout_width="64dp" android:layout_height="64dp" android:layout_alignParentLeft="true" android:layout_marginBottom="1dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginTop="1dp" android:contentDescription="icon" android:src="@mipmap/ic_launcher" /> <TextView android:id="@+id/item_title" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/item_icon" android:layout_marginTop="8dp" android:layout_toRightOf="@+id/item_icon" android:textColor="@android:color/darker_gray" android:textSize="22dp" /> </RelativeLayout>
主程式 圖檔URL陣列 private String[] sources = { "https://cms-assets.tutsplus.com/uploads/users/21/posts/19431/featured_image/CodeFeature.jpg", "http://lorempixel.com/600/250/sports", "http://lorempixel.com/600/200/sports/Dummy-Text", "http://lorempixel.com/600/200/nature", "http://lorempixel.com/600/200/food", };
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); // 取得recyclerView RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);// 建立資料 ItemData itemsData[] = { new ItemData("Delete", sources[0]), new ItemData("Cloud", sources[1]), new ItemData("Favorite", sources[2]), new ItemData("Like", sources[3]), new ItemData("Rating", sources[4]), }; // 設定layoutManger recyclerView.setLayoutManager(new LinearLayoutManager(this));// 設定adapter MyAdapter mAdapter = new MyAdapter(itemsData);// 綁定recyclerview與adapter recyclerView.setAdapter(mAdapter);// 設定預設動畫效果DefaultAnimator recyclerView.setItemAnimator(new DefaultItemAnimator()); }
MyAdapter中onCreateViewHolder使用item_layout的結果
如果MyAdapter中onCreateViewHolder改用前面p7的CardView結果
如果要使用資料庫等資料 ItemData[] itemsData = new ItemData[5]; // 5=陣列大小 for (int i = 0; i <= 4; i++) { ItemData aa = new ItemData("xxxxxx", "http://2.bp.blogspot.com/-zgczCEVDO8w/U-CCbDk-jII/AAAAAAAAJNQ/tTDqk12t5gs/s1600/RecyclerView.png"); itemsData[i]=aa; }