I want to animate appearance of only last item of a recyclerview. Every time scroll is done to end, view should be shown with animation.
Applying Item Animator animates when item is removed, added, deleted. But i did not get option to animate in on scroll.
I applied animation in onBindView, but onBindView is not always called and animation is not started. Moreover, in cases onBindView is called and user is performing slow scroll operation, animation had already started when view is actually visible to user.
What can be suitable way to apply this animation?
Thanks
Vibhor
I have tested this solution and It's working like a charm.
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
LinearLayoutManager layoutManager = LinearLayoutManager.class.cast(recyclerView.getLayoutManager());
int lastItem=adapter.getItemCount()-1;
tryAnimation(layoutManager.findViewByPosition(lastItem));
}
});
public void tryAnimation(View view) {
Animation animation = AnimationUtils.loadAnimation(this, android.R.anim.slide_in_left);
if (view != null)
view.startAnimation(animation);
}
this solution can be optimized by taking advantage of dy
I am working on the Simple demo of Horizontal RecyclerView.
I want to display scrollbar along with the recyclerview. So I have added android:scrollbars="horizontal" and android:scrollbarSize="5dp" in XML.
I am able to get the Scrollbar but it is showing on the bottom. What I want to achieve is to show it on Top. I have found some questions like this but none of them are for horizontal recyclerView + top side scrollbar.
Here is the code which I have tried so far:
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:isScrollContainer="false"
android:orientation="horizontal"
android:scrollbars="horizontal"
android:scrollbarSize="5dp"
android:visibility="visible" />
Thanks!
I have searched couple of hours but not found anything as per your requirement. But there are some trikes or do with some hacky code we can get output as per your requirement.
Set your RecyclerView as below in your xml file.
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbarAlwaysDrawHorizontalTrack="true"
android:scrollbarSize="10dp"
android:scrollbarStyle="outsideInset"
android:scrollbarThumbVertical="#color/black"
android:scrollbars="horizontal"
android:verticalScrollbarPosition="right"/>
Put your data in revers order in your List or ArrayList because we need to rotate the recyclerviews so when we rotate it then our data will be display as an ASEC order.
//call this method for set recyclerview
private void setRecyclerView()
{
//Please make sure with your item that it will be inserted in revers order then an then it will be working
ArrayList<String> itemList = new ArrayList<>();
for (int i = 50; i > 0; i--){
itemList.add("item " + i);
}
ContainerAdapter adapterMessage = new ContainerAdapter(MainActivity.this, itemList);
if (adapterMessage != null)
{
rvItemList.setHasFixedSize(true);
rvItemList.setLayoutManager(new LinearLayoutManager(MainActivity.this,
LinearLayoutManager.HORIZONTAL, false);
rvItemList.setItemAnimator(new DefaultItemAnimator());
rvItemList.setAdapter(adapterMessage);
//here is the main line for your requirement
rvItemList.setRotation(180);
adapterMessage.notifyDataSetChanged();
}
Now last, In your adapter please rotate your all view in revers direction like below.
public class ViewHolder extends RecyclerView.ViewHolder
{
TextView txt_name;
public ViewHolder(View itemView) {
super(itemView);
txt_name = (TextView) itemView.findViewById(R.id.txt_name);
// here you need to revers rotate your view because your recyclerview is already rotate it so your view is also rotated and you need to revers rotate that view
txt_name.setRotation(-180);
}
}
If you do code as above then your item and its output look like this OutPut
Please make sure to doing this kind of code because android will not responsible for this kind of code, but as per your requirement you can do like this.
I want to make a RecyclerView that scrolls infinitely while also being able to scroll to an item programmatically.
At the moment I've made the RecyclerView loop infinitely using this hacky method: https://stackoverflow.com/a/31254146/7443375
i.e. Overriding my adapter
#Override
public int getCount() {
return Integer.MAX_VALUE;
}
Getting position of item in my adapter like so:
int positionInList = position % fragmentList.size();
And then initializing my RecyclerView's scroll position like so:
recyclerView.getLayoutManager().scrollToPosition(Integer.MAX_VALUE / 2);
However, in my Fragment that has the RecyclerView, I want to be able to scroll to a specific item in my list (i.e. item 3 out of a list of 10 items). When I call
recyclerView.getLayoutManager().scrollToPosition(2);
The list goes into an infinite scroll. I can't figure out how to go to the specific item itself.
Furthermore, how can I make sure that the specific item is centered in the screen? I am using LinearSnapHelper to snap the items in the center of the screen as I scroll, but LinearSnapHelper does not seem to work when setting positions programmatically.
Try this way..
recyclerView.post(new Runnable() {
#Override
public void run() {
new CountDownTimer(Integer.MAX_VALUE, 20 ) {
public void onTick(long millis) {
recyclerView.scrollBy(0, 20);
}
public void onFinish() {
}
}.start();
}
});
I basically have to smooth scroll a listview and update a row at the same time.
I do it with a simple approach for now:
mListViewWeeks.post(new Runnable() {
#Override
public void run() {
// update the row concerned
updateItemAtPosition(rowIndex);
int duration = 200;
mListView.smoothScrollToPositionFromTop(rowIndex, 0, duration);
}
});
with the updateItemAtPosition() function:
private void updateItemAtPosition(int position) {
int visiblePosition = mListView.getFirstVisiblePosition();
View view = mListView.getChildAt(position - visiblePosition);
mListView.getAdapter().getView(position, view, mListView);
}
It's working well at a reasonable scroll speed, but when going faster (calling the first block above at a high rate) it can get a bit laggy. Is there anything that I can do to improve updating a row while scrolling smoothly?
You should'nt acces the iew dirrectly like this. Instead you should update your model object displayed by the list and call notifyDataSetChanged() in your adapter.
Well, I'm really late in the game. It looks like one of the reason why RecyclerView was introduced. I'm gonna try to use this component from now on.
A combination of layoutManager.scrollToPosition(position);
and adapter.notifyItemChanged(position); does the job. Everything runs smoothly!!
I'm using basic RecyclerView with GridLayoutManager. I observed that nor smoothScrollToPosition nor scrollToPosition works properly.
a) when using smoothScrollToPosition I often receive error from RecyclerView
"RecyclerView﹕ Passed over target position while smooth scrolling."
and RecyclerView is not scrolled properly (often it misses the targeted row). This is observed mostly when I'm trying to scroll to the 1st item of some row
b) when using scrollToPosition it seems to work quite ok but most of the time I can see only the 1st item of the row and the rest are not displayed.
Can you give me some hints how to make work properly at least one of the methods?
Thanks a lot!
Finally I was able to make it work! LinearLayoutManager.scrollToPositionWithOffset(int, int) did the trick.
I also have same issue, but managed to fix the issue by Customizing SmoothScroller
let Custom LayoutManager as below
public class CustomLayoutManager extends LinearLayoutManager {
private static final float MILLISECONDS_PER_INCH = 50f;
private Context mContext;
public CustomLayoutManager(Context context) {
super(context);
mContext = context;
}
#Override
public void smoothScrollToPosition(RecyclerView recyclerView,
RecyclerView.State state, final int position) {
LinearSmoothScroller smoothScroller =
new LinearSmoothScroller(mContext) {
//This controls the direction in which smoothScroll looks
//for your view
#Override
public PointF computeScrollVectorForPosition
(int targetPosition) {
return CustomLayoutManager.this
.computeScrollVectorForPosition(targetPosition);
}
//This returns the milliseconds it takes to
//scroll one pixel.
#Override
protected float calculateSpeedPerPixel
(DisplayMetrics displayMetrics) {
return MILLISECONDS_PER_INCH/displayMetrics.densityDpi;
}
};
smoothScroller.setTargetPosition(position);
startSmoothScroll(smoothScroller);
}
}
(documentation commented inside the code given above)Please set the above LayoutManager
to the recyerview
CustomLayoutManagerlayoutManager = new CustomLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.smoothScrollToPosition(position);
by using the custom Layout manager
scrollToPosition
also working well in my case u can use
recyclerView.scrollToPosition(position)
also if you want to adjust the speed of smoothScrollToPosition please override the
private static final float MILLISECONDS_PER_INCH = 50f;
in CustomLayoutManager.
So if we put the value as 1f the smoothScrollToPosition will be faster like scrollToPosition.increasing value make delay and decreasing will make the speed of scroll.
Hope this will useful.
In My case,
mRecyclerView.scrollToPosition(10);
also did not work.
But
mRecyclerView.smoothScrollToPosition(10);
works fine for me...
To scroll down smoothly to bottom from any position in the RecyclerView on clicking EditText.
edittext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
rv_commentList.postDelayed(new Runnable() {
#Override
public void run() {
rv_commentList.scrollToPosition(rv_commentList.getAdapter().getItemCount() - 1);
}
}, 1000);
}
});
Another reason why any of the before mentioned solutions may not work is if your RecyclerView is embedded in a NestedScrollView. In this case you have to call the scroll action on the NestedScrollView.
for example:
nestedScrollview.smoothScrollTo(0,0)
This extension is so useful, try please.
fun RecyclerView.smoothSnapToPosition(position: Int, snapMode: Int = LinearSmoothScroller.SNAP_TO_START) {
val smoothScroller = object : LinearSmoothScroller(this.context) {
override fun getVerticalSnapPreference(): Int = snapMode
override fun getHorizontalSnapPreference(): Int = snapMode
}
smoothScroller.targetPosition = position
layoutManager?.startSmoothScroll(smoothScroller)
}
I was facing a weird issue wherein smoothScrollToPosition only worked occasionally.
After putting the smoothScrollToPosition inside Handler Post
Delayed with 1 second delay, it worked fine.
Refer to the following Kotlin example:
Handler().postDelayed({
recyclerViewObject.smoothScrollToPosition(0) // mention the position in place of 0
}, 1000) // 1000 indicates the 1 second delay.
recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView,new RecyclerView.State(),currentPosition);
Try measuring item width or height and call smoothScrollBy(int dx, int dy).
How to perform smooth scrolling and save RecyclerView vertical position after device rotating:
This is the method that works for my case,
public class MainFragment extends Fragment { //OR activity it's //fragment in my case
....
#Override
public void onLoadFinished(#NonNull Loader<List<Report>> loader, List<Report> objects) { // or other method of your choice, in my case it's a Loader
RecyclerView recyclerViewRv = findViewById(........;
.....
recyclerViewRv.setAdapter(.....Your adapter);
recyclerViewRv.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(#NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
recyclerScrollY = recyclerViewRv. computeVerticalScrollOffset();
}
});
//Apply smooth vertical scroll
recyclerViewRv.smoothScrollBy(0,recyclerScrollY);
}
//Save vertical scroll position before rotating devices
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("recyclerScrollY",recyclerScrollY);
}
//BackUp vertical scroll position after rotating devices
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null) {
recyclerScrollY = savedInstanceState.getInt("recyclerScrollY");
}
}
//If you want to perform the same operation for horizontal scrolling just add a variable called recyclerScrollX = recyclerScrollY = recyclerViewRv. computeHorizontalScrollOffset(); then save in bundle
Calling the recyclerView smoothScroll isn't effective, as the recyclerView itself doesn't handle its layout.
What you should do is calling the layout manager scroll method instead.
This should look something like this
mRecyclerView.getLayoutManager().scrollToPosition(desiredPosition);
If you are trying to do a quick scroll to a position at the top of the RecyclerView, just use LinearLayoutManager.scrollToPositionWithOffset with 0 as the offset.
Example:
mLinearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(mLinearLayoutManager);
mLinearLayoutManager.scrollToPositionWithOffset(myPosition, 0);
smoothScrollToPosition is very slow. If you want something fast go with scrollToPositionWithOffset.
when you use scrollToPosition it will show it on top of the recycler view.
But if you use smoothScrollToPosition it will scroll till it come in to Window Visible. that's why while smoothScrool to item below, it will show it on bottom
Actually, if you have a RecyclerView inside a NestedScrollView, you must use both of these lines every time you want to go to the beginning of the RecyclerView:
nestedScrollView.smoothScrollTo(0, 0);
layoutManager.scrollToPositionWithOffset(0, 0);
This completely works for me.
this worked for me
Handler().postDelayed({
(recyclerView.getLayoutManager() as LinearLayoutManager).scrollToPositionWithOffset( 0, 0)
}, 100)
None of these answers worked for me. I needed to smoothScrollToPosition but #Ramz answer didn't work. I was finding it would consistently overscroll but only in one direction. I discovered that it seemed to be the item decorators throwing it off. I had a horizontal layout and I wanted to add a space after every item except the last and it didn't like that asymmetry. As soon as I included a space after every item, it worked!
nestedScroll.smoothScrollTo(0, recycler.top)
So i was looking for a solution to get back to the top with a recyclerview inside another layout that has a view on top of it (in my case I had a LinearLayout with a TextView and my recyclerview inside). Because of that the smoothscroll would go only to half the way to the first item.
Here's what I did which works really well (Kotlin solution):
back_to_top.setOnClickListener {
GlobalScope.launch(Dispatchers.Main) {
GlobalScope.launch(Dispatchers.Main) {
recyclerview.layoutManager?.smoothScrollToPosition(recyclerview, RecyclerView.State(), 0)
delay((recyclerview.layoutManager as LinearLayoutManager).findLastVisibleItemPosition() * 100L)
}.join()
recyclerview.scrollToPosition(0)
}
back_to_top.visibility = View.GONE
}
}
Here what I do is I smoothscroll to the first element and delay the scroll by 100ms times the last item visible and then call the scrollToPosition(0) (which goes to the top.correctly)