FormLayoutManager首頁,裏面有github地址
Adapter基類用法
從我首頁的文章,大家應該瞭解到FormLayoutManager實現的是表格每一格的view都會複用,由想可知,我們adapter的數據源的list,存儲的是每一格的數據。下面先看一下基類BaseFormAdapter,其他簡單的重寫我不多說,我說幾個關鍵的地方。
@Override
public int getItemCount() {
return getRowCount() * getColumnCount();
}
再重複一遍,我們複用的是每一格的view,故整個itemCount就是表格的格子數,getRowCount和getColumnCount即使提供給子類來重寫描述表格的行數和列數
/**
* 表格的行數
* @return
*/
public abstract int getRowCount();
/**
* 表格的列數
* @return
*/
public abstract int getColumnCount();
接下來看一下我們第一個例子界面TestFormActivity,裏面的TestAdapter是直接繼承BaseFormAdapter的adapter
@Override
public int getRowCount() {
return 10;
}
@Override
public int getColumnCount() {
return 10;
}
這裏都返回10,看一下界面,就知道,這個表格就是簡單的一個10x10,數據就是0到99的字符串。其他方法重寫跟你平時用RecyclerView的adapter一樣,但要注意的是下面的三個方法都是針對一個格子而言的,佈局也好,holder也好,設置數據也好。
@Override
public View createView(ViewGroup viewGroup, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.adapter_monster_form_item, viewGroup, false);
return view;
}
@Override
public RecyclerView.ViewHolder createViewHolder(View view, int viewType) {
RecyclerView.ViewHolder viewHolder = new ItemHolder(view);
return viewHolder;
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
ItemHolder holder = (ItemHolder) viewHolder;
holder.tvItem.setText(mList.get(position));
}
BaseHFormAdapter和BaseVFormAdapter
這個兩個分別是水平表格和垂直表格的adapter。(水平表格、垂直表格這是我亂取的名字,後面告訴具體是什麼)
上面的TestAdapter大家看明白後,接下來就可以認真聽了。一般我們的數據源(如後臺,數據庫給的數據),它不是每一格子代表一個實體的,而是以一行或一列爲一個對象實體的,如下兩圖的表格
左圖就是我上面所說的水平表格,在代碼裏一行就是一個數據Monster對象
右圖就是我上面所說的垂直表格,在代碼裏一行就是一個數據Monster對象
所以纔會出現BaseHFormAdapter和BaseVFormAdapter這兩個基類,兩個基類只是異曲同工,我就抽BaseHFormAdapter來說。
BaseHFormAdapter的出現就是,儘管我們的表格是一個個格子複用,但是你的數據源list還是可以是一個List<Monster>,而不是像TestAdapter那樣每個格子的數據都存到list。對於BaseHFormAdapter來說,它的list每個數據對應的就是每一行的數據。說白了,BaseHFormAdapter就是一個幫我們把一行數據轉換成表格一格格數據的媒介。
@Override
public int getRowCount() {
return mList.size();
}
BaseHFormAdapter重寫了getRowCount的方法(而BaseVFormAdapter當然就是重寫getColumnCount,至於爲啥,自己想啊,這世界不是你老師,不是什麼問題都會公仔畫出牆)
getRowCount我們返回的就是list的size了,如上所說,我們的list就是代表每一行數據的列表。而getColumnCount我們就不重寫,我們交給繼承BaseHFormAdapter的子類來填寫。
接下來看一下繼承BaseHFormAdapter的MonsterHAdapter
public class MonsterHAdapter extends BaseHFormAdapter<Monster> {
public MonsterHAdapter(Context context) {
super(context);
}
@Override
protected String[] getRowDatas(Monster model) {
return new String[]{model.getName(), model.getAttribute(), model.getLv(), model.getAtk(),
model.getDef(), model.getRace(), model.getType1(), model.getType2()};
}
public MonsterHAdapter(Context context, List<Monster> list) {
super(context, list);
}
@Override
protected View createView(ViewGroup viewGroup, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.adapter_monster_form_item, viewGroup, false);
return view;
}
@Override
protected RecyclerView.ViewHolder createViewHolder(View view, int viewType) {
RecyclerView.ViewHolder viewHolder = new ItemHolder(view);
return viewHolder;
}
@Override
protected void setData(RecyclerView.ViewHolder viewHolder, int rowIndex, int columnIndex, String content) {
ItemHolder holder = (ItemHolder) viewHolder;
holder.tvItem.setText(content);
}
@Override
public int getColumnCount() {
return 8;
}
private class ItemHolder extends RecyclerView.ViewHolder {
public TextView tvItem;
public ItemHolder(View itemView) {
super(itemView);
tvItem = itemView.findViewById(R.id.tv_item);
}
}
}
可以看到getColumnCount返回的是8,表明我的表格要顯示8列。因爲我不知道你要用你實體多少屬性來做列,所以這列數根據實際情況來填寫。
最關鍵的一個方法就是getRowDatas,也是提供給大家重寫的。看這代碼,大家也許get到點了,這個getRowDatas返回的數組就是告訴我們的表格第一列到第八列分別是用實體的那些屬性,再看一下BaseHFormAdapter的onBindViewHolder就會更明白了
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
int rowIndex = position / getColumnCount();
int columnIndex = position % getColumnCount();
String[] rowDatas = getRowDatas(mList.get(rowIndex));
setData(holder, rowIndex, columnIndex, rowDatas[columnIndex]);
}
在onBindViewHolder裏面,我把position轉換成該格子對應的行和列,以及該格子對應的文案,一起傳到setData。這個時候焦點回到MonsterHAdapter的setData,這個setData方法就是給大家設置每個格控件的屬性。
一開始我設計的時候,想getRowDatas這個返回的是一個數組,而每次我們設置格子數據的時候,這裏都返回一個數組,而我們每次只用到數組裏面一個值。我感覺我應該讓getRowDatas返回一個字符串就好了,裏面應該用switch/case來告訴表格用實體的那個屬性。想着想着,還是數組看起來非常直觀地知道每一列分別是那個屬性,雖然switch/case也直觀,但太大一坨了,你想一想,要是你的表格有30幾列,你這switch/case該有多少行。就算我每次返回一個數組,那個數組也很快會被回收,應該也不太會影響性能。其實也如果你是用kotlin的話,我建議的改一下我的BaseHFormAdapter再用,把getRowDatas返回一個字符串,因爲kotlin的switch/case非常簡潔,而且非常直觀地能看出第幾列是用那個屬性。
這些Adapter基本就當介紹完了。接下來會詳細說FormLayoutManager裏面的代碼了。
敬請期待……