【发布时间】:2016-01-12 03:52:57
【问题描述】:
我正在尝试通过 RecyclerView 和 ItemTouchHelper 实现“滑动删除”功能。我有一个奇怪的问题,我一生都找不到这个问题。我从顶部(不是第一个)滑动一个项目,它消失了,到目前为止一切都很好。当我滚动并返回时,在被刷掉的项目上方的行中有一个人工制品。看起来该行未绘制(或者可能 x 已翻译?)。视频显示了问题。
视频步骤:
- 我刷掉了第 2 项
- 向下滚动到底部
- 回来
- 第 1 项不再可见
- 我再次向下滚动到底部
- 我向上滚动
- 现在一切都很好
- 同样,但从顶部开始第三个(不是第二个)项目,同样的问题
- 同样,对于第一个项目,没有问题
相关代码:(整个github示例应用here)
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);
}
}
}
编辑:
我有一个可以消除此故障的 hack,但我仍然想知道原因以及如何才能真正解决此问题。黑客正在调用 notifyDataSetChanged() 但在动画完成之后(否则动画会终止)。基本上我添加了一个 ItemDecorator 并确定动画结束了。
mRecyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
boolean running;
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
if (parent.getItemAnimator().isRunning()) {
running = true;
}
if (running == true && !parent.getItemAnimator().isRunning()) {
// first time it's not running
running = false;
parent.getAdapter().notifyDataSetChanged();
}
super.onDraw(c, parent, state);
}
});
【问题讨论】:
标签: android android-recyclerview