RecyclerView scroll to position and get that view

核能气质少年 提交于 2019-12-13 01:28:35

问题


I want to auto scroll a list item to top (firstVisible item) in my recycler view and get the view at that position, so I can highlight it, from my fragment.

So, this is the gist of my fragment code :

    private void activateNewListItem(int position) {

       mLayoutManager().scrollToPositionWithOffset(position, 0);
       RecyclerView.ViewHolder viewHolder = mRecyclerView.findViewHolderForLayoutPosition(position);

       View view = viewHolder.getItemView();
       view.setBackgroundColor(getResources().getColor(R.color.esr_light_grey));
}

If position is 1,2,3,4 etc, mRecyclerView.findViewHolderForPosition(position) returns a valid ViewHolder, because I guess RecyclerView has drawn ViewHolders for those indexes in dataSet.

However, if I pass in position as say, 25, mRecyclerView.findViewHolderForPosition(position) returns null, because I assume, it hasn't been drawn yet, even thoughI called mLayoutManager.scrollToPositionWithOffset(position, 0) above it.

What can I do to achieve these two things?

  1. Scroll the list item of dataSet index position to firstVisibleItem.

  2. Get the View or ViewHolder object of that listItem, so I can change the background or whatever.


回答1:


Instead of accessing ViewHolder somewhere else, go for a custom selector background in your adapters item layout xml file instead, track the position in your adapter as selected position and call notifydatasetchanged()/notifyItemRangeChanged() to highlight it once the scroll is complete. You already have the scrollToPosition() method, have a scroll listener to track the scroll state.

Example for selector background : item_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android=
      "http://schemas.android.com/apk/res/android">
   <item android:state_activated="true"
         android:drawable="@color/primary_dark" />
   <item android:drawable="@android:color/transparent" />
</selector>

Set it as background to your item xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container_list_item"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/item_selector">
    <--- Your layout items here --->
</RelativeLayout>

Your adapter code :

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

    private final String[] list;
    private int lastCheckedPosition = -1;

    public SampleAdapter(String[] list) {
        this.list = list;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = View.inflate(parent.getContext(), R.layout.sample_layout, null);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.choiceName.setText(list[position]);
        holder.containerView.setSelected(position == lastCheckedPosition);
    }

    @Override
    public int getItemCount() {
        return list.length;
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        @Bind(R.id.choice_name)
        TextView choiceName;
        @Bind(R.id. container_list_item)
        View containerView;

        public ViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    lastCheckedPosition = getAdapterPosition();
                    notifyItemRangeChanged(0, list.length);

                }
            });
        }
    }
}

To scroll to any position :

recyclerview.scrollToPosition(position)

Let me know if this helps.




回答2:


It takes some seconds to update the ViewHolder Information. Just scroll and delay the mRecyclerView.findViewHolderForLayoutPosition call for some milliseconds (100ms sounds reasonable)




回答3:


Put this code in your fragment where you are going to scroll to the first RecyclerView item:

RecyclerView.ViewHolder holder = mRecyclerView
                .findViewHolderForAdapterPosition(0);
while (holder == null) {
    int firstVisiblePosition = mLayoutManager()
                .findFirstCompletelyVisibleItemPosition();
    RecyclerView.ViewHolder firstVisibleHolder = mRecyclerView
                .findViewHolderForAdapterPosition(firstVisiblePosition);

    View v = firstVisibleHolder.getItemView();
    if (v != null) mRecyclerView.scrollBy(0, (int) v.getY());
    else break;
    holder = mRecyclerView.findViewHolderForAdapterPosition(0);
}

View view = null;
if (holder != null) view = holder.getItemView();
if (view != null) mRecyclerView.scrollBy(0, (int) view.getY());


来源:https://stackoverflow.com/questions/33442820/recyclerview-scroll-to-position-and-get-that-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!