我有一个带有TextView文本框和十字按钮ImageView的RecyclerView。我在recyclerview外面有一个按钮,使得十字按钮ImageView可见/消失。
我想要从recylerview中移除一个项目,当该项目交叉按钮ImageView被按下时。
我的适配器:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener, View.OnLongClickListener {
private ArrayList<String> mDataset;
private static Context sContext;
public MyAdapter(Context context, ArrayList<String> myDataset) {
mDataset = myDataset;
sContext = context;
}
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_text_view, parent, false);
ViewHolder holder = new ViewHolder(v);
holder.mNameTextView.setOnClickListener(MyAdapter.this);
holder.mNameTextView.setOnLongClickListener(MyAdapter.this);
holder.mNameTextView.setTag(holder);
return holder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mNameTextView.setText(mDataset.get(position));
}
@Override
public int getItemCount() {
return mDataset.size();
}
@Override
public void onClick(View view) {
ViewHolder holder = (ViewHolder) view.getTag();
if (view.getId() == holder.mNameTextView.getId()) {
Toast.makeText(sContext, holder.mNameTextView.getText(), Toast.LENGTH_SHORT).show();
}
}
@Override
public boolean onLongClick(View view) {
ViewHolder holder = (ViewHolder) view.getTag();
if (view.getId() == holder.mNameTextView.getId()) {
mDataset.remove(holder.getPosition());
notifyDataSetChanged();
Toast.makeText(sContext, "Item " + holder.mNameTextView.getText() + " has been removed from list",
Toast.LENGTH_SHORT).show();
}
return false;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mNumberRowTextView;
public TextView mNameTextView;
public ViewHolder(View v) {
super(v);
mNameTextView = (TextView) v.findViewById(R.id.nameTextView);
}
}
}
我的布局是:
<?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="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:id="@+id/layout">
<TextView
android:id="@+id/nameTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:padding="5dp"
android:background="@drawable/greyline"/>
<ImageView
android:id="@+id/crossButton"
android:layout_width="16dp"
android:layout_height="16dp"
android:visibility="gone"
android:layout_marginLeft="50dp"
android:src="@drawable/cross" />
</LinearLayout>
我怎样才能获得像onClick这样的东西为我的crossButton ImageView工作?有没有更好的办法?也许更改整个项目onclick到删除项目? recyclerview显示需要编辑的位置列表。关于最佳实施的任何技术建议或意见/建议都将受到高度赞赏。
答案 0 :(得分:214)
我做了类似的事情。
在MyAdapter
:
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public CardView mCardView;
public TextView mTextViewTitle;
public TextView mTextViewContent;
public ImageView mImageViewContentPic;
public ImageView imgViewRemoveIcon;
public ViewHolder(View v) {
super(v);
mCardView = (CardView) v.findViewById(R.id.card_view);
mTextViewTitle = (TextView) v.findViewById(R.id.item_title);
mTextViewContent = (TextView) v.findViewById(R.id.item_content);
mImageViewContentPic = (ImageView) v.findViewById(R.id.item_content_pic);
//......
imgViewRemoveIcon = (ImageView) v.findViewById(R.id.remove_icon);
mTextViewContent.setOnClickListener(this);
imgViewRemoveIcon.setOnClickListener(this);
v.setOnClickListener(this);
mTextViewContent.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
if (mItemClickListener != null) {
mItemClickListener.onItemClick(view, getPosition());
}
return false;
}
});
}
@Override
public void onClick(View v) {
//Log.d("View: ", v.toString());
//Toast.makeText(v.getContext(), mTextViewTitle.getText() + " position = " + getPosition(), Toast.LENGTH_SHORT).show();
if(v.equals(imgViewRemoveIcon)){
removeAt(getPosition());
}else if (mItemClickListener != null) {
mItemClickListener.onItemClick(v, getPosition());
}
}
}
public void setOnItemClickListener(final OnItemClickListener mItemClickListener) {
this.mItemClickListener = mItemClickListener;
}
public void removeAt(int position) {
mDataset.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mDataSet.size());
}
希望这有帮助。
修改强>
getPosition()
现已弃用,请改用getAdapterPosition()
。
答案 1 :(得分:42)
首先,应该从列表中删除项目!
mDataSet.remove(getAdapterPosition());
然后:
notifyItemRemoved(getAdapterPosition());
notifyItemRangeChanged(getAdapterPosition(),mDataSet.size());
答案 2 :(得分:18)
如果仍未删除项目,则使用此魔术方法:)
private void deleteItem(int position) {
mDataSet.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mDataSet.size());
holder.itemView.setVisibility(View.GONE);
}
答案 3 :(得分:5)
Actually with the previously mentioned code (That you can find here below), all RecyclerView childs are animated when a single item is removed and it's not a responsive solution at all, also because it has some potential hidden issues
public void remove(int position) {
dataset.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mDataSet.size());
}
Instead, the following snippet will play the animation just on the child that is being removed, and from my part it stopped throwing IndexOutOfBoundException
s, marked by the debugger as "data inconsistency"
void remove(int position) {
dataset.removeAt(position);
notifyItemChanged(position);
notifyItemRangeRemoved(position, 1);
}
If we dig into RecyclerView
class we can find a pice of javadoc that has the explanation, indeed as second parameter we have to pass the number of items that are removed from the dataset, not the total number of items
/**
* Notify any registered observers that the <code>itemCount</code> items previously
* located at <code>positionStart</code> have been removed from the data set. The items
* previously located at and after <code>positionStart + itemCount</code> may now be found
* at <code>oldPosition - itemCount</code>.
*
* <p>This is a structural change event. Representations of other existing items in the data
* set are still considered up to date and will not be rebound, though their positions
* may be altered.</p>
*
* @param positionStart Previous position of the first item that was removed
* @param itemCount Number of items removed from the data set
*/
public final void notifyItemRangeRemoved(int positionStart, int itemCount) {
mObservable.notifyItemRangeRemoved(positionStart, itemCount);
}
答案 4 :(得分:5)
可能是一个重复的答案,但对我来说非常有用。您可以在RecyclerView.Adapter<RecyclerView.ViewHolder>
中实施以下方法
并且可以根据您的要求使用此方法,我希望它能为您服务
public void removeItem(@NonNull Object object) {
mDataSetList.remove(object);
notifyDataSetChanged();
}
答案 5 :(得分:4)
我尝试了上述所有答案,但是在recyclerview中插入或删除项会导致dataSet中的位置出现问题。在viewHolder中使用delete(getAdapterPosition());
结束,它可以很好地找到项目的位置。
答案 6 :(得分:3)
我遇到的问题是我从列表中删除了一个不再与适配器关联的项目,以确保您正在修改正确的适配器,您可以在适配器中实现这样的方法:
public void removeItemAtPosition(int position) {
items.remove(position);
}
并在你的片段或活动中调用它:
adapter.removeItemAtPosition(position);
答案 7 :(得分:3)
以下是一些视觉补充示例。有关添加和删除范围的示例,请参阅my fuller answer。
在索引2
添加“Pig”。
String item = "Pig";
int insertIndex = 2;
data.add(insertIndex, item);
adapter.notifyItemInserted(insertIndex);
从列表中删除“Pig”。
int removeIndex = 2;
data.remove(removeIndex);
adapter.notifyItemRemoved(removeIndex);
答案 8 :(得分:2)
您必须从数据的arrayList中删除此项
myDataset.remove(holder.getAdapterPosition());
notifyItemRemoved(holder.getAdapterPosition());
notifyItemRangeChanged(holder.getAdapterPosition(), getItemCount());
答案 9 :(得分:1)
String str = arrayList.get(position);
arrayList.remove(str);
MyAdapter.this.notifyDataSetChanged();
答案 10 :(得分:1)
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private Context context;
private List<cardview_widgets> list;
public MyAdapter(Context context, List<cardview_widgets> list) {
this.context = context;
this.list = list;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(this.context).inflate(R.layout.fragment1_one_item,
viewGroup, false);
return new MyViewHolder(view);
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
TextView txt_value;
TextView txt_category;
ImageView img_inorex;
ImageView img_category;
TextView txt_date;
public MyViewHolder(@NonNull View itemView) {
super(itemView);
txt_value = itemView.findViewById(R.id.id_values);
txt_category = itemView.findViewById(R.id.id_category);
img_inorex = itemView.findViewById(R.id.id_inorex);
img_category = itemView.findViewById(R.id.id_imgcategory);
txt_date = itemView.findViewById(R.id.id_date);
}
}
@NonNull
@Override
public void onBindViewHolder(@NonNull final MyViewHolder myViewHolder, int i) {
myViewHolder.txt_value.setText(String.valueOf(list.get(i).getValuee()));
myViewHolder.txt_category.setText(list.get(i).getCategory());
myViewHolder.img_inorex.setBackgroundColor(list.get(i).getImg_inorex());
myViewHolder.img_category.setImageResource(list.get(i).getImg_category());
myViewHolder.txt_date.setText(list.get(i).getDate());
myViewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
list.remove(myViewHolder.getAdapterPosition());
notifyDataSetChanged();
return false;
}
});
}
@Override
public int getItemCount() {
return list.size();
}}
我希望对您有帮助。
答案 11 :(得分:0)
如果你想删除项目,你应该这样做: 首先删除项目:
phones.remove(position);
在下一步中,您应该通过此代码通知您的Recycler适配器您删除了一个项目:
notifyItemRemoved(position);
notifyItemRangeChanged(position, phones.size());
但如果您更改项目,请执行以下操作: 首先更改对象的参数,如下所示:
Service s = services.get(position);
s.done = "Cancel service";
services.set(position,s);
或像这样新:
Service s = new Service();
services.set(position,s);
然后通过此代码通知您的Recycler适配器修改项目:
notifyItemChanged(position);
notifyItemRangeChanged(position, services.size());
希望能帮到你。
答案 12 :(得分:0)
//////// set the position
holder.cancel.setTag(position);
///// click to remove an item from recycler view and an array list
holder.cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int positionToRemove = (int)view.getTag(); //get the position of the view to delete stored in the tag
mDataset.remove(positionToRemove);
notifyDataSetChanged();
}
});
答案 13 :(得分:0)
使接口进入自定义适配器类并在回收器视图上处理click事件。
onItemClickListner onItemClickListner;
public void setOnItemClickListner(CommentsAdapter.onItemClickListner onItemClickListner) {
this.onItemClickListner = onItemClickListner;
}
public interface onItemClickListner {
void onClick(Contact contact);//pass your object types.
}
@Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
// below code handle click event on recycler view item.
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onItemClickListner.onClick(mContectList.get(position));
}
});
}
在定义适配器之后,绑定到下面的代码称为的回收器视图中。
adapter.setOnItemClickListner(new CommentsAdapter.onItemClickListner() {
@Override
public void onClick(Contact contact) {
contectList.remove(contectList.get(contectList.indexOf(contact)));
adapter.notifyDataSetChanged();
}
});
}
答案 14 :(得分:0)
如果有人想在Main类而不是Adapter类中实现类似的东西,则可以使用`public void removeAt(int position){ peopleListUser.remove(position);
friendsListRecycler.getAdapter().notifyItemRemoved(position);
friendsListRecycler.getAdapter().notifyItemRangeChanged(position, peopleListUser.size());
}`
其中friendsListRecycler是适配器名称
答案 15 :(得分:0)
方法onBindViewHolder
编写此代码
holder.remove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Cursor del=dbAdapter.ExecuteQ("delete from TblItem where Id="+values.get(position).getId());
values.remove(position);
notifyDataSetChanged();
}
});
答案 16 :(得分:0)
如果您想知道像我一样,在哪里可以找到方法getadapterposition()中的适配器位置;它在viewholder对象中。因此,您必须像这样放置代码
mdataset.remove(holder.getadapterposition());
答案 17 :(得分:0)
在活动中:
mAdapter.updateAt(pos, text, completed);
mAdapter.removeAt(pos);
在您的适配器中:
void removeAt(int position) {
list.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, list.size());
}
void updateAt(int position, String text, Boolean completed) {
TodoEntity todoEntity = list.get(position);
todoEntity.setText(text);
todoEntity.setCompleted(completed);
notifyItemChanged(position);
}