问题
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?
Scroll the list item of dataSet index
position
to firstVisibleItem.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