編輯:Android資訊
RecyclerView是傳統ListView的一個很好的替代,具有很好的拓展性,初次接觸RecyclerView可能會被其復雜的邏輯搞暈,本文就以一個簡單的實例帶小伙伴們理清其中的關系。
本文所使用的IDE為AndroidStudio。
依次點擊File—>Project Structure—>左下角Module的app—>Dependencis—>點擊左下方的+號,選擇recycler view即可。
首先創建一個名為NotesListFragment的fragment,對應的布局文件名為fragment_notes_list。接著將該fragment加入到主Activity中(關於如何在Activity中操作fragment將另作文章說明,此處省略啦),接下來在NotesListFragment中定義一個私有字段
private RecyclerView noteRecycler;
我們將要實現的是一個顯示筆記的RecyclerView,這裡將筆記類定義如下:
package com.aristark.note; import java.util.Date; import java.util.UUID; public class Note { private UUID uuid; private String title; private String content; private Date date; private String tag; public Note{ uuid = UUID.randomUUID(); date = new Date(); } public UUID getUuid() { return uuid; } public Date getDate() { return date; } public void setTitle(String title) { this.title = title; } public String getTitle() { return title; } public void setContent(String content) { this.content = content; } public String getContent() { return content; } public void setTag(String tag) { this.tag = tag; } public String getTag() { return tag; } }
為了操作方便,我們再創建一個NoteLab類:
package com.aristark.note; import android.content.Context; import java.util.ArrayList; public class NoteLab { private static NoteLab sNoteLab; //for the global use private ArrayList<Note> notes; private NoteLab(Context context){ notes = new ArrayList<Note>(); //generate 100 Note Objects for (int i=0;i<100;i++){ Note note = new Note(); note.setTitle("this is title "+i); note.setContent("this is content"+i+"balabalabalabalalabalabalabalabalala/nbalabalabalabalalabalabalabala balala/nbalabalabalabalalabalabalabalabalala/nbalabalabalabalalabalabalab alabalala/nbalabalabalabalalabalabalabalabalala/n"); notes.add(note); } } public static NoteLab getNoteLab(Context context){ if (sNoteLab == null){ sNoteLab = new NoteLab(context); } return sNoteLab; } public ArrayList<Note> getNotes() { return notes; } }
注意體會該類所使用的單例模式,sNoteLab以靜態方式存在,既節省了內存,又可以讓應用的各個部件方便的訪問。在構造方法NoteLab中,我們生成100個Note對象以作後面的測試。
這兩個類是實現列表的關鍵,其實從字面含義很容易猜測這兩個類的作用,ViewHolder操作的是列表每個部分的布局,而Adapter則是用數據去填充View,雖然解釋的不是很准確,但姑且這麼理解是沒問題的。那麼下面我們就在NotesListFragment裡創建這兩個類:
1 首先創建NoteHolder
private class NoteHolder extends RecyclerView.ViewHolder{ public NoteHolder(View root) { super(root); } }
這個類很簡單,值得注意的是自動創建的構造方法所傳入的參數名叫itemView,這裡我將其改為root,因為接下來我們通過這個構造方法傳進來的是一個完整的布局文件,而不僅僅是一個控件。
2 創建Adapter
private class NoteAdapter extends RecyclerView.Adapter<NoteHolder>{ private List<Note> notes; public NoteAdapter(List<Note> notes){ this.notes = notes; } public void setNotes(List<Note> notes) { this.notes = notes; } @Override public NoteHolder onCreateViewHolder(ViewGroup parent, int viewType) { return null; } @Override public void onBindViewHolder(NoteHolder holder, int position) { } @Override public int getItemCount() { return 0; } }
前面說了Adapter是有關於數據的操作了,因此在類的內部定義notes字段也很容易理解,我們再來看看這裡覆寫的三個方法,onCreateViewHolder返回值是NoteHolder,因此它是用來創建ViewHolder,onBindViewHolder則可以直接操作NoteHolder,position指的是當前View處在整個List的位置(我們的目的是要創建類似於微信消息列表的一個列表,其每個部件的布局其實是一樣的,只是填充的數據不一樣而已),以便按照當前的位置填入相應的數據。getItemCount則是返回需要相應布局的總數。talk is cheap,show me the code。說再多恐怕也難以表達,下面看代碼,多看幾遍,自然而然就會用了。
private class NoteAdapter extends RecyclerView.Adapter<NoteHolder>{ private List<Note> notes; public NoteAdapter(List<Note> notes){ this.notes = notes; } public void setNotes(List<Note> notes) { this.notes = notes; } @Override public NoteHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater layoutInflater = LayoutInflater.from(getActivity()); View view = layoutInflater.inflate(R.layout.list_item_note,parent,false); return new NoteHolder(view); } @Override public void onBindViewHolder(NoteHolder holder, int position) { Note note = notes.get(position); holder.bindView(note); } @Override public int getItemCount() { return notes.size(); } }
其中R.layout.list_item_note的布局文件如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/list_item_note_title" /> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/list_item_note_content" /> </LinearLayout>
這裡只簡單的使用了Note類中title和content兩個字段,其實就是這個view就是形成整個列表,只是依次填充類不同的數據而已。
前面已經准備好了ViewHolder和Adapter,接下來要做的就是將這些部件組裝在一起,最後將整個fragment貼出來,大家注意onCreateView裡是 Ruhr操作的!
public class NotesListFragment extends Fragment { private RecyclerView noteRecycler; private NoteAdapter noteAdapter; public NotesListFragment() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment //return inflater.inflate(R.layout.fragment_notes_list, container, false); View root = inflater.inflate(R.layout.fragment_notes_list,container,false); noteRecycler = (RecyclerView) root.findViewById(R.id.note_recycler_view); noteRecycler.setLayoutManager(new LinearLayoutManager(getActivity())); NoteLab noteLab = NoteLab.getNoteLab(getActivity()); ArrayList<Note> notes = noteLab.getNotes(); noteAdapter = new NoteAdapter(notes); noteRecycler.setAdapter(noteAdapter); return root; } private class NoteHolder extends RecyclerView.ViewHolder{ private TextView noteTitle; private TextView noteContent; public NoteHolder(View root) { super(root); noteTitle = (TextView) root.findViewById(R.id.list_item_note_title); noteContent = (TextView) root.findViewById(R.id.list_item_note_content); } public void bindView(Note note){ noteTitle.setText(note.getTitle()); noteContent.setText(note.getContent()); } } private class NoteAdapter extends RecyclerView.Adapter<NoteHolder>{ private List<Note> notes; public NoteAdapter(List<Note> notes){ this.notes = notes; } public void setNotes(List<Note> notes) { this.notes = notes; } @Override public NoteHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater layoutInflater = LayoutInflater.from(getActivity()); View view = layoutInflater.inflate(R.layout.list_item_note,parent,false); return new NoteHolder(view); } @Override public void onBindViewHolder(NoteHolder holder, int position) { Note note = notes.get(position); holder.bindView(note); } @Override public int getItemCount() { return notes.size(); } } }
最後給大家貼出最後的效果圖吧!
這是我第一次寫博客,解釋的不多,代碼較多,一來是因為我沒有很多表達的經驗,二來我覺得很多時候類名,函數名足以說明它的用途,過多解釋怕會誤導大家。whatever,還是希望得到大家的支持,我會在堅持寫代碼的同時也堅持把博客寫下去,是對自己學到的知識的總結,也希望確確實實可以幫到需要幫助的朋友。我的QQ891871898,大家有任何技術交流的問題都可以聯系我,批評也可以!另外,求工作!
前言 開始前我們先來關注一下Android Overflow menu的幾個相關問題: 什麼是Overflow menu Android 3.0以上默認不顯示o
工作中有做過手機App項目,前端和android或ios程序員配合完成整個項目的開發,開發過程中與ios程序配合基本沒什麼問題,而android各種機子和rom的
桌面應用程序與浏覽器端的自動化測試都已經歷了十年的發展,無論是從工具上還是項目管理方 法論上都已經趨於成熟。而移動設備端應用程序的自動化測試近兩年才剛起步,似乎一
前言 本篇博客要實現的是一個離線下載和離線閱讀的功能,這是很多閱讀類app都常見的一個功能,典型的應用就是網易新聞。什麼是離線下載?其實這個概念是比較模糊,是離線