我想在一个 RecyclerView 中有 2 个布局
我有一个名为 Bookmark 的回收器 View 列表,它是从 xml 解析的,这一切正常,但我想在此回收器 View 中放置另一个布局,其中包含一个按钮并且可以单击。 就像照片中的图标来自 recyclerview,加号按钮需要与列表兼容,如果列表更大或更小,按钮将与列表的空间兼容。
这是我的适配器新代码,它取决于@LluisFelisart 的回答
这是错误
ViewHolder View 在创建时不得附加。确保您没有将“true”传递给 LayoutInflater.inflate(..., boolean attachToRoot) 的 attachToRoot 参数
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
ArrayList<Bookmark> arrayList = new ArrayList<>();
public MyAdapter(Context context, ArrayList<Bookmark> arrayList) {
this.context = context;
this.arrayList = arrayList;
}
public class ViewHolder0 extends RecyclerView.ViewHolder {
TextView tvName,tvId,tvSearchUrl,tvNativeUrl;
ImageView tvIcon;
public ViewHolder0(@NonNull View itemView) {
super(itemView);
tvName=itemView.findViewById(R.id.textView);
tvIcon = itemView.findViewById(R.id.image_view);
/* tvId=itemView.findViewById(R.id.tvId);
tvSearchUrl=itemView.findViewById(R.id.tvSearchUrl);
tvNativeUrl=itemView.findViewById(R.id.tvNativeUrl);*/
}
}
public class ViewHolder2 extends RecyclerView.ViewHolder {
ImageView tvAddBookmark;
public ViewHolder2(@NonNull View itemView) {
super(itemView);
tvAddBookmark = itemView.findViewById(R.id.image_button_add);
}
}
@Override
public int getItemViewType(int position) {
// Just as an example, return 0 or 2 depending on position
// Note that unlike in ListView adapters, types don't have to be contiguous
return position % 2 * 2;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.grid_item, viewGroup, false);
switch (i) {
case 0: return new ViewHolder0(viewGroup);
case 2: return new ViewHolder2(viewGroup);
}
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case 0:
ViewHolder0 viewHolder0 = (ViewHolder0) holder;
((ViewHolder0) holder).tvName.setText(arrayList.get(position).getName());
((ViewHolder0) holder).tvIcon.setImageResource(arrayList.get(position).getIcon());
break;
case 2:
ViewHolder2 viewHolder2 = (ViewHolder2) holder;
}
((ViewHolder0) holder).tvIcon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent;
intent = new Intent(context, BookmarkActivity.class);
v.getContext().startActivity(intent);
}
});
((ViewHolder0) holder).tvIcon.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
Intent intent = new Intent(context, ActivityBookmarksFavorites.class);
v.getContext().startActivity(intent);
return false;
}
});
}
@Override
public int getItemCount() {
return arrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView tvName,tvId,tvSearchUrl,tvNativeUrl;
ImageView tvIcon;
public ViewHolder(@NonNull View itemView) {
super(itemView);
tvName=itemView.findViewById(R.id.textView);
tvIcon = itemView.findViewById(R.id.image_view);
/* tvId=itemView.findViewById(R.id.tvId);
tvSearchUrl=itemView.findViewById(R.id.tvSearchUrl);
tvNativeUrl=itemView.findViewById(R.id.tvNativeUrl);*/
}
}
}
这是网格项目布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:orientation="vertical"
android:visibility="visible"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:id="@+id/image_view"
style="@style/BookmarkIconIv" />
<TextView android:id="@+id/textView"
android:layout_marginTop="1.0dip"
style="@style/BookmarkTextTv" />
</LinearLayout>
这是我想在回收站 View 中的按钮布局
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:id="@+id/image_button_add"
android:layout_width="45dp"
android:layout_height="45dp"
android:src="@drawable/ic_add_black_24dp"
android:background="@color/transparent" />
</android.support.constraint.ConstraintLayout>
这是回收者查看的 fragment
public class FragmentBookmark extends Fragment {
ArrayList<Bookmark> arrayList = new ArrayList<>();
XmlPullParser pullParser;
MyAdapter myAdapter;
View paramView;
RecyclerView myRecyclerView;
private Context mContext;
@Override
public void onAttach(Context context) {
super.onAttach(context);
mContext = context;
}
@Nullable
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
paramView = inflater.inflate(R.layout.bookmark, container, false);
myRecyclerView = paramView.findViewById(R.id.myRecyclerView);
myRecyclerView.setLayoutManager(new GridLayoutManager(mContext, 4));
myRecyclerView.setHasFixedSize(true);
myAdapter = new MyAdapter(mContext, arrayList);
myRecyclerView.setAdapter(myAdapter);
try {
XmlPullParser xpp = getResources().getXml(R.xml.bookmarks);
while (xpp.getEventType() != XmlPullParser.END_DOCUMENT) {
if (xpp.getEventType() == XmlPullParser.START_TAG) {
if (xpp.getName().equals("Bookmark")) {
Bookmark bookmark = new Bookmark();
bookmark.setName(xpp.getAttributeValue(null, "name"));
int drawableResourceId = getResources().getIdentifier(xpp.getAttributeValue(null, "icon"),"drawable", mContext.getPackageName());
bookmark.setIcon(drawableResourceId);
arrayList.add(bookmark);
}
}
xpp.next();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
myAdapter.notifyDataSetChanged();
return paramView;
}
}
这是包含recyclerview的布局书签
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/myRecyclerView"
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:fillViewport="false">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
最佳答案
答案在这里
按照这个步骤
首先为您的多 View 类型创建两个布局
示例代码
layout.layout_one
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:cardCornerRadius="15dp"
app:cardElevation="5dp"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="Name : " />
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="Icon : " />
<ImageView
android:id="@+id/tvIcon"
android:layout_width="20dp"
android:layout_height="20dp"
android:padding="10dp"
android:text="" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="Id : " />
<TextView
android:id="@+id/tvId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="SearchUrl : " />
<TextView
android:id="@+id/tvSearchUrl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="NativeUrl : " />
<TextView
android:id="@+id/tvNativeUrl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
layout.button_two
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imgButton"
android:layout_width="50dp"
android:layout_height="50dp" />
</LinearLayout>
现在你需要为你的两个viewType创建两个RecyclerView.ViewHolder
现在你需要覆盖getItemViewType()
- 它返回 position 项目的
viewType
以便 View 回收。
现在在您的 onCreateViewHolder()
方法中,您需要返回您的 ViewHolder
实例viewType
将使用 getItemViewType()
方法
比在你的 onBindViewHolder()
方法中基于你的 viewType
设置你的 View 属性
here is the sample code of
RecyclerView.Adapter
with multiple view types
数据适配器
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
public class DataAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
ArrayList<Bookmark> arrayList = new ArrayList<>();
public static final int ITEM_TYPE_ONE = 0;
public static final int ITEM_TYPE_TWO = 1;
public DataAdapter(Context context, ArrayList<Bookmark> arrayList) {
this.context = context;
this.arrayList = arrayList;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = null;
// check here the viewType and return RecyclerView.ViewHolder based on view type
if (viewType == ITEM_TYPE_ONE) {
view = LayoutInflater.from(context).inflate(R.layout.layout_one, parent, false);
return new ViewHolder(view);
} else if (viewType == ITEM_TYPE_TWO) {
view = LayoutInflater.from(context).inflate(R.layout.button_two, parent, false);
return new ButtonViewHolder(view);
}else {
return null;
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
final int itemType = getItemViewType(position);
// First check here the View Type
// than set data based on View Type to your recyclerview item
if (itemType == ITEM_TYPE_ONE) {
ViewHolder viewHolder = (ViewHolder) holder;
viewHolder.tvName.setText(arrayList.get(position).getName());
viewHolder.tvIcon.setImageResource(arrayList.get(position).getIcon());
viewHolder.tvSearchUrl.setText(arrayList.get(position).getSearchUrl());
viewHolder.tvNativeUrl.setText(arrayList.get(position).getNativeUrl());
} else if (itemType == ITEM_TYPE_TWO) {
ButtonViewHolder buttonViewHolder = (ButtonViewHolder) holder;
buttonViewHolder.imgButton.setImageResource(arrayList.get(position).getIcon());
}
}
@Override
public int getItemViewType(int position) {
// based on you list you will return the ViewType
if (arrayList.get(position).getViewType() == 0) {
return ITEM_TYPE_ONE;
} else {
return ITEM_TYPE_TWO;
}
}
@Override
public int getItemCount() {
return arrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView tvName, tvId, tvSearchUrl, tvNativeUrl;
ImageView tvIcon;
public ViewHolder(@NonNull View itemView) {
super(itemView);
tvName = itemView.findViewById(R.id.tvName);
tvIcon = itemView.findViewById(R.id.tvIcon);
tvId = itemView.findViewById(R.id.tvId);
tvSearchUrl = itemView.findViewById(R.id.tvSearchUrl);
tvNativeUrl = itemView.findViewById(R.id.tvNativeUrl);
}
}
public class ButtonViewHolder extends RecyclerView.ViewHolder {
ImageView imgButton;
public ButtonViewHolder(@NonNull View itemView) {
super(itemView);
imgButton = itemView.findViewById(R.id.imgButton);
}
}
}
当您在列表中添加数据时,您需要在列表中提供viewtype
在您的 Bookmark
POJO 类中进行一些更改
Bookmark
POJO class
public class Bookmark
{
String name,id,nativeUrl,searchUrl;
int icon;
int viewType;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getIcon() {
return icon;
}
public void setIcon(int icon) {
this.icon = icon;
}
public String getNativeUrl() {
return nativeUrl;
}
public void setNativeUrl(String nativeUrl) {
this.nativeUrl = nativeUrl;
}
public String getSearchUrl() {
return searchUrl;
}
public void setSearchUrl(String searchUrl) {
this.searchUrl = searchUrl;
}
public int getViewType() {
return viewType;
}
public void setViewType(int viewType) {
this.viewType = viewType;
}
@Override
public String toString() {
return "Bookmark{" +
"name='" + name + '\'' +
", icon='" + icon + '\'' +
", id='" + id + '\'' +
", nativeUrl='" + nativeUrl + '\'' +
", searchUrl='" + searchUrl + '\'' +
'}';
}
}
Sample activity code
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private Context mContext;
ArrayList<Bookmark> arrayList = new ArrayList<>();
RecyclerView myRecyclerView;
DataAdapter dataAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
myRecyclerView = findViewById(R.id.myRecyclerView);
myRecyclerView.setLayoutManager(new LinearLayoutManager(mContext));
myRecyclerView.setHasFixedSize(true);
dataAdapter = new DataAdapter(mContext, arrayList);
myRecyclerView.setAdapter(dataAdapter);
try {
XmlPullParser xpp = getResources().getXml(R.xml.bookmarks);
while (xpp.getEventType() != XmlPullParser.END_DOCUMENT) {
if (xpp.getEventType() == XmlPullParser.START_TAG) {
if (xpp.getName().equals("Bookmark")) {
Log.e("MY_VALUE", " * " + xpp.getAttributeValue(0) + " * ");
Log.e("MY_VALUE", " * " + xpp.getAttributeValue(1) + " * ");
Log.e("MY_VALUE", " * " + xpp.getAttributeValue(5) + " * ");
Log.e("MY_VALUE", " * " + xpp.getAttributeValue(2) + " * ");
Log.e("MY_VALUE", " * " + xpp.getAttributeValue(3) + " * ");
Log.e("MY_VALUE", " * " + xpp.getAttributeValue(4) + " * ");
Bookmark bookmark = new Bookmark();
bookmark.setName(xpp.getAttributeValue(0));
int drawableResourceId = this.getResources().getIdentifier(xpp.getAttributeValue(1), "drawable", mContext.getPackageName());
bookmark.setIcon(drawableResourceId);
bookmark.setId(xpp.getAttributeValue(2));
bookmark.setSearchUrl(xpp.getAttributeValue(3));
bookmark.setNativeUrl(xpp.getAttributeValue(4));
// here you need to set view type
bookmark.setViewType(0);
arrayList.add(bookmark);
}
}
xpp.next();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// here i have added second viewType
// you need to set as per your requirement
Bookmark bookmark = new Bookmark();
bookmark.setViewType(1);
bookmark.setIcon(R.drawable.dishu);
arrayList.add(bookmark);
dataAdapter.notifyDataSetChanged();
}
}
注意
在下面的代码中,我在 Arraylist
的最后一个索引处设置了第二个 viewType
你需要根据你的要求设置viewType
更多信息你可以查看下面的文章
- Working with RecyclerView and multiple view types
- A RecyclerView with multiple item types
- Android RecyclerView with Different Child Layouts
- Android Pagination Tutorial—Handling Multiple View Types
- Heterogenous Layouts inside RecyclerView
- Android RecyclerView Example – Multiple ViewTypes
- How to create RecyclerView with multiple view type?
- Android Multiple row layout using RecyclerView
关于android - 从布局创建具有多个 View 的 RecyclerView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53682637/