RecyclerView插入动画中断OnClick

时间:2017-05-24 13:09:48

标签: java android animation android-recyclerview

我正在使用RecyclerView,新项目只显示在列表顶部。我想对此操作使用默认插入动画,但它会在OnClick()内打破ViewHolder方法 如果我插入了新项,OnClick()将使用前一项ArrayList中的数据。如果我使用NotifyDataSetChanged(),数据是可以的,但当然,没有动画。看起来没有调用ViewHolder.bind()方法存在问题。如何在NotifyItemInserted(0)之后更新每个项目的索引?

RecyclerAdapter.java

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {

private Context context;
private LayoutInflater inflater;
private ArrayList<Song> data = new ArrayList<>();
//то, что ниже - для анимации
private static final int UNSELECTED = -1;
private RecyclerView recyclerView;
private int selectedItem = UNSELECTED;

public RecyclerAdapter(Context context, ArrayList<Song> data, RecyclerView recyclerView) {
    this.context = context;
    inflater = LayoutInflater.from(context);
    this.data = data;
    this.recyclerView = recyclerView;
}

public void insert(Song song)
{
    data.add(0, song);
    recyclerView.scrollToPosition(0);
    notifyItemInserted(0);
}

public void swap(ArrayList<Song> datas){
    data.clear();
    data.addAll(datas);
    notifyDataSetChanged();
}

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    TextView tv_songName;
    TextView tv_songGenreID;
    TextView tv_songUserInfo;
    ExpandableLayout expandableLayout;
    private CardView expandButton;
    private int position;
    private TextView youtubeButton;
    private TextView shareButton;

    public ViewHolder(View itemView) {
        super(itemView);
        tv_songName = (TextView) itemView.findViewById(R.id.tv_songName);
        tv_songGenreID = (TextView) itemView.findViewById(R.id.tv_songGenreID);
        tv_songUserInfo = (TextView) itemView.findViewById(R.id.tv_songUserInfo);
        youtubeButton = (TextView) itemView.findViewById(R.id.youtube_button);
        shareButton = (TextView) itemView.findViewById(R.id.share_button);
        expandableLayout = (ExpandableLayout) itemView.findViewById(R.id.expandable_layout);
        expandableLayout.setInterpolator(new OvershootInterpolator());
        expandButton = (CardView) itemView.findViewById(R.id.card_view);
        expandButton.setOnClickListener(this);
        youtubeButton.setOnClickListener(this);
        shareButton.setOnClickListener(this);
    }

    public void bind(int position) {
        this.position = position;
        Song current = data.get(position);
        StringBuilder songInfo = new StringBuilder();
        songInfo.append(context.getString(R.string.genre));
        songInfo.append(current.songGenreID);
        songInfo.append(System.getProperty("line.separator"));
        songInfo.append(context.getString(R.string.album));
        this.tv_songName.setText(current.songName);
        this.tv_songGenreID.setText(songInfo);
        this.tv_songUserInfo.setText(current.songUserInfo);
        expandButton.setSelected(false);
        expandableLayout.collapse(false);
    }


    @Override
    public void onClick(View view) {
        switch (view.getId())
        {
            case R.id.youtube_button:
                String youtubeURL = data.get(position).songName.replaceAll(" ", "%20");
                    youtubeURL = "https://www.youtube.com/results?search_query=" + youtubeURL;
                    Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(youtubeURL));
                    context.startActivity(browserIntent);
                break;
            case R.id.share_button:
                String songName = data.get(position).songName;
                Intent shareIntent = new Intent();
                shareIntent.setAction(Intent.ACTION_SEND);
                shareIntent.putExtra(Intent.EXTRA_TEXT, songName);
                shareIntent.setType("text/plain");
                context.startActivity(shareIntent);
                break;
            default:
                ViewHolder holder = (ViewHolder) recyclerView.findViewHolderForAdapterPosition(selectedItem);
                if (holder != null) {
                    holder.expandButton.setSelected(false);
                    holder.expandableLayout.collapse();
                }

                if (position == selectedItem) {
                    selectedItem = UNSELECTED;
                } else {
                    expandButton.setSelected(true);
                    expandableLayout.expand();
                    selectedItem = position;
                }
                break;
        }

    }
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v=inflater.inflate(R.layout.recycler_item, parent,false);
    return new ViewHolder(v);
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    holder.bind(position);
    setAnimation(holder.itemView, position);
}

private int lastPosition = -1;

private void setAnimation(View viewToAnimate, int position) {
    if (position > lastPosition) {
        Animation anim = AnimationUtils.loadAnimation(context, android.R.anim.fade_in);
        viewToAnimate.startAnimation(anim);
        lastPosition = position;
    }
}

@Override
public int getItemCount() {
    return data.size();
}
}

Activity.java的OnCreate()

protected void onCreate(Bundle savedInstanceState) {
    setTheme(R.style.AppTheme_NoActionBar);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_layout);
    layout = (CoordinatorLayout)findViewById(R.id.coordinator1);
    FloatingActionButton myFab = (FloatingActionButton) findViewById(R.id.floatingActionButton);
    mRecyclerView = (RecyclerViewEmptySupport) findViewById(R.id.my_recycler_view);
    mRecyclerView.setEmptyView(findViewById(R.id.list_empty));
    myFab.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            FragmentManager fm = getSupportFragmentManager();
            AddSongDialogFragment addSongDialogFragment = new AddSongDialogFragment();
            addSongDialogFragment.show(fm, "add_song");
        }
    });
    mAdapter = new RecyclerAdapter(MainActivity.this, data, mRecyclerView);
    mLayoutManager = new LinearLayoutManager(MainActivity.this);
    mRecyclerView.setAdapter(mAdapter);
    mRecyclerView.setHasFixedSize(true);
    mRecyclerView.setLayoutManager(mLayoutManager);
    dbHelper = new DBHelper(this);
    mAdapter.swap(dbHelper.readFromDB());
    RecyclerView.ItemAnimator itemAnimator = new DefaultItemAnimator();
    itemAnimator.setAddDuration(700);
    itemAnimator.setRemoveDuration(1000);
    mRecyclerView.setItemAnimator(itemAnimator);
}

2 个答案:

答案 0 :(得分:2)

使用getAdapterPosition()从您的VIewHolder获取商品的正确位置。这样,在从RecyclerView移动/删除项目后,位置不会混淆。

注意:如果用户在动画期间点击空白区域getAdapterPosition()可能会返回-1:请确保处理该案例。

祝你好运

答案 1 :(得分:1)

添加新项目后,您可以使用notifyItemRangeChanged(position, data.size());通知其他项目。

如果您使用swap() notifyItemRemoved()notifyItemInserted()而非notifyItemMoved()功能,也可以为notifyDataSetChanged()功能设置动画。您只需要检查新列表是否包含旧列表的项目。