我尝试在RecyclerView中添加一些滑动功能。基本上,当用户滑动项目超过某个范围并释放它时,项目滑动到最后并被删除。到目前为止,非常好。
在少量项目(小于屏幕高度)上,一切都很完美,但是项目数量越多,奇怪的行为就开始了。当一些项目在列表中间被删除时,一个项目位于屏幕顶部正上方,一个项目位于屏幕底部正下方,"消失"也留下空位。
我对此问题进行了调查。问题似乎是在删除项目视图之前更改TranslationX
。我删除项目的基本代码:
view.animate()
.translationX(view.getWidth())
.setDuration(500)
.alpha(0)
.withEndAction(new Runnable() {
@Override
public void run() {
removeItem(position);
}
});
一旦我意外地将TranslationX
值更改为小于项目宽度的数字。这表明这两个项目不会消失,而是与删除的项目具有相同的TranslationX
值。实际上,如果我没有动画删除,只需设置项目TranslationX
然后将其删除,问题仍然存在。
问题可以通过这种方式解决,但这是一个肮脏的解决方案,不能解释这种行为的本质:
view.animate()
.translationX(view.getWidth())
.setDuration(500)
.alpha(0)
.withEndAction(new Runnable() {
@Override
public void run() {
view.setTranslationX(0f); // Dirty solution
removeItem(position);
}
});
以下是问题的解决方法(如果TranslationX
小于宽度):
我使用片段和适配器创建了一个简单的项目,以消除任何可能的外部影响。
ItemsFragment.java
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
public class ItemsFragment extends Fragment implements ItemsAdapter.ItemsAdapterClickListener {
private RecyclerView mItemsList;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_items, container, false);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mItemsList = (RecyclerView) getView().findViewById(R.id.items_list);
mItemsList.setHasFixedSize(true);
mItemsList.setItemAnimator(new DefaultItemAnimator());
mItemsList.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
List<String> items = new ArrayList<>();
for (int i = 0; i < 20; i++) {
items.add("Item " + (i + 1));
}
ItemsAdapter adapter = new ItemsAdapter(items, this);
mItemsList.setAdapter(adapter);
}
@Override
public void onDestroy() {
mItemsList = null;
super.onDestroy();
}
@Override
public void onItemClicked(final int position) {
LinearLayoutManager manager = (LinearLayoutManager) mItemsList.getLayoutManager();
int first = manager.findFirstCompletelyVisibleItemPosition();
final View view = mItemsList.getChildAt(position - first + 1);
view.animate()
.translationX(view.getWidth() / 2)
.setDuration(500)
.alpha(0)
.withEndAction(new Runnable() {
@Override
public void run() {
//view.setTranslationX(0f);
removeItem(position);
}
});
//view.setTranslationX(500);
//removeItem(position);
}
public void removeItem(int position) {
ItemsAdapter adapter = (ItemsAdapter) mItemsList.getAdapter();
adapter.removeItem(position);
adapter.notifyItemRemoved(position);
}
}
ItemsAdapter.java
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
public class ItemsAdapter extends RecyclerView.Adapter<ItemsAdapter.ViewHolder> {
private List<String> mItems;
private ItemsAdapterClickListener mListener;
public ItemsAdapter(List<String> items, ItemsAdapterClickListener listener) {
this.mItems = items;
this.mListener = listener;
}
public interface ItemsAdapterClickListener {
public void onItemClicked(int position);
}
public String removeItem(int position) {
return mItems.remove(position);
}
class ViewHolder extends RecyclerView.ViewHolder {
private TextView mTitle;
public ViewHolder(View itemView) {
super(itemView);
mTitle = (TextView) itemView.findViewById(R.id.item_title);
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.items_list_item, parent, false);
final ViewHolder holder = new ViewHolder(view);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mListener != null)
mListener.onItemClicked(holder.getPosition());
}
});
return holder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mTitle.setText(mItems.get(position));
}
@Override
public int getItemCount() {
return mItems.size();
}
}
您对RecyclerView中的错误有什么解释吗?