在RecyclerView适配器中使用自定义视图? [英] Use custom View in a RecyclerView Adapter?
问题描述
我有一个基本的自定义视图,如下所示:
I have a basic custom View which looks like this:
public class CustomView extends RelativeLayout {
private User user;
private ImageView profilePicture;
public CustomView(Context context) {
super(context);
init();
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
inflate(getContext(), R.layout.custom_layout, this);
profilePicture = (ImageView) findViewById(R.id.profilePicture);
// ACCESS USER MODEL HERE
// e.g. user.getUsername()
}
}
如您所见,我想在视图中访问用户数据(即:user.getUsername()
).
As you can see, I'd like to access user data in the View (i.e.: user.getUsername()
).
我还需要能够在RecyclerView
适配器中使用自定义视图.
I also need to be able to use the custom View in a RecyclerView
Adapter.
这是我的适配器当前的外观:
Here is what my Adapter currently looks like:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private Context context;
private List<User> userData;
public MyAdapter(Context context, List<User> userData) {
this.context = context;
this.userData = userData;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View v) {
super(v);
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
// HOW TO INFLATE THE CUSTOM VIEW?
// ViewHolder viewHolder = new ViewHolder(customView);
return viewHolder;
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
// ANYTHING HERE?
}
@Override
public int getItemCount() {
return userData.size();
}
}
如何在适配器中为自定义视图充气?
另外,我应该在onBindViewHolder()
中放入任何内容吗?
How can I inflate the custom View in the Adapter?
Also, should I put anything in onBindViewHolder()
?
注意:我必须使用自定义视图,因为我在不同的适配器下使用该视图(即:不仅是这个RecyclerView
适配器).
Note: I must use a custom View, as I use this View under different Adapters (i.e.: not just this RecyclerView
Adapter).
推荐答案
假设一个CustomView
类看起来像这样:
Assuming a CustomView
class that looks something like this:
public class CustomView extends RelativeLayout {
private User user;
private ImageView profilePicture;
// override all constructors to ensure custom logic runs in all cases
public CustomView(Context context) {
this(context, null);
}
public CustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public CustomView(
Context context,
AttributeSet attrs,
int defStyleAttr,
int defStyleRes
) {
super(context, attrs, defStyleAttr, defStyleRes);
// put all custom logic in this constructor, which always runs
inflate(getContext(), R.layout.custom_layout, this);
profilePicture = (ImageView) findViewById(R.id.profilePicture);
}
public void setUser(User newUser) {
user = newUser;
// ACCESS USER MODEL HERE
// e.g. user.getUsername()
}
}
您的RecyclerView.Adapter
和RecyclerView.ViewHolder
可能看起来像这样:
Your RecyclerView.Adapter
and RecyclerView.ViewHolder
could look something like this:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
// no Context reference needed—can get it from a ViewGroup parameter
private List<User> userData;
public MyAdapter(List<User> userData) {
// make own copy of the list so it can't be edited externally
this.userData = new ArrayList<User>(userData);
}
@Override
public int getItemCount() {
return userData.size();
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// no need for a LayoutInflater instance—
// the custom view inflates itself
CustomView itemView = new CustomView(parent.getContext());
// manually set the CustomView's size
itemView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
));
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.getCustomView().setUser(userData.get(position));
}
public class ViewHolder extends RecyclerView.ViewHolder {
private CustomView customView;
public ViewHolder(View v) {
super(v);
customView = (CustomView) v;
}
public CustomView getCustomView() {
return customView;
}
}
}
-
CustomView
管理自己的设置,该设置发生在其自己的构造函数中,在这种情况下,使用XML文件的填充. (或者,它可以通过编程方式设置其子视图.) - 因此,
RecyclerView.Adapter
不需要执行任何充气操作,只需创建一个新的CustomView
实例,并让CustomView
担心自己的设置即可. - 在调用其
setUser
方法之前,CustomView
无法获得User
实例,因此在构造函数中无法进行用户访问.在任何情况下,在CustomView
个生命周期中,RecyclerView
都可以要求它在不同时间显示许多不同用户的信息.CustomView
需要能够执行此操作.因此,引入了setUser
方法. - 由于
CustomView
是通过代码而不是XML实例化的,因此无法在XML中定义大小属性.因此,大小是在实例化后以编程方式完成的. -
onBindViewHolder
只需在CustomView
上调用setUser
即可将CustomView
与正确的User
实例链接. -
ViewHolder
类现在只是RecyclerView
项目和CustomView
之间的链接. - The
CustomView
manages its own setup, which occurs in its own constructor and in this case uses inflation of an XML file. (Alternatively, it could set up its child views programmatically.) - Because of this, the
RecyclerView.Adapter
doesn't need to perform any inflation—it just creates a newCustomView
instance, and lets theCustomView
worry about its own setup. - The
CustomView
can't get aUser
instance until itssetUser
method is called, so user access cannot occur in the constructor. In any case, over oneCustomView
lifetime, aRecyclerView
could ask it to show information for many different users at different times. TheCustomView
needs to be able to do this. Therefore, asetUser
method is introduced. - Because the
CustomView
is instantiated by code instead of by XML, attributes for size can't be defined in XML. Therefore, sizing is done programmatically after instantation. onBindViewHolder
simply callssetUser
on theCustomView
to link theCustomView
with the correctUser
instance.- The
ViewHolder
class is now just a link between aRecyclerView
item and aCustomView
.
似乎从未讨论过使用RecyclerView
内另一个类的预构建自定义视图(即,不夸大RecyclerView.Adapter
内的XML).我认为,即使自定义视图仅在RecyclerView
中使用,这也是一个好主意,因为它遵守单一责任原则.
Using pre-built custom views from another class within RecyclerView
s (i.e. not inflating XML within the RecyclerView.Adapter
) never seems to be discussed. I think it's an excellent idea even when the custom view is exclusively used within a RecyclerView
, because it promotes separation of concerns and adherence to the Single Responsibility Principle.
这篇关于在RecyclerView适配器中使用自定义视图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!