删除项目后RecyclerView的奇怪行为

时间:2015-03-24 00:27:25

标签: android android-animation android-recyclerview

我尝试在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小于宽度): Screenshots of the problem

我使用片段和适配器创建了一个简单的项目,以消除任何可能的外部影响。

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中的错误有什么解释吗?

0 个答案:

没有答案