我正在尝试通过RecyclerView和ItemTouchHelper实现“滑动删除”功能。我有一个奇怪的问题,我无法找到我的生活问题。我将物品从顶部(不是第一个)上移开,它消失了,到目前为止一切都很好。当我滚动并回来时,在上面的行中有一个人工制品。看起来那行没有绘制(或者可能是x翻译?)。视频显示了这个问题。
视频的步骤:
相关代码:(整个github示例应用here)
0
编辑:
我有一个黑客可以消除这个故障,但我仍然想知道原因,我怎么能真正解决这个问题。黑客正在调用notifyDataSetChanged(),但是在动画完成后(否则动画终止)。基本上我添加一个ItemDecorator并找出动画结束。
public class MainActivity extends AppCompatActivity {
RecyclerView mRecyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setAdapter(new TestAdapter());
setUpItemTouchHelper();
}
private void setUpItemTouchHelper() {
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
int swipedPosition = viewHolder.getAdapterPosition();
TestAdapter adapter = (TestAdapter)mRecyclerView.getAdapter();
adapter.remove(swipedPosition);
}
};
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
itemTouchHelper.attachToRecyclerView(mRecyclerView);
}
static class TestAdapter extends RecyclerView.Adapter {
List<String> items;
public TestAdapter() {
items = new ArrayList<>();
// this should give us a couple of screens worth
for (int i=1; i<= 15; i++) {
items.add("Item " + i);
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new TestViewHolder(parent);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
TestViewHolder viewHolder = (TestViewHolder)holder;
String item = items.get(position);
viewHolder.titleTextView.setText(item);
}
@Override
public int getItemCount() {
return items.size();
}
public void remove(int position) {
if (position < 0 || position >= items.size()) {
return;
}
items.remove(position);
notifyItemRemoved(position);
}
}
static class TestViewHolder extends RecyclerView.ViewHolder {
TextView titleTextView;
public TestViewHolder(ViewGroup parent) {
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.row_view, parent, false));
titleTextView = (TextView) itemView.findViewById(R.id.title_text_view);
}
}
}
答案 0 :(得分:8)
尝试在删除方法中添加notifyDataSetChanged()
public void remove(int position) {
if (position < 0 || position >= items.size()) {
return;
}
items.remove(position);
notifyItemRemoved(position);
notifyDataSetChanged();
}
notifyItemRemoved(position)
通知RecyclerView适配器已在特定位置删除适配器中的数据。
notifyDataSetChanged()
通知附加的观察者基础数据已被更改,反映数据集的任何视图都应自行刷新。
<强>更新强>
尝试在mRecyclerView.removeViewAt(position);
之前添加notifyItemRemoved(position);
这不会影响动画。
public class MainActivity extends AppCompatActivity {
RecyclerView mRecyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setAdapter(new TestAdapter());
setUpItemTouchHelper();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.menu_item_add_5_items) {
((TestAdapter)mRecyclerView.getAdapter()).addItems(5);
}
return super.onOptionsItemSelected(item);
}
private void setUpItemTouchHelper() {
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
int swipedPosition = viewHolder.getAdapterPosition();
TestAdapter adapter = (TestAdapter)mRecyclerView.getAdapter();
adapter.remove(swipedPosition);
}
};
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
itemTouchHelper.attachToRecyclerView(mRecyclerView);
}
class TestAdapter extends RecyclerView.Adapter {
List<String> items;
int lastInsertedIndex;
public TestAdapter() {
items = new ArrayList<>();
lastInsertedIndex = 15;
// this should give us a couple of screens worth
for (int i=1; i<= lastInsertedIndex; i++) {
items.add("Item " + i);
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new TestViewHolder(parent);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
TestViewHolder viewHolder = (TestViewHolder)holder;
String item = items.get(position);
viewHolder.titleTextView.setText(item);
}
@Override
public int getItemCount() {
return items.size();
}
public void addItems(int howMany){
if (howMany > 0) {
for (int i = lastInsertedIndex + 1; i <= lastInsertedIndex + howMany; i++) {
items.add("Item " + i);
notifyItemInserted(items.size() - 1);
}
lastInsertedIndex = lastInsertedIndex + howMany;
}
}
public void remove(int position) {
if (position < 0 || position >= items.size()) {
return;
}
items.remove(position);
mRecyclerView.removeViewAt(position);
notifyItemRemoved(position);
}
}
static class TestViewHolder extends RecyclerView.ViewHolder {
TextView titleTextView;
public TestViewHolder(ViewGroup parent) {
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.row_view, parent, false));
titleTextView = (TextView) itemView.findViewById(R.id.title_text_view);
}
}
}
答案 1 :(得分:3)
更新: 23.1.1修复了该错误。不要使用23.1.0。
看起来此错误是回收站视图支持库中的回归。我认为这是导致它的commit,但仍然不能100%理解这种情况,所以不要指责我。
该错误表现为com.android.support:recyclerview-v7
版本23.1.0
但不包含23.0.1
或22.2.1
我会尝试找到一个正确的位置进行举报,并将此链接发布在此答案的评论中。
答案 2 :(得分:1)
我想建议您看到该链接,因为这是实现此功能的最简单方法 Drag and swipe with RecyclerView using ItemTouchHelper
答案 3 :(得分:0)
我在滑动到重新排序时遇到了类似的问题。 RecyclerView正在留下视图的“幽灵”,只是移动到移动到该位置的视图下方。 Random给我的onItemMoved方法添加'notifyDataSetChanged()'的答案有效,但这会破坏交换动画。我在短暂的延迟后运行notifyDataSetChanged时解决了这个问题:
notifyItemMoved(position1, position2);
getActivity().getHandler().postDelayed(new Runnable() {
@Override
public void run() {
notifyDataSetChanged();
}
}, 300);
答案 4 :(得分:0)
我能够通过在recyclerview上再次设置适配器来解决此问题。从列表中删除后,只需....
RecyclerView.setAdapter(this);