我有一个基本的自定义视图,如下所示:
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()
)。
我还需要能够在RecyclerView
适配器中使用自定义视图。
以下是我的适配器目前的样子:
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()
中添加任何内容吗?
注意:我必须使用自定义视图,因为我在不同的适配器下使用此视图(即:不仅仅是RecyclerView
适配器)。
答案 0 :(得分:16)
假设CustomView
类看起来像这样:
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
看起来像这样:
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
担心自己的设置。 CustomView
在调用User
方法之前无法获得setUser
个实例,因此构造函数中不会发生用户访问。在任何情况下,CustomView
生命周期超过一RecyclerView
,可以要求它在不同时间显示许多不同用户的信息。 CustomView
需要能够执行此操作。因此,引入了setUser
方法。CustomView
是由代码而不是XML实例化的,所以大小的属性不能用XML定义。因此,调整是在即时之后以编程方式完成的。onBindViewHolder
只需拨打setUser
上的CustomView
即可将CustomView
与正确的User
个实例相关联。ViewHolder
类现在只是RecyclerView
项与CustomView
之间的链接。在RecyclerView
中使用来自另一个类的预构建自定义视图(即不在RecyclerView.Adapter
内扩充XML)似乎从未进行过讨论。即使自定义视图仅在RecyclerView
内使用,我认为这也是一个很好的主意,因为它promotes separation of concerns和adherence to the Single Responsibility Principle。
答案 1 :(得分:3)
CustomView extends RelativeLayout {
您已经拥有一个视图(好吧,ViewGroup
)
如何填写自定义视图?
您不需要......自定义视图对象的要点是不需要XML,因此没有通货膨胀。
您可以创建new CustomView()
,但我需要设置所有布局参数,这些参数在XML中看起来更干净。
大多数RecyclerView
教程都会显示inflating via XML。
View customView = inflater.inflate(...); ViewHolder viewHolder = new ViewHolder(customView);
这应该有效,因为在类链中,你有CustomView > RelativeLayout > ViewGroup > View
LayoutInflater inflater = LayoutInflater.from(context);
就像我之前说过的那样,如果没有要扩充的XML文件,则不需要这样做。
您也不需要context
变量。
parent.getContext()
是一个很好的解决方案。
// ANYTHING HERE?
嗯,是的,你应该&#34;绑定&#34; ViewHolder
包含ViewHolder
应保留的数据。
同样,大多数(如果不是全部)教程都涵盖了这一点。
答案 2 :(得分:-1)
<强> list_content.xml 强>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:text="TextView"
android:layout_width="@dimen/_160sdp"
android:textSize="@dimen/_14sdp"
android:layout_gravity="center|bottom"
android:layout_height="match_parent"
android:layout_weight="1"
android:paddingTop="@dimen/_10sdp"
android:id="@+id/name"
/>
<ImageView
android:layout_width="@dimen/_20sdp"
android:layout_gravity="center|right"
android:layout_height="@dimen/_20sdp"
app:srcCompat="@drawable/close"
android:id="@+id/close"
android:layout_weight="1" />
</LinearLayout>
Adapter.java
public class yourAdapter extends RecyclerView.Adapter<yourAdapter .SimpleViewHolder> {
private Context mContext;
ArrayList<String> mylist;
public yourAdapter (Context context, ArrayList<String> checklist) {
mContext = context;
mylist = checklist;
}
@Override
public yourAdapter .SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_content, parent, false);
return new yourAdapter .SimpleViewHolder(view);
}
@Override
public void onBindViewHolder(final yourAdapter .SimpleViewHolder holder, final int position) {
holder.name.setText(adap.getName());
}
@Override
public long getItemId(int i) {
return 0;
}
@Override
public int getItemCount() {
return mylist.size();
}
@Override
public int getItemViewType(int i) {
return 0;
}
public static class SimpleViewHolder extends RecyclerView.ViewHolder {
TextView name;
Imageview content;
public SimpleViewHolder(View itemView) {
super(itemView);
name= (TextView) itemView.findViewById(R.id.name);
close= (Imageview) itemView.findViewById(R.id.close);
}
}
}
然后在您想要的活动中调用适配器类
https://developer.sonymobile.com/2010/05/20/android-tutorial-making-your-own-3d-list-part-1/