您的位置:首页 > 其它

Databinding打造RecyclerView万能适配器

2017-12-07 17:12 459 查看


这是最终效果图,用到了两种布局,Listview和Gridview形式的布局,其中垂直布局中显示了不同类型的item。下面示范如何使用,首先BaseRecyleAdapter如下:

public class BaseRecyleAdapter extends RecyclerView.Adapter<BaseRecyleAdapter.ViewHolder> {
public List<?> data;//用?代表所有所有类型
Map<Integer, Integer> hashMap;

public BaseRecyleAdapter(List<?> data, Map<Integer, Integer> hashMap) {
this.data = data;
this.hashMap = hashMap;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater from = LayoutInflater.from(parent.getContext());
ViewDataBinding inflate = DataBindingUtil.inflate(from, viewType, parent, false);//引入布局
return new ViewHolder(inflate);
}

/**
* map可以入参多个,也就是添加多布局,至少需要传一个,map中的key代表布局id,value对应布局中实体类的BR id
*默认取第一个,也就是把布局id取出来
* @param position
* @return
*/
@Override
public int getItemViewType(int position) {
Set<Integer> integers = hashMap.keySet();
return integers.iterator().next();
}

@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
Integer varid = hashMap.get(getItemViewType(position));
holder.dataBinding.setVariable(varid, data.get(position));//varid表示的是布局中数据名称对应的BR

if (onRecycleitemOnClic != null)//这里是实现item点击
holder.dataBinding.getRoot().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onRecycleitemOnClic.onItemClic(view, position);//开放接口
}
});
}

public OnRecycleitemOnClic getOnRecycleitemOnClic() {
return onRecycleitemOnClic;
}

public void setOnRecycleitemOnClic(OnRecycleitemOnClic onRecycleitemOnClic) {
this.onRecycleitemOnClic = onRecycleitemOnClic;
}

OnRecycleitemOnClic onRecycleitemOnClic;

public interface OnRecycleitemOnClic {
void onItemClic(View view, int position);
}

@Override
public int getItemCount() {
if (data == null)
return 0;
return data.size();
}

public class ViewHolder extends RecyclerView.ViewHolder {
ViewDataBinding dataBinding;

public ViewHolder(ViewDataBinding itemView) {
super(itemView.getRoot());
this.dataBinding = itemView;
}
}
}
我们在activity_main中写的布局如下:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

<data class="com.rvadapter.recyclerviewadapter.MainData">

</data>

<RelativeLayout xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.rvadapter.recyclerviewadapter.activity.MainActivity">

<android.support.v7.widget.RecyclerView
android:id="@+id/rv_main"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>

<android.support.v7.widget.RecyclerView
android:id="@+id/rv_main_grid"
android:layout_below="@+id/rv_main"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
</layout>
上面data里面的class是我们定义的类名,这个类是databinding自己创建的“隐形”类(不直接显示在文件夹中,但存在),我们这里定义了两个recyclerview,水平和垂直的,这里不用一个Recyclerview是因为嵌套本身也
ca45
会增加代码的耦合性,如果内容非常丰富多样的话以后改起来麻烦。 
下面是MainActivity:

public class MainActivity extends FragmentActivity {

private MainData mainData;
private TestListItemAdapter mainAdapter;
public BaseRecyleAdapter mainGridAdapter;
private List<UserInfo> userInfo;
private LinearLayoutManager linearLayoutManager;
private GridLayoutManager gridLayoutManager;//gridview类型的布局

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initdatabinding();
}

private void initdatabinding() {
mainData = DataBindingUtil.setContentView(this, R.layout.activity_main);
linearLayoutManager = new LinearLayoutManager(this);//不设置方向默认是垂直
mainData.rvMain.setLayoutManager(linearLayoutManager);

userInfo = new ArrayList<>();//初始化的操作放在set之前
setUserInfo();
/**
* 这里用TestListItemAdapter是因为adapter里面需要写不同类型的item或者需要自己单独去设置某控件的值
* 如果是相同类型的,比如下面的gridLayoutManager就直接用BaseRecyleAdapter
* 这里的BR是dataBinding自动生成的,我们在布局中写好变量,用“BR.变量名”就能得到
*/
Map<Integer, Integer> map = new HashMap<>();
map.put(R.layout.item_main, BR.info);
map.put(R.layout.item_main_diverse, BR.info2);
mainAdapter = new TestListItemAdapter(userInfo, map);
mainData.rvMain.setAdapter(mainAdapter);

/**
* 加载Grid类型的,这里设置3行
*/
gridLayoutManager = new GridLayoutManager(this, 3);
mainData.rvMainGrid.setLayoutManager(gridLayoutManager);

Map<Integer, Integer> gridMap = new HashMap<>();
gridMap.put(R.layout.item_main_grid, BR.gridinfo);
mainGridAdapter = new BaseRecyleAdapter(userInfo, gridMap);
mainData.rvMainGrid.setAdapter(mainGridAdapter);
}

private void setUserInfo() {
for (int i = 0; i < 5; i++) {
UserInfo userInfo = new UserInfo();
userInfo.setTitle("以梦为马,诗酒趁年华" + i);
userInfo.setName(" ");
userInfo.setCover("http://jyts-public-oss.longruncloud.com/images/4ee98d67ccf5e5d33db6eba5046e1e289eb8d787f7888aab69280e169b4556c5.jpg");
userInfo.setAge("年龄:" + String.valueOf(i));
this.userInfo.add(userInfo);
}
}
}

注释已经很详细,就不赘述了,其中用到了实体类是自己写的,如果是服务端给的接口也是一样用的。Bean代码贴出来:

public class UserInfo {

private String cover;
private String title;
private String name;
private String age;

public String getCover() {
return cover;
}

public void setCover(String cover) {
this.cover = cover;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAge() {
return age;
}

public void setAge(String age) {
this.age = age;
}
}
因为我们垂直布局中需要自己写前面的序号,还有需要自己设置不同类型的item,所以我们需要写自己的Adapter集成BaseRecyleAdapter,重写里面的方法进行设置,就是MainActivity中用到的TestListItemAdapter。

public class TestListItemAdapter extends BaseRecyleAdapter {
public TestListItemAdapter(List<?> data, Map<Integer, Integer> hashMap) {
super(data, hashMap);
}

/**
* 如果有值不是从bean类里面获取的,需要自己去设置的话就重写此方法
* @param holder
* @param position
*/
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
super.onBindViewHolder(holder, position);
int i = position + 1;
String text = i >= 10 ? String.valueOf(i) : String.valueOf("0" + i);
holder.dataBinding.setVariable(BR.itemNum, text);//这里就是设置前面的序号
}
/**
* 编写规则,返回相应布局,比如这里是第四个item加载其他布局
*
* @param position
* @return
*/
@Override
public int getItemViewType(int position) {
if (position == 3)
return R.layout.item_main_diverse;
else
return R.layout.item_main;
}
}
其中需要注意的是在布局中设置图片的话和文字有些不同,我们需要自己实现:

public class ImagBindingUtils {

@BindingAdapter("imgurl")
public static void bindingImage(ImageView imageView, String url) {
Glide.with(imageView.getContext()).load(url).into(imageView);//用的glide加载,在build.gradle中添加依赖就能使用
}
}
用到的layout我只贴一种,因为其他的都是一样的,我这里只是做了item颜色修改:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<data>
<variable
name="info2"
type="com.rvadapter.recyclerviewadapter.bean.UserInfo" />

<variable
name="itemNum2"
type="java.lang.String" />
</data>

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp">

<TextView
android:id="@+id/tv_main_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginRight="10sp"
android:text="@{itemNum2}"
android:textColor="#fb9223"
android:textSize="14sp" />

<ImageView
android:id="@+id/iv_main_img"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginRight="10dp"
android:layout_toRightOf="@+id/tv_main_number"
app:imgurl="@{info2.cover}" />

<TextView
android:id="@+id/tv_main_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/iv_main_img"
android:layout_toRightOf="@+id/iv_main_img"
android:text="@{info2.title}"
android:textColor="@color/red"
android:textSize="10sp" />

<TextView
android:id="@+id/tv_main_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/iv_main_img"
android:layout_toRightOf="@+id/iv_main_img"
android:text="@{info2.name+info2.age}"
android:textColor="@color/gray"
android:textSize="10sp" />

<View
android:layout_width="match_parent"
android:layout_height="0.2dp"
android:layout_below="@+id/tv_main_description"
android:layout_marginTop="10dp"
android:background="@color/gray" />
</RelativeLayout>

</layout>
UserInfo是我们自己创建的Bean类,我们把全类名引入进来,创建了info2的变量,在textview中通过@{info2.}来使用,具体就是这样,如果需要设置item点击事件的话,在自己建的Apater类里实现BaseRecyleAdapter.OnRecycleitemOnClic,然后再构造器里面添加setOnRecycleitemOnClic(this),最后在实现的onItemClic方法中写我们需要进行的操作即可,具体的使用如下:

public class ListenerBookRankAdapter extends BaseRecyleAdapter implements BaseRecyleAdapter.OnRecycleitemOnClic {
private List<RankingBean.SalesBean.BooksBeanDes> booksBeanDes;

public ListenerBookRankAdapter(List<?> data, Map<Integer, Integer> hashMap) {
super(data, hashMap);
this.booksBeanDes = (List<RankingBean.SalesBean.BooksBeanDes>) data;
setOnRecycleitemOnClic(this);//2.设置item点击,Base中已写好
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
super.onBindViewHolder(holder, position);
int i = position + 1;
String text = i >= 10 ? String.valueOf(i) : String.valueOf("0" + i);
holder.dataBinding.setVariable(BR.itemtestnum, text);
}

@Override
public void onItemClic(View view, int position) {//3.重写方法
int id = booksBeanDes.get(position).getBook().getId();
Intent intent = new Intent();
intent.putExtra("ID", id);
intent.setClass(view.getContext(), BookRankDetailsActivity.class);
view.getContext().startActivity(intent);
}
}
使用过程就是这些,如有问题可以留言,希望可以互相学习,Demo链接是http://download.csdn.net/download/xkyh941/10149648,发现Adapter文件夹里面手抖多建了个新建文件夹,我就不重新上传了,联系管理员麻烦,不会影响使用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: