概述
在Android開發(fā)過程中,我們經(jīng)常會用到adapter聚假。因為adapter在基本使用的過程中锦庸,代碼比較繁瑣机蔗,于是進行一個簡單封裝,使調(diào)用起來更加簡單便捷酸员。這節(jié)就來講講這個適配器的封裝吧蜒车。
前言
在Android開發(fā)過程中,我們經(jīng)常會用到adapter幔嗦。因為adapter在基本使用的過程中酿愧,代碼比較繁瑣,于是進行一個簡單封裝邀泉,使調(diào)用起來更加簡單便捷嬉挡。這節(jié)就來講講這個適配器的封裝吧。
今天涉及的內(nèi)容:
- adapter庫依賴
- 封裝類ComAdapter和GroupAdapter概述
- 通用適配器ComAdapter的使用
- 分組適配器GroupAdapter的使用
- MainActivity中調(diào)用示例
- 效果圖和項目結(jié)構(gòu)圖
先來波adapter使用的效果圖吧
一. adapter庫依賴
Github地址
本adapter的封裝是建立在一個第三方庫的基礎(chǔ)之上的汇恤。在使用之前庞钢,你需要添加該庫的依賴:
將JitPack存儲庫添加到您的構(gòu)建文件中(項目根目錄下build.gradle文件):
allprojects {
repositories {
google()
jcenter()
maven { url 'https://jitpack.io' }
}
}
添加依賴項以最新版本為準:
dependencies {
implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.34'
}
二.封裝類ComAdapter和GroupAdapter概述
適配器庫BaseRecyclerViewAdapterHelper是一個專注adapter的庫,里面有一個適配器基類:BaseQuickAdapter因谎,為了方便日常調(diào)度使用基括,我在BaseQuickAdapter基礎(chǔ)上再度擴展,分別整合了兩個adapter基類:ComAdapter和GroupAdapter财岔。
ComAdapter:基于一般的列表或九宮格布局的使用
GroupAdapter:基于簡單的分組列表展示使用风皿。
三.通用適配器ComAdapter的使用
ComAdapter是一個通用適配器基類,里面集成了adapter創(chuàng)建需要的一些基本方法匠璧,包括控件初始化,獲取布局對象桐款,加載動畫,列表數(shù)據(jù)加載夷恍,控件點擊事件監(jiān)聽等方法魔眨。 當你要實現(xiàn)一個線性列表,需要創(chuàng)建adapter的時候酿雪,繼承ComAdapter可以幫你快速實現(xiàn)自己的adapter遏暴。
3.1 繼承ComAdapter,寫自己的Adapter
當RecyclerView加載列表的時候,需要一個適配器(NameAdapter)指黎,你可以像這樣快速來創(chuàng)建它:
public class NameAdapter<T>extends ComAdapter {
private TextView mTvName;
public NameAdapter(List<T> data, Context context) {
//加載布局和數(shù)據(jù)
super(R.layout.item_layout, data, context);
}
@Override
public <T>void initView(BaseViewHolder viewHolder, T obj) {
//控件初始化
mTvName=viewHolder.getView(R.id.tv);
}
@Override
public <T>void initData(BaseViewHolder viewHolder, T obj) {
String name=obj.toString();
mTvName.setText(name);
}
@Override
public <T>void setListener(BaseViewHolder viewHolder, T obj) {
//添加控件監(jiān)聽
addOnClickListener(mTvName,viewHolder,obj);
}
}
3.2 線性布局調(diào)用
mNames=new ArrayList<>();
//for (int i = 0; i < 10; i++) {
// mNames.add("小黃"+i);
//}
mNameAdapter=new NameAdapter<>(mNames,MainActivity.this);
mNameAdapter.setRecyclerLinearManager(mRecyclerView);
3.3 九宮格布局調(diào)用
mNames=new ArrayList<>();
//for (int i = 0; i < 10; i++) {
// mNames.add("小黃"+i);
//}
mNameAdapter=new NameAdapter<>(mNames,MainActivity.this);
mNameAdapter.setRecyclerGridManager(mRecyclerView,4);
3.4 設(shè)置分割線,返回RecyclerView.ItemDecoration對象
//設(shè)置線性布局分割線
LinearDividerItemDecoration linearDivider=mNameAdapter.setLinearLayoutItemSpace(mRecyclerView,5,R.color.colorAccent);
//設(shè)置九宮格局分割線
GridDividerItemDecoration gridDivider=mNameAdapter.setGridLayoutItemSpace(mRecyclerView,5,R.color.colorAccent);
3.5 移除分割線
/**移除RecycleView間距**/
removeItemSpace(RecyclerView recyclerView, RecyclerView.ItemDecoration divider)
3.6 點擊事件
//點擊事件
mNameAdapter.setOnItemClickListener(new AdapterHelper.OnItemClickListener() {
@Override
public void itemClickListener(View view, BaseViewHolder viewHolder, Object obj) {
switch (view.getId()) {
case R.id.tv:
ToastUtil.shortShow("====1====="+obj.toString());
break;
default:
break;
}
}
});
四. 分組適配器GroupAdapter的使用
GroupAdapter是一個列表分組顯示的適配器基類朋凉,里面集成了adapter創(chuàng)建需要的一些基本方法,包括控件初始化,獲取布局對象袋励,加載動畫,列表數(shù)據(jù)加載,控件點擊事件監(jiān)聽等方法茬故。 當你要船創(chuàng)建一個分組顯示功能的adapter盖灸,繼承GroupAdapter可方便快捷實現(xiàn)
4.1 javaBean繼承SectionEntity類
GroupAdapter顯示的數(shù)據(jù),都需要用javaBean進行封裝磺芭。并且JavaBean需要繼承SectionEntity類,然后重寫含(boolean isHeader, String header)參數(shù)的構(gòu)造方法赁炎。 以Person對象為例,你需要這樣處理:
public class Person extends SectionEntity {
private String name;
private int age;
public Person(boolean isHeader, String header) {
super(isHeader,header);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
4.2 繼承GroupAdapter,寫自己的adapter
然后寫一個自己的adapter钾腺,繼承自GroupAdapter徙垫,以PersonAdapter為例:
public class PersonAdapter<T> extends GroupAdapter {
//header
private TextView mTvHeader;
//item
private TextView mTvItem;
public PersonAdapter(List<T> data, Context context) {
super(R.layout.item_layout, R.layout.header_layout, data,context);
}
@Override
protected void convertHead(BaseViewHolder viewHolder, SectionEntity item) {
//標題相關(guān)所有都在此處理
//標題初始化
mTvHeader=viewHolder.getView(R.id.tv_title);
//標題數(shù)據(jù)處理
mTvHeader.setText(item.header);
//標題點擊事件
addOnClickListener(mTvHeader,viewHolder,item);
}
@Override
public <T>void initView(BaseViewHolder viewHolder, T obj) {
//item初始化
mTvItem=viewHolder.getView(R.id.tv);
}
@Override
public <T>void initData(BaseViewHolder viewHolder, T obj) {
//item數(shù)據(jù)處理
Person person= (Person) obj;
mTvItem.setText("姓名:"+person.getName()+" 年齡:"+person.getAge());
}
@Override
public <T>void setListener(BaseViewHolder viewHolder, T obj) {
//item中控件監(jiān)聽
addOnClickListener(mTvItem,viewHolder,obj);
}
}
其中PersonAdapter(List data, Context context)構(gòu)造方法的super方法中,要引入兩個布局id放棒,一個是item的一個是header的姻报。 Header相關(guān)方法都在convertHead中處理。item的相關(guān)處理在initView,initData和setListener方法中進行间螟。
4.3 線性布局使用
mPersonList=new ArrayList<>();
//for (int i = 0; i < 10; i++) {
//Person person;
//if(i%7==0){//header
// person=new Person(true,"標題"+i);
//}else{//item
// person=new Person(false,null);
// person.setName("小黑"+i);
// person.setAge(25+i);
// }
// mPersonList.add(person);
//}
mPersonAdapter=new PersonAdapter<>(mPersonList,MainActivity.this);
mPersonAdapter.setRecyclerLinearManager(mRecyclerView);
4.4 九宮格布局使用
mPersonList=new ArrayList<>();
//for (int i = 0; i < 10; i++) {
//Person person;
//if(i%7==0){//header
// person=new Person(true,"標題"+i);
//}else{//item
// person=new Person(false,null);
// person.setName("小黑"+i);
// person.setAge(25+i);
// }
// mPersonList.add(person);
//}
mPersonAdapter=new PersonAdapter<>(mPersonList,MainActivity.this);
mPersonAdapter.setRecyclerGridManager(mRecyclerView,3);
4.5 設(shè)置分割線,返回RecyclerView.ItemDecoration對象
線性布局的時候吴旋,可以像下面這樣設(shè)置分割線:
//線性布局分割線
LinearDividerItemDecoration linearDivider=mPersonAdapter.setLinearLayoutItemSpace(mRecyclerView, 5, R.color.colorAccent);
注意: 在實現(xiàn)分組適配器<即繼承GroupAdapter的adapter>不能使用setGridLayoutItemSpace給列表設(shè)置分割線,會出現(xiàn)ui上顯示的bug厢破,為了避免 用戶使用不當荣瑟,我已經(jīng)將GroupAdapter類中的setGridLayoutItemSpace拋出異常并做以錯誤提示。大家若還是需要在分組九宮格布局中做分割線的話摩泪, 需要自己在布局中笆焰,或者在adapter中處理數(shù)據(jù)的時候,用代碼來實現(xiàn)分割線效果见坑。
4.6 移除分割線
/**移除RecycleView間距**/
removeItemSpace(RecyclerView recyclerView, RecyclerView.ItemDecoration divider)
4.7 點擊事件
若要設(shè)置adapter的點擊事件嚷掠,你可以像下面這樣寫:
//點擊事件
mPersonAdapter.setOnItemClickListener(new AdapterHelper.OnItemClickListener() {
@Override
public void itemClickListener(View view, BaseViewHolder viewHolder, Object obj) {
Person person= (Person) obj;
switch (view.getId()) {
case R.id.tv_title://header
ToastUtil.shortShow("===="+person.header+"===");
break;
case R.id.tv://item
ToastUtil.shortShow("===="+person.getName()+"===");
break;
default:
break;
}
}
});
五.MainActivity中調(diào)用示例
下面貼出adapter在MainActivity中使用的代碼:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button mBtn1;
private Button mBtn2;
private Button mBtn3;
private Button mBtn4;
private RecyclerView mRecyclerView;
private List<String>mNames;
private NameAdapter<String>mNameAdapter;
private List<Person>mPersonList;
private PersonAdapter<Person>mPersonAdapter;
private LinearDividerItemDecoration mLinearDivider;
private GridDividerItemDecoration mGridDivider;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
setListener();
}
private void initData() {
mBtn1 = findViewById(R.id.btn1);
mBtn2 = findViewById(R.id.btn2);
mBtn3 = findViewById(R.id.btn3);
mBtn4 = findViewById(R.id.btn4);
mRecyclerView = findViewById(R.id.rv);
mBtn1.setText("通用線性");
mBtn2.setText("通用九宮");
mBtn3.setText("分組線性");
mBtn4.setText("分組九宮");
}
private void setListener() {
mBtn1.setOnClickListener(this);
mBtn2.setOnClickListener(this);
mBtn3.setOnClickListener(this);
mBtn4.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn1://通用布局線性測試
commonLinearLayout();
break;
case R.id.btn2://通用布局九宮格測試
commonGridLayout();
break;
case R.id.btn3://分組布局線性測試
diffGropLinearLayout();
break;
case R.id.btn4://分組布局九宮格測試
diffGropGridLayout();
break;
default:
break;
}
//點擊事件
commonDiffClick();
}
private void initCommonData(){
//通用布局
if(mNames==null) {
mNames = new ArrayList<>();
}
mNames.clear();
for (int i = 0; i < 10; i++) {
mNames.add("小黃" + i);
}
}
private void initdiffGropData(){
//分組布局
if(mPersonList==null) {
mPersonList = new ArrayList<>();
}
mPersonList.clear();
for (int i = 0; i < 10; i++) {
Person person;
if(i%7==0){//header
person=new Person(true,"標題"+i);
}else{//item
person=new Person(false,null);
person.setName("小黑"+i);
person.setAge(25+i);
}
mPersonList.add(person);
}
}
/**
* 通用布局線性測試
**/
private void commonLinearLayout() {
initCommonData();
mNameAdapter = new NameAdapter<>(mNames, MainActivity.this);
mNameAdapter.setRecyclerLinearManager(mRecyclerView);
//清除舊的分割線
mNameAdapter.removeItemSpace(mRecyclerView,mLinearDivider);
mNameAdapter.removeItemSpace(mRecyclerView,mGridDivider);
//設(shè)置分割線
mLinearDivider=mNameAdapter.setLinearLayoutItemSpace(mRecyclerView, 5, R.color.colorAccent);
}
/**
* 通用布局九宮格測試
**/
private void commonGridLayout() {
initCommonData();
mNameAdapter = new NameAdapter<>(mNames, MainActivity.this);
mNameAdapter.setRecyclerGridManager(mRecyclerView, 3);
//清除舊的分割線
mNameAdapter.removeItemSpace(mRecyclerView,mLinearDivider);
mNameAdapter.removeItemSpace(mRecyclerView,mGridDivider);
//設(shè)置分割線
mGridDivider=mNameAdapter.setGridLayoutItemSpace(mRecyclerView, 5, R.color.colorAccent);
}
/**
* 分組布局線性測試
**/
private void diffGropLinearLayout() {
initdiffGropData();
mPersonAdapter=new PersonAdapter<>(mPersonList,MainActivity.this);
mPersonAdapter.setRecyclerLinearManager(mRecyclerView);
//清除舊的分割線
mNameAdapter.removeItemSpace(mRecyclerView,mLinearDivider);
mNameAdapter.removeItemSpace(mRecyclerView,mGridDivider);
//設(shè)置分割線
mLinearDivider=mPersonAdapter.setLinearLayoutItemSpace(mRecyclerView, 5, R.color.colorAccent);
}
/**
* 分組布局九宮格測試
**/
private void diffGropGridLayout() {
initdiffGropData();
mPersonAdapter=new PersonAdapter<>(mPersonList,MainActivity.this);
mPersonAdapter.setRecyclerGridManager(mRecyclerView,3);
//清除舊的分割線
mNameAdapter.removeItemSpace(mRecyclerView,mLinearDivider);
mNameAdapter.removeItemSpace(mRecyclerView,mGridDivider);
}
/**點擊事件**/
private void commonDiffClick(){
//通用布局點擊事件
if(mNameAdapter!=null) {
mNameAdapter.setOnItemClickListener(new AdapterHelper.OnItemClickListener() {
@Override
public void itemClickListener(View view, BaseViewHolder viewHolder, Object obj) {
switch (view.getId()) {
case R.id.tv:
ToastUtil.shortShow("====1=====" + obj.toString());
break;
default:
break;
}
}
});
}
//分組布局點擊事件
if(mPersonAdapter!=null) {
mPersonAdapter.setOnItemClickListener(new AdapterHelper.OnItemClickListener() {
@Override
public void itemClickListener(View view, BaseViewHolder viewHolder, Object obj) {
Person person = (Person) obj;
switch (view.getId()) {
case R.id.tv_title://header
ToastUtil.shortShow("====" + person.header + "===");
break;
case R.id.tv://item
ToastUtil.shortShow("====" + person.getName() + "===");
break;
default:
break;
}
}
});
}
}
}
六. 效果圖和項目結(jié)構(gòu)圖
效果圖
項目結(jié)構(gòu)圖
最后
雖然萬能適配器方便好用,但是我還是推薦使用原生寫法,因為原生寫法更靈活鳄梅,不會出現(xiàn)莫名的問題叠国。萬能適配器的動畫目前可能有點毛病,謹慎使用列表動畫!