這次要說的內容用到的會很廣泛,我儘可能多的講到一些細節性的東西。
該專題的其它文章:
『Material Design入門學習筆記』前言
『Material Design入門學習筆記』動畫(含demo)
『Material Design 入門學習筆記』主題與 AppCompatActivity(附 demo)
demo下載
RecyclerView
佈局檔案
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/toolbar_test"/>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:id="@+id/recycler"
android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
</LinearLayout>複製程式碼
看到上面佈局檔案可知,RecyclerView是v7裡的東西,所以理所當然的要依賴v7。其次include的佈局是上一節講過的toolbar。
Adapter
RecyclerView與ListView一樣,也需要一個Adapter,只是Adapter有些不同,RecyclerView的Adapter自帶了效能優化機制,包括ViewHolder。
public class CardListAdapter extends RecyclerView.Adapter<CardListAdapter.MyViewHolder>{
private Context context;
private ArrayList<String> list ;
private IcardViewChanger icardViewChanger;
public CardListAdapter(Context context,ArrayList<String> list){
this.context = context;
this.list = list;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
MyViewHolder holder = new MyViewHolder(LayoutInflater.from(
context).inflate(R.layout.item_cardview, parent,
false));
return holder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.tv.setText(list.get(position));
if (icardViewChanger!=null){
icardViewChanger.changeCardView(holder.cardView);
}
}
@Override
public int getItemCount() {
return list.size();
}
class MyViewHolder extends RecyclerView.ViewHolder
{
TextView tv;
CardView cardView;
public MyViewHolder(View view)
{
super(view);
tv = (TextView) view.findViewById(R.id.text);
cardView = (CardView) view.findViewById(R.id.cardView);
}
}
}複製程式碼
構造方法我就不多說了,onCreateViewHolder
相當與BaseAdapter的getView中的View構建。ListView的Adapter需要手動判斷,view是否為空,然後決定是否建立。現在只要在onCreateViewHolder
方法中寫view的構建即可。onBindViewHolder
是用來處理介面邏輯,相當於BaseAdapter的getView中的介面處理邏輯。每次重新整理介面,都會被動呼叫該方法。getItemCount
就是返回Item的數量。
然後就是ViewHolder的構建了。要注意這要繼承RecyclerView.ViewHolder
關於這裡面所用的佈局檔案,下文中講解CardView的時候會提。
然後就是設定RecyclerView了。
recyclerView = (RecyclerView)findViewById(R.id.recycler);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setItemAnimator(new DefaultItemAnimator());複製程式碼
RecyclerView.LayoutManager吧,這是一個抽象類,好在系統提供了3個實現類:
- LinearLayoutManager 現行管理器,支援橫向、縱向。
- GridLayoutManager 網格佈局管理器
StaggeredGridLayoutManager 瀑布就式佈局管理器
setItemAnimator
是刪減動畫。
我們可以通過該方法新增分割線mRecyclerView.addItemDecoration()
關於動畫和分割線,都可以通過繼承的方式設定成你想要的效果。這裡不再細說。CardView
CardView支援多種效果,我們可以讓RecyclerView中的Item都使用CardView。
依賴
如果需要使用CardView,需要依賴:
compile 'com.android.support:cardview-v7:25.3.1'複製程式碼
現在回到
CardListAdapter
,看一下佈局檔案item_cardview
。<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.CardView android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#558b2f" android:layout_margin="10dp" app:cardBackgroundColor="#558b2f" android:id="@+id/cardView"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:src="@mipmap/ic_launcher_round" android:id="@+id/logo"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" android:layout_alignParentRight="true" android:id="@+id/text"/> </RelativeLayout> </android.support.v7.widget.CardView> </LinearLayout>複製程式碼
CardView有一些基本屬性:
app:cardBackgroundColor這是設定背景顏色
app:cardCornerRadius這是設定圓角大小
app:cardElevation這是設定z軸的陰影
app:cardMaxElevation這是設定z軸的最大高度值
app:cardUseCompatPadding是否使用CompatPadding
app:cardPreventCornerOverlap是否使用PreventCornerOverlap
app:contentPadding 設定內容的padding
app:contentPaddingLeft 設定內容的左padding
app:contentPaddingTop 設定內容的上padding
app:contentPaddingRight 設定內容的右padding
app:contentPaddingBottom 設定內容的底padding
至此CardView的相關屬性已經介紹完畢。然後我們會根據屬性值,設定幾種CardView,進行對比。
擴充
首先我們增加一個介面
public interface IcardViewChanger {
public void changeCardView(CardView cardView);
}複製程式碼
用這個介面來設定CardView,首先在CardListAdapter中新增一個方法:
public void setIcardViewChanger(IcardViewChanger icardViewChanger) {
this.icardViewChanger = icardViewChanger;
}複製程式碼
修改onBindViewHolder
:
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.tv.setText(list.get(position));
if (icardViewChanger!=null){
icardViewChanger.changeCardView(holder.cardView);
}
Log.e("xxxxxx" ,"onBindViewHolder");
}複製程式碼
然後我們在使用RecyclerView的Activity中設定呼叫:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_card,menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.btn_changeElevation:
adapter.setIcardViewChanger(new IcardViewChanger() {
@Override
public void changeCardView(CardView cardView) {
cardView.setCardElevation(80);
}
});
adapter.notifyDataSetChanged();
break;
case R.id.btn_changeRadius:
adapter.setIcardViewChanger(new IcardViewChanger() {
@Override
public void changeCardView(CardView cardView) {
cardView.setRadius(80);
}
});
adapter.notifyDataSetChanged();
break;
case R.id.btn_changeColor:
adapter.setIcardViewChanger(new IcardViewChanger() {
@Override
public void changeCardView(CardView cardView) {
cardView.setCardBackgroundColor(getResources().getColor(R.color.cardBackground));
}
});
adapter.notifyDataSetChanged();
break;
}
return super.onOptionsItemSelected(item);
}複製程式碼
最後給大家貼出一張展示圖:
總結
RecyclerView與CardView並不一定要連起來使用,如果有需要可以拆開使用,我這裡是為了方便做demo一起展示。
對於RecyclerView與CardView的更多設定,可以在我demo的基礎上進行修改實驗。
不得不說有了這兩個元件,Android很多介面處理起來簡單多了,不僅因為介面設定多了,同時,對於操作進行了解耦,例如動畫和分割線ViewHolder等。
有問題可以給我留言,或者關注我的公眾號留言。