如何在 ListView 中创建第 Header 部分,并滑动以使用撤消选项删除项目
How to make Section Header in ListView, and Swipe to delete a Item with Undo option
要求:
1.I 想在 Android.
中创建分段 Header 列表视图
2.That 应该滑动删除项目,像 Gmail 一样使用撤消选项 App.but Gmail 应用程序不包含 Header.
部分
3.My 应用程序应包含 Header 部分。
我尝试了下面提到的 link 滑动删除以及撤消按钮。效果很好。
问题:
编辑:1(列表视图)
1.i 找到了 在列表视图中滑动以使用撤消删除项目的代码 Link-Swipe to delete a listview item and Section Header Using Listview link-Section header in listview.
2.both 有两个不同的 Base Adapters 我遇到了一些错误,请帮我合并那个适配器或建议我添加部分的任何新方法 Header 在滑动中删除列表视图项目。
代码:
Class 用于滑动删除和列表视图中的部分 Header
ListViewActivity.class
package com.data.swipetodeletesimplelistview;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import static android.widget.Toast.LENGTH_SHORT;
public class ListViewActivity extends AppCompatActivity {
private static final int TIME_TO_AUTOMATICALLY_DISMISS_ITEM = 3000;
/*For Section header*/
ListView mListView;
ArrayList<String> mArrayList = new ArrayList<String>();
SectionedAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_view);
init((ListView) findViewById(R.id.list_view));
/*For Section Header Starts Here*/
mListView = (ListView) findViewById(R.id.list_view);
adapter = new SectionedAdapter() {
@Override
protected View getHeaderView(String caption, int index, View convertView, ViewGroup parent) {
convertView = getLayoutInflater().inflate(R.layout.section_header, null);
TextView header = (TextView) convertView.findViewById(R.id.header);
header.setText(caption);
return convertView;
}
};
for (int i = 0; i < 5; i++)
{
mArrayList.add("Item " + i);
MyAdapter myAdapter = new MyAdapter();
adapter.addSection("Header " + i, myAdapter);
}
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
Toast.makeText(getApplicationContext(), arg0.getAdapter().getItem(position).toString(), Toast.LENGTH_LONG).show();
}
});
mListView.setAdapter(adapter);
/*For Section Header Ends Here*/
}
/*FOr Swipe to Delete a item Starts Here*/
private void init(ListView listView)
{
final MyBaseAdapter adapter = new MyBaseAdapter();
listView.setAdapter(adapter);
final SwipeToDismissTouchListener<ListViewAdapter> touchListener =
new SwipeToDismissTouchListener<>(
new ListViewAdapter(listView),
new SwipeToDismissTouchListener.DismissCallbacks<ListViewAdapter>() {
@Override
public boolean canDismiss(int position) {
return true;
}
@Override
public void onPendingDismiss(ListViewAdapter recyclerView, int position) {
}
@Override
public void onDismiss(ListViewAdapter view, int position) {
adapter.remove(position);
}
});
touchListener.setDismissDelay(TIME_TO_AUTOMATICALLY_DISMISS_ITEM);
listView.setOnTouchListener(touchListener);
// Setting this scroll listener is required to ensure that during ListView scrolling,
// we don't look for swipes.
listView.setOnScrollListener((AbsListView.OnScrollListener) touchListener.makeScrollListener());
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (touchListener.existPendingDismisses()) {
touchListener.undoPendingDismiss();
} else {
Toast.makeText(ListViewActivity.this, "Position " + position, LENGTH_SHORT).show();
}
}
});
}
/*FOr Swipe to Delete*/
static class MyBaseAdapter extends BaseAdapter
{
private static final int SIZE = 100;
private final List<String> mDataSet = new ArrayList<>();
MyBaseAdapter() {
for (int i = 0; i < SIZE; i++)
mDataSet.add(i, "This is row number " + i);
}
@Override
public int getCount() {
return mDataSet.size();
}
@Override
public String getItem(int position) {
return mDataSet.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
public void remove(int position) {
mDataSet.remove(position);
notifyDataSetChanged();
}
static class ViewHolder {
TextView dataTextView;
ViewHolder(View view) {
dataTextView = (TextView) view.findViewById(R.id.txt_data);
view.setTag(this);
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = convertView == null
? new ViewHolder(convertView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false)) : (ViewHolder) convertView.getTag();
viewHolder.dataTextView.setText(mDataSet.get(position));
return convertView;
}
}
/*FOr Swipe to Delete a item Ends Here*/
/*For adding Section header*/
class MyAdapter extends BaseAdapter
{
public int getCount()
{
return mArrayList.size();
}
public Object getItem(int position)
{
return mArrayList.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
convertView = (TextView) getLayoutInflater().inflate(R.layout.section_item, null);
TextView item = (TextView) convertView.findViewById(R.id.item);
item.setText(mArrayList.get(position));
return convertView;
}
}
}
您基本上希望列表中有两种类型的行。
- 将具有滑动删除功能的项目。
- Header 没有滑动功能。
通过膨胀两种不同类型的布局来创建 recyclerView 或 listView。
检查 How to create RecyclerView with multiple view type?
编辑:滑动删除、撤消和分段列表适配器问题
正如@MadScientist 所说,列表或recyclerView 应该只有一个Adapter。
按照以下步骤实现您的要求:
- 创建一个 Recycler 视图以显示分段 header 和项目。
- 实现滑动以删除现有列表的功能。
- 对现有列表实施撤消功能。
请参阅下面的 RecyclerAdapter 示例代码,了解分段 header 和撤消功能:
public class SectionedRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TYPE_HEADER = 0;
private static final int TYPE_ITEM = 1;
private List<SectionedItem> sectionedItemList;
private List<SectionedItem> itemsPendingRemoval;
private Context context;
private static final int PENDING_REMOVAL_TIMEOUT = 3000;
private Handler handler = new Handler();
private HashMap<SectionedItem, Runnable> pendingRunnables = new HashMap<>();
public SectionedRecyclerAdapter(List<SectionedItem> itemList, Context context) {
this.sectionedItemList = itemList;
this.context = context;
itemsPendingRemoval = new ArrayList<>();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_ITEM) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_item, parent, false);
return new SectionedItemViewHolder(view);
} else if (viewType == TYPE_HEADER) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_header, parent, false);
return new SectionedHeaderViewHolder(view);
}
throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly");
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, final int position) {
if (viewHolder instanceof SectionedItemViewHolder) {
final SectionedItem data = sectionedItemList.get(position);
if (itemsPendingRemoval.contains(data)) {
((SectionedItemViewHolder) viewHolder).itemLayout.setVisibility(View.GONE);
((SectionedItemViewHolder) viewHolder).undoLayout.setVisibility(View.VISIBLE);
((SectionedItemViewHolder) viewHolder).undobutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
undoOpt(data);
}
});
} else {
((SectionedItemViewHolder) viewHolder).itemLayout.setVisibility(View.VISIBLE);
((SectionedItemViewHolder) viewHolder).undoLayout.setVisibility(View.GONE);
((SectionedItemViewHolder) viewHolder).itemName.setText(sectionedItemList.get(position).itemName);
}
}
if (viewHolder instanceof SectionedHeaderViewHolder) {
((SectionedHeaderViewHolder) viewHolder).headerTitle.setText(sectionedItemList.get(position).itemName);
}
}
@Override
public int getItemCount() {
return sectionedItemList.size();
}
@Override
public int getItemViewType(int position) {
if (isPositionHeader(position)) {
return TYPE_HEADER;
}
return TYPE_ITEM;
}
private boolean isPositionHeader(int position) {
return sectionedItemList.get(position).isHeader;
}
private void undoOpt(SectionedItem customer) {
Runnable pendingRemovalRunnable = pendingRunnables.get(customer);
pendingRunnables.remove(customer);
if (pendingRemovalRunnable != null)
handler.removeCallbacks(pendingRemovalRunnable);
itemsPendingRemoval.remove(customer);
// this will rebind the row in "normal" state
notifyItemChanged(sectionedItemList.indexOf(customer));
}
public void pendingRemoval(int position) {
final SectionedItem data = sectionedItemList.get(position);
if (!itemsPendingRemoval.contains(data) && !data.isHeader) {
itemsPendingRemoval.add(data);
// this will redraw row in "undo" state
notifyItemChanged(position);
// let's create, store and post a runnable to remove the data
Runnable pendingRemovalRunnable = new Runnable() {
@Override
public void run() {
remove(sectionedItemList.indexOf(data));
}
};
handler.postDelayed(pendingRemovalRunnable, PENDING_REMOVAL_TIMEOUT);
pendingRunnables.put(data, pendingRemovalRunnable);
}
}
public void remove(int position) {
SectionedItem data = sectionedItemList.get(position);
if (itemsPendingRemoval.contains(data)) {
itemsPendingRemoval.remove(data);
}
if (sectionedItemList.contains(data)) {
sectionedItemList.remove(position);
notifyItemRemoved(position);
}
}
private void removeItemPermanently(int position) {
sectionedItemList.get(position).isSoftDeleted = false;
sectionedItemList.remove(position);
notifyItemRemoved(position);
}
public boolean isPendingRemoval(int position) {
SectionedItem data = sectionedItemList.get(position);
return (itemsPendingRemoval.contains(data) || data.isHeader);
}
}
我用过link as reference to implement undo bar
添加 SwipeUtil.java class,因为它来自上面的 link 并更新您的 Activity class,如下所示:
将此功能添加到您的 Activity class
private void setSwipeForRecyclerView() {
SwipeUtils swipeHelper = new SwipeUtils(0, ItemTouchHelper.LEFT, ActivityB.this) {
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int swipedPosition = viewHolder.getAdapterPosition();
SectionedRecyclerAdapter adapter = (SectionedRecyclerAdapter) sectionedList.getAdapter();
adapter.pendingRemoval(swipedPosition);
}
@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int position = viewHolder.getAdapterPosition();
SectionedRecyclerAdapter adapter = (SectionedRecyclerAdapter) sectionedList.getAdapter();
if (adapter.isPendingRemoval(position)) {
return 0;
}
return super.getSwipeDirs(recyclerView, viewHolder);
}
};
ItemTouchHelper mItemTouchHelper = new ItemTouchHelper(swipeHelper);
mItemTouchHelper.attachToRecyclerView(sectionedList);
//set swipe label
swipeHelper.setLeftSwipeLable("Deleted");
//set swipe background-Color
//swipeHelper.setLeftcolorCode(ContextCompat.getColor((), R.color.swipebg));
}
并使用以下代码创建列表:
sectionedList = (RecyclerView)findViewById(R.id.sectioned_list);
RecyclerView.LayoutManager layoutManager= new LinearLayoutManager(this);
sectionedList.setLayoutManager(layoutManager);
final SectionedRecyclerAdapter sectionedRecyclerAdapter = new SectionedRecyclerAdapter(itemList, this);
sectionedList.setAdapter(sectionedRecyclerAdapter);
setSwipeForRecyclerView();
编辑 2:ViewHolders
public class SectionedItemViewHolder extends RecyclerView.ViewHolder{
public TextView itemName;
public TextView undobutton;
public View itemLayout;
public View undoLayout;
public SectionedItemViewHolder(View itemView) {
super(itemView);
itemName = (TextView)itemView.findViewById(R.id.item_title);
undobutton = (TextView) itemView.findViewById(R.id.txt_undo);
itemLayout = itemView.findViewById(R.id.item_layout);
undoLayout = itemView.findViewById(R.id.undo_layout);
}
}
public class SectionedHeaderViewHolder extends RecyclerView.ViewHolder{
public TextView headerTitle;
public SectionedHeaderViewHolder(View itemView) {
super(itemView);
headerTitle = (TextView)itemView.findViewById(R.id.header_title);
}
}
请使用此 link 在 android 中实现部分回收视图
http://android-pratap.blogspot.in/2015/12/sectioned-recyclerview-in-android_1.html
没有得到太多的问题,但如果需要的是这个
Header view not swipe-able but content view swipe-able and an undo bar there
then,
您不需要 2 个适配器,
只需一个 RecyclerView 适配器即可,具有两种不同的视图类型,如回答者:@nnn
但是在您的 SimpleItemCallback 实现中,通过执行以下操作修改您不需要回调的 RecyclerView
位置:
ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT) {
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
// check for the position you do not want the ItemTouchHelper to work
//and make it return 0;
if (viewHolder.getAdapterPosition() == 0)
return 0;
else
return super.getSwipeDirs(recyclerView, viewHolder);
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
// perform delete operation and undo bar operation here.
}
};
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleCallback);
itemTouchHelper.attachToRecyclerView(recyclerView);
仅供参考:一个很好的 undobar 库:com.cocosw:undobar:1.+@aar
RecyclerView 适配器代码框架:
public class Adapter_HeaderView extends RecyclerView.Adapter<Adapter_HeaderView.ViewHolder> {
private final int VIEW_TYPE_HEADER = 1, VIEW_TYPE_CONTENT = 2;
private Context context;
private List<Object> list;
// private int meanPercentage;
public Adapter_HeaderView(Context context, List<Object> list) {
this.context = context;
this.list = list;
// this.meanPercentage =meanPercentage;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
int layoutID;
switch (viewType) {
case VIEW_TYPE_CONTENT:
// content row layout
layoutID = R.layout.row_list;
break;
case VIEW_TYPE_HEADER:
// header row layout
layoutID = R.layout.row_list_header;
break;
default:
layoutID = R.layout.row_list;
break;
}
return new ViewHolder(LayoutInflater.from(context).inflate(layoutID, parent, false));
}
// override the getItemViewType to return position based on position
@Override
public int getItemViewType(int position) {
if (position == 0) {
return VIEW_TYPE_HEADER;
} else
return VIEW_TYPE_CONTENT;
}
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
if (getItemViewType(position) != VIEW_TYPE_HEADER) {
// load content layout here
// access all items of list as list.get(position-1); as dummy item added as the first element
} else {
// load header layout components here.
}
}
@Override
public int getItemCount() {
// add a dummy item in item count which will be the recycler view header.
return list.size() + 1;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
}
}
}
要求:
1.I 想在 Android.
中创建分段 Header 列表视图2.That 应该滑动删除项目,像 Gmail 一样使用撤消选项 App.but Gmail 应用程序不包含 Header.
部分3.My 应用程序应包含 Header 部分。
我尝试了下面提到的 link 滑动删除以及撤消按钮。效果很好。
问题:
编辑:1(列表视图)
1.i 找到了 在列表视图中滑动以使用撤消删除项目的代码 Link-Swipe to delete a listview item and Section Header Using Listview link-Section header in listview.
2.both 有两个不同的 Base Adapters 我遇到了一些错误,请帮我合并那个适配器或建议我添加部分的任何新方法 Header 在滑动中删除列表视图项目。
代码: Class 用于滑动删除和列表视图中的部分 Header
ListViewActivity.class
package com.data.swipetodeletesimplelistview;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import static android.widget.Toast.LENGTH_SHORT;
public class ListViewActivity extends AppCompatActivity {
private static final int TIME_TO_AUTOMATICALLY_DISMISS_ITEM = 3000;
/*For Section header*/
ListView mListView;
ArrayList<String> mArrayList = new ArrayList<String>();
SectionedAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_view);
init((ListView) findViewById(R.id.list_view));
/*For Section Header Starts Here*/
mListView = (ListView) findViewById(R.id.list_view);
adapter = new SectionedAdapter() {
@Override
protected View getHeaderView(String caption, int index, View convertView, ViewGroup parent) {
convertView = getLayoutInflater().inflate(R.layout.section_header, null);
TextView header = (TextView) convertView.findViewById(R.id.header);
header.setText(caption);
return convertView;
}
};
for (int i = 0; i < 5; i++)
{
mArrayList.add("Item " + i);
MyAdapter myAdapter = new MyAdapter();
adapter.addSection("Header " + i, myAdapter);
}
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
Toast.makeText(getApplicationContext(), arg0.getAdapter().getItem(position).toString(), Toast.LENGTH_LONG).show();
}
});
mListView.setAdapter(adapter);
/*For Section Header Ends Here*/
}
/*FOr Swipe to Delete a item Starts Here*/
private void init(ListView listView)
{
final MyBaseAdapter adapter = new MyBaseAdapter();
listView.setAdapter(adapter);
final SwipeToDismissTouchListener<ListViewAdapter> touchListener =
new SwipeToDismissTouchListener<>(
new ListViewAdapter(listView),
new SwipeToDismissTouchListener.DismissCallbacks<ListViewAdapter>() {
@Override
public boolean canDismiss(int position) {
return true;
}
@Override
public void onPendingDismiss(ListViewAdapter recyclerView, int position) {
}
@Override
public void onDismiss(ListViewAdapter view, int position) {
adapter.remove(position);
}
});
touchListener.setDismissDelay(TIME_TO_AUTOMATICALLY_DISMISS_ITEM);
listView.setOnTouchListener(touchListener);
// Setting this scroll listener is required to ensure that during ListView scrolling,
// we don't look for swipes.
listView.setOnScrollListener((AbsListView.OnScrollListener) touchListener.makeScrollListener());
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (touchListener.existPendingDismisses()) {
touchListener.undoPendingDismiss();
} else {
Toast.makeText(ListViewActivity.this, "Position " + position, LENGTH_SHORT).show();
}
}
});
}
/*FOr Swipe to Delete*/
static class MyBaseAdapter extends BaseAdapter
{
private static final int SIZE = 100;
private final List<String> mDataSet = new ArrayList<>();
MyBaseAdapter() {
for (int i = 0; i < SIZE; i++)
mDataSet.add(i, "This is row number " + i);
}
@Override
public int getCount() {
return mDataSet.size();
}
@Override
public String getItem(int position) {
return mDataSet.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
public void remove(int position) {
mDataSet.remove(position);
notifyDataSetChanged();
}
static class ViewHolder {
TextView dataTextView;
ViewHolder(View view) {
dataTextView = (TextView) view.findViewById(R.id.txt_data);
view.setTag(this);
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = convertView == null
? new ViewHolder(convertView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false)) : (ViewHolder) convertView.getTag();
viewHolder.dataTextView.setText(mDataSet.get(position));
return convertView;
}
}
/*FOr Swipe to Delete a item Ends Here*/
/*For adding Section header*/
class MyAdapter extends BaseAdapter
{
public int getCount()
{
return mArrayList.size();
}
public Object getItem(int position)
{
return mArrayList.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
convertView = (TextView) getLayoutInflater().inflate(R.layout.section_item, null);
TextView item = (TextView) convertView.findViewById(R.id.item);
item.setText(mArrayList.get(position));
return convertView;
}
}
}
您基本上希望列表中有两种类型的行。
- 将具有滑动删除功能的项目。
- Header 没有滑动功能。
通过膨胀两种不同类型的布局来创建 recyclerView 或 listView。 检查 How to create RecyclerView with multiple view type?
编辑:滑动删除、撤消和分段列表适配器问题
正如@MadScientist 所说,列表或recyclerView 应该只有一个Adapter。 按照以下步骤实现您的要求:
- 创建一个 Recycler 视图以显示分段 header 和项目。
- 实现滑动以删除现有列表的功能。
- 对现有列表实施撤消功能。
请参阅下面的 RecyclerAdapter 示例代码,了解分段 header 和撤消功能:
public class SectionedRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TYPE_HEADER = 0;
private static final int TYPE_ITEM = 1;
private List<SectionedItem> sectionedItemList;
private List<SectionedItem> itemsPendingRemoval;
private Context context;
private static final int PENDING_REMOVAL_TIMEOUT = 3000;
private Handler handler = new Handler();
private HashMap<SectionedItem, Runnable> pendingRunnables = new HashMap<>();
public SectionedRecyclerAdapter(List<SectionedItem> itemList, Context context) {
this.sectionedItemList = itemList;
this.context = context;
itemsPendingRemoval = new ArrayList<>();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_ITEM) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_item, parent, false);
return new SectionedItemViewHolder(view);
} else if (viewType == TYPE_HEADER) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_header, parent, false);
return new SectionedHeaderViewHolder(view);
}
throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly");
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, final int position) {
if (viewHolder instanceof SectionedItemViewHolder) {
final SectionedItem data = sectionedItemList.get(position);
if (itemsPendingRemoval.contains(data)) {
((SectionedItemViewHolder) viewHolder).itemLayout.setVisibility(View.GONE);
((SectionedItemViewHolder) viewHolder).undoLayout.setVisibility(View.VISIBLE);
((SectionedItemViewHolder) viewHolder).undobutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
undoOpt(data);
}
});
} else {
((SectionedItemViewHolder) viewHolder).itemLayout.setVisibility(View.VISIBLE);
((SectionedItemViewHolder) viewHolder).undoLayout.setVisibility(View.GONE);
((SectionedItemViewHolder) viewHolder).itemName.setText(sectionedItemList.get(position).itemName);
}
}
if (viewHolder instanceof SectionedHeaderViewHolder) {
((SectionedHeaderViewHolder) viewHolder).headerTitle.setText(sectionedItemList.get(position).itemName);
}
}
@Override
public int getItemCount() {
return sectionedItemList.size();
}
@Override
public int getItemViewType(int position) {
if (isPositionHeader(position)) {
return TYPE_HEADER;
}
return TYPE_ITEM;
}
private boolean isPositionHeader(int position) {
return sectionedItemList.get(position).isHeader;
}
private void undoOpt(SectionedItem customer) {
Runnable pendingRemovalRunnable = pendingRunnables.get(customer);
pendingRunnables.remove(customer);
if (pendingRemovalRunnable != null)
handler.removeCallbacks(pendingRemovalRunnable);
itemsPendingRemoval.remove(customer);
// this will rebind the row in "normal" state
notifyItemChanged(sectionedItemList.indexOf(customer));
}
public void pendingRemoval(int position) {
final SectionedItem data = sectionedItemList.get(position);
if (!itemsPendingRemoval.contains(data) && !data.isHeader) {
itemsPendingRemoval.add(data);
// this will redraw row in "undo" state
notifyItemChanged(position);
// let's create, store and post a runnable to remove the data
Runnable pendingRemovalRunnable = new Runnable() {
@Override
public void run() {
remove(sectionedItemList.indexOf(data));
}
};
handler.postDelayed(pendingRemovalRunnable, PENDING_REMOVAL_TIMEOUT);
pendingRunnables.put(data, pendingRemovalRunnable);
}
}
public void remove(int position) {
SectionedItem data = sectionedItemList.get(position);
if (itemsPendingRemoval.contains(data)) {
itemsPendingRemoval.remove(data);
}
if (sectionedItemList.contains(data)) {
sectionedItemList.remove(position);
notifyItemRemoved(position);
}
}
private void removeItemPermanently(int position) {
sectionedItemList.get(position).isSoftDeleted = false;
sectionedItemList.remove(position);
notifyItemRemoved(position);
}
public boolean isPendingRemoval(int position) {
SectionedItem data = sectionedItemList.get(position);
return (itemsPendingRemoval.contains(data) || data.isHeader);
}
}
我用过link as reference to implement undo bar
添加 SwipeUtil.java class,因为它来自上面的 link 并更新您的 Activity class,如下所示: 将此功能添加到您的 Activity class
private void setSwipeForRecyclerView() {
SwipeUtils swipeHelper = new SwipeUtils(0, ItemTouchHelper.LEFT, ActivityB.this) {
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int swipedPosition = viewHolder.getAdapterPosition();
SectionedRecyclerAdapter adapter = (SectionedRecyclerAdapter) sectionedList.getAdapter();
adapter.pendingRemoval(swipedPosition);
}
@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int position = viewHolder.getAdapterPosition();
SectionedRecyclerAdapter adapter = (SectionedRecyclerAdapter) sectionedList.getAdapter();
if (adapter.isPendingRemoval(position)) {
return 0;
}
return super.getSwipeDirs(recyclerView, viewHolder);
}
};
ItemTouchHelper mItemTouchHelper = new ItemTouchHelper(swipeHelper);
mItemTouchHelper.attachToRecyclerView(sectionedList);
//set swipe label
swipeHelper.setLeftSwipeLable("Deleted");
//set swipe background-Color
//swipeHelper.setLeftcolorCode(ContextCompat.getColor((), R.color.swipebg));
}
并使用以下代码创建列表:
sectionedList = (RecyclerView)findViewById(R.id.sectioned_list);
RecyclerView.LayoutManager layoutManager= new LinearLayoutManager(this);
sectionedList.setLayoutManager(layoutManager);
final SectionedRecyclerAdapter sectionedRecyclerAdapter = new SectionedRecyclerAdapter(itemList, this);
sectionedList.setAdapter(sectionedRecyclerAdapter);
setSwipeForRecyclerView();
编辑 2:ViewHolders
public class SectionedItemViewHolder extends RecyclerView.ViewHolder{
public TextView itemName;
public TextView undobutton;
public View itemLayout;
public View undoLayout;
public SectionedItemViewHolder(View itemView) {
super(itemView);
itemName = (TextView)itemView.findViewById(R.id.item_title);
undobutton = (TextView) itemView.findViewById(R.id.txt_undo);
itemLayout = itemView.findViewById(R.id.item_layout);
undoLayout = itemView.findViewById(R.id.undo_layout);
}
}
public class SectionedHeaderViewHolder extends RecyclerView.ViewHolder{
public TextView headerTitle;
public SectionedHeaderViewHolder(View itemView) {
super(itemView);
headerTitle = (TextView)itemView.findViewById(R.id.header_title);
}
}
请使用此 link 在 android 中实现部分回收视图
http://android-pratap.blogspot.in/2015/12/sectioned-recyclerview-in-android_1.html
没有得到太多的问题,但如果需要的是这个
Header view not swipe-able but content view swipe-able and an undo bar there then,
您不需要 2 个适配器,
只需一个 RecyclerView 适配器即可,具有两种不同的视图类型,如回答者:@nnn
但是在您的 SimpleItemCallback 实现中,通过执行以下操作修改您不需要回调的 RecyclerView
位置:
ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT) {
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
// check for the position you do not want the ItemTouchHelper to work
//and make it return 0;
if (viewHolder.getAdapterPosition() == 0)
return 0;
else
return super.getSwipeDirs(recyclerView, viewHolder);
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
// perform delete operation and undo bar operation here.
}
};
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleCallback);
itemTouchHelper.attachToRecyclerView(recyclerView);
仅供参考:一个很好的 undobar 库:com.cocosw:undobar:1.+@aar
RecyclerView 适配器代码框架:
public class Adapter_HeaderView extends RecyclerView.Adapter<Adapter_HeaderView.ViewHolder> {
private final int VIEW_TYPE_HEADER = 1, VIEW_TYPE_CONTENT = 2;
private Context context;
private List<Object> list;
// private int meanPercentage;
public Adapter_HeaderView(Context context, List<Object> list) {
this.context = context;
this.list = list;
// this.meanPercentage =meanPercentage;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
int layoutID;
switch (viewType) {
case VIEW_TYPE_CONTENT:
// content row layout
layoutID = R.layout.row_list;
break;
case VIEW_TYPE_HEADER:
// header row layout
layoutID = R.layout.row_list_header;
break;
default:
layoutID = R.layout.row_list;
break;
}
return new ViewHolder(LayoutInflater.from(context).inflate(layoutID, parent, false));
}
// override the getItemViewType to return position based on position
@Override
public int getItemViewType(int position) {
if (position == 0) {
return VIEW_TYPE_HEADER;
} else
return VIEW_TYPE_CONTENT;
}
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
if (getItemViewType(position) != VIEW_TYPE_HEADER) {
// load content layout here
// access all items of list as list.get(position-1); as dummy item added as the first element
} else {
// load header layout components here.
}
}
@Override
public int getItemCount() {
// add a dummy item in item count which will be the recycler view header.
return list.size() + 1;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
}
}
}