Calling a function in Viewholder when item selected using SnapHelper - android

I have a horizontal Recycler view implemented with SnapHelper to get a carousal effect. In my ViewHolder I have a function to animate the views inside Recycler item. So whenever an item is scrolled to center (selected) in SnapHelper I need to start the animation. I have tried following code but its not working. Sometimes I am getting viewholder as null.
widgetScrollView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(final RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_SETTLING) {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
int pos = ((LinearLayoutManager) widgetScrollView.getLayoutManager()).findFirstCompletelyVisibleItemPosition();
ResultTallyAdapter.ViewHolder viewHolder = (ResultTallyAdapter.ViewHolder) recyclerView.findViewHolderForAdapterPosition(pos);
viewHolder.startAnimation(MainActivity.this, pos);
}
}, 1000);
}
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});

I was trying same thing like you. But code is different. I use SnapHelper to find current view and get position from this view and start operation on adapter by this position. You can get idea following code, may help you
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(#NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
synchronized (this) {
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
//calculatePositionAndScroll(recyclerView);
View view = snapHelper.findSnapView(recyclerView.getLayoutManager());
if (view != null) {
int pos = recyclerView.getLayoutManager().getPosition(view);
Log.d("RecyclerViewTest", "position: " + pos + " item: " + itemList.get(pos).getName());
makeSelectedItem(pos); // do your stuff on this view
// adapter.notifyDataSetChanged();
}
}
}
}
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});

Related

On insertion of an element to recyclerview, how to scroll to the bottom?

I am practicing to build a chat app. When I insert an item to the recyclerview, I need it to scroll to the bottom. My recyclerview code for now looks like this. I tried adding an onScroll listener and that approach was wrong. Thanks!
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
((SimpleItemAnimator) binding.chatRecyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
linearLayoutManager.setReverseLayout(true);
binding.chatRecyclerView.setLayoutManager(linearLayoutManager);
binding.chatRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int firstVisiblePosition = linearLayoutManager.findLastVisibleItemPosition();
Log.i(TAG, "onScrolled: " + firstVisiblePosition);
if (dy < 0) {
binding.chatDate.setVisibility(View.VISIBLE);
binding.chatDate.setText(sfdMainDate.format(new Date(chatadapter.getItem(firstVisiblePosition).getTimestamp())));
} else if (dy > 0) {
binding.chatDate.setVisibility(View.GONE);
}
}
});```
Add the data observer to your adapter and override onItemRangeInserted.
adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
#Override
public void onItemRangeInserted(int positionStart, int itemCount) {
binding.chatRecyclerView.smoothScrollToPosition(0);
}
});

How to use scroll listener in onBindViewHolder in Adapter of a RecyclerView?

I have a long itemView in RecyclerView adapter and what I want is a listener to check if a view in itemView is visible or not, while scrolling recyclerView.
What I need is somthing like "onRecyclerViewScrolled()" in this example code:
public class MyAdapter extends RecyclerView.Adapter<ViewHolder> {
#Override
public void onBindViewHolder(#NonNull final ViewHolder myViewHolder, int
position) {
onRecyclerViewScrolled() {
if (!isVisible(myViewHolder.myView)) {
//do something
}
}
}
}
public static boolean isVisible(final View view) {
if (view == null) {
return false;
}
if (!view.isShown()) {
return false;
}
final Rect actualPosition = new Rect();
view.getGlobalVisibleRect(actualPosition);
final Rect screen = new Rect(0, 0, getScreenWidth(), getScreenHeight());
return actualPosition.intersect(screen);
}
public static int getScreenWidth() {
return Resources.getSystem().getDisplayMetrics().widthPixels;
}
public static int getScreenHeight() {
return Resources.getSystem().getDisplayMetrics().heightPixels;
}
You can set addOnScrollListener on your RecyclerView to get notified when the user scrolls, and you can get the first/last visible views from LinearLayoutMangar or GridLayoutManager:
RecyclerView recycler = findViewById(R.id.recycler_view);
reycler.setAdapter(YOUR_ADAPTER);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recycler.setLayoutManager(layoutManager);
recycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//First visible item position.
int firstVisiblePosition = layoutManager.findFirstVisibleItemPosition();
//Last visible item position.
int lastVisiblePosition = layoutManager.findLastVisibleItemPosition();
/*If you really need to access your visible views,
Loop through all the visible views*/.
for (int position = firstVisiblePosition; position == lastVisiblePosition; position++) {
View lastVisibleView = layoutManager.getChildAt(firstVisiblePosition);
//do something
}
dataList.get(firstVisiblePosition);
}
});
More info from documentation RecyclerView.OnScrollListener have to functions:
onScrolled(RecyclerView recyclerView, int dx, int dy)
Callback method to be invoked when the RecyclerView has been scrolled.
onScrollStateChanged(RecyclerView recyclerView, int newState)
Callback method to be invoked when RecyclerView's scroll state changes.
Apparently, onScrolled is called when the scroll is completed.
For more info see Yigit answer`s

recyclerview add scrollListener

I have a RecyclerView with Horizontal LinearLayoutManager.
I would like to check ScrollListener.
My goal is to check these steps:
Check when RecyclerView start scroll
Check when RecyclerView end scroll
Check when RecyclerView's scroll is in center position
Here is a my RecyclerView code with LinearLayoutManager.
LinearLayoutManager horizontalManager = new LinearLayoutManager(context);
horizontalManager.setOrientation(LinearLayoutManager.HORIZONTAL);
viewHolderStory.recyclerView.setLayoutManager(horizontalManager);
viewHolderStory.recyclerView.addItemDecoration(new PaddingItemDecoration((Activity) context));
viewHolderStory.recyclerView.setHasFixedSize(true);
viewHolderStory.recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
});
viewHolderStory.recyclerView.setNestedScrollingEnabled(false);
Is any way to add validation on my addOnScrollListener method?
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if(newState==RecyclerView.SCROLL_STATE_IDLE){
/// User Stops Scroll
}
if(newState==RecyclerView.SCROLL_STATE_DRAGGING){
/// User Starts Scroll
}
}
You can find more from this.
You can compute this with computeVerticalScrollExtent() , computeVerticalScrollOffset() and computeVerticalScrollRange()
if your recyler view is horizontal, these functions have a horizontal counterpart
full code :
viewHolderStory.recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener()
{
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
int extent = recyclerView.computeVerticalScrollExtent();
int offset = recyclerView.computeVerticalScrollOffset();
int range = recyclerView.computeVerticalScrollRange();
if(offset == 0){
//fire when recycler view hit top
Log.i("myTag", "onScrolled: top");
}
else if(offset + extent == range){
//fire when recycler view hit bottom
Log.i("myTag", "onScrolled: bottom");
}
else {
//fire the rest of the time
Log.i("myTag", "onScrolled: middle");
}
}
});

Recycler View on Scroll Stop

Basically I want my recyclerview to automatically scroll to a position where the item is not half shown. Like the one in googleplay.
I have written a code
public void scrollToVisible(){
int firstVisibleItemPosition = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition();
View view = recyclerView.getLayoutManager().getChildAt(0);
if (firstVisibleItemPosition > 0 && view != null) {
int offsetTop = view.getTop();
if (firstVisibleItemPosition - 1 >= 0 && adapter.getItemCount() > 0) {
((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(firstVisibleItemPosition - 1, offsetTop);
}
}
}
The problem comes next. I dont know where to put this code. I have a vague idea to put it when the recyclerview stops on scrolling but I've been searching for quite some time now and i cant find such a method. when i put it on the onScroll some unexpected behavior comes out
You may create a CustomRecyclerView extending RecyclerView
public class CustomRecyclerView extends RecyclerView {
#Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
// check if scrolling has stopped
if (state == SCROLL_STATE_IDLE) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
// use code here
}
}
If it maybe of any help to someone:
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
Log.d("y value",String.valueOf(dy));
if (dy > 0) {
//scrolling up
} else {
// Scrolling down
}
}
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
// Do something
Log.e("SCROLL_STATE_FLING","SCROLL_STATE_FLING");
} else if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
Log.e("SCROLLTOUCH_SCROLL","SCROLL_STATE_TOUCH_SCROLL");
//slideUp(party_view);
// Do something
} else if (newState==AbsListView.OnScrollListener.SCROLL_STATE_IDLE){
// Do something
//slideDown(party_view);
Log.e("SCROLL_STATE_IDLE","SCROLL_STATE_IDLE");
}
}
});
complete example with UI synchronization
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(#NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
Handler handler = new Handler(getMainLooper());
if (newState == 0) {
handler.removeCallbacks(MainActivity.this::hideFab);
handler.postDelayed(MainActivity.this::showFab, 400);
} else {
handler.removeCallbacks(MainActivity.this::showFab);
handler.postDelayed(MainActivity.this::hideFab, 100);
}
}
});
private void hideFab() {
addFile.hide();
addText.hide();
camera.hide();
}
private void showFab() {
addFile.show();
addText.show();
camera.show();
}

How to judge the VerticalGridView has scrolled to bottom in Android?

I am developing an App for Android TV via Nexus Player. In my App, I use the VerticalGridFragment to show TV shows. For shows' number is 2000+, I want to use page loading when the VerticalGridView scrolls to its bottom.
However, I get stuck on how to judge the VerticalGridView has scrolled to bottom.
I use reflect to get the VerticalGridView,and addScrollListener() to it.Here the codes:
private void addGridScrollListener() {
try {
Class<VerticalGridFragment> VerticalGridFragmentClass = VerticalGridFragment.class;
Field verticalGridViewHolder = VerticalGridFragmentClass.getDeclaredField("mGridViewHolder");
verticalGridViewHolder.setAccessible(true);
VerticalGridPresenter.ViewHolder viewHolder = (VerticalGridPresenter.ViewHolder) verticalGridViewHolder.get(this);
VerticalGridView gridView = viewHolder.getGridView();
gridView.addOnScrollListener(scrollListener);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
private RecyclerView.OnScrollListener scrollListener = new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
};
RecyclerView doesn't has the function such as getLastVisiableItemPosition, so I can't know if the VerticalGridView has scrolled to bottom or not.
What should I do in the scrollListener ? Or is there any other solutions?
Thanks!
I found the solution:
private RecyclerView.OnScrollListener scrollListener = new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState != RecyclerView.SCROLL_STATE_IDLE) {
return;
}
//get current last child View
View lastChildView = recyclerView.getLayoutManager().getChildAt(recyclerView.getLayoutManager().getChildCount() - 1);
//get the bottom
int lastChildBottom = lastChildView.getBottom();
// get recyclerView's bottom
int recyclerBottom = recyclerView.getBottom() - recyclerView.getPaddingBottom();
//get last childview's position
int lastPosition = recyclerView.getLayoutManager().getPosition(lastChildView);
if (lastChildBottom == recyclerBottom && lastPosition == recyclerView.getLayoutManager().getItemCount() - 1) {
// yes to bottom.
}
}
};

Categories

Resources