Smooth Scrolling in Android

Smooth scrolling in scrollView

You have added ScrollView inside RelativeLayout, what I suggest is that you should place RelativeLayout inside ScrollView tag. Please go through below code,

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/top_string"
android:textColor="@android:color/white"
android:textSize="16dp"
android:textScaleX="1.5"
/>
<ImageView
android:id="@+id/img"
android:layout_width="300dp"
android:layout_height="150dp"
android:src="@drawable/dg_truck_main"
android:layout_gravity="center_horizontal"
android:background="@android:color/holo_blue_light"
android:layout_marginTop="10dp"
android:layout_centerHorizontal="true"
android:layout_below="@id/text_view"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/top_string2"
android:textColor="@android:color/white"
android:textSize="16dp"
android:textScaleX="1.5"
android:layout_marginTop="50dp"
android:layout_below="@id/img"
/>
</RelativeLayout>

</RelativeLayout>
</ScrollView>

RecyclerView - How to smooth scroll to top of item on a certain position?

RecyclerView is designed to be extensible, so there is no need to subclass the LayoutManager (as droidev suggested) just to perform the scrolling.

Instead, just create a SmoothScroller with the preference SNAP_TO_START:

RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(context) {
@Override protected int getVerticalSnapPreference() {
return LinearSmoothScroller.SNAP_TO_START;
}
};

Now you set the position where you want to scroll to:

smoothScroller.setTargetPosition(position);

and pass that SmoothScroller to the LayoutManager:

layoutManager.startSmoothScroll(smoothScroller);

Smooth scrolling in Android

I have no experience with OpenGL nor accelerometer, but swipe (called fling in Android's API) is not hard to achieve. First thing you need when making such a custom View, is implementing a GestureDetector and call its onTouchEvent() in your view's onTouchEvent()

GestureDetector mGD = new GestureDetector(getContext(),
new SimpleOnGestureListener() {

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
// beware, it can scroll to infinity
scrollBy((int)distanceX, (int)distanceY);
return true;
}

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float vX, float vY) {
mScroller.fling(getScrollX(), getScrollY(),
-(int)vX, -(int)vY, 0, (int)mMaxScrollX, 0, (int)mMaxScrollY);
invalidate(); // don't remember if it's needed
return true;
}

@Override
public boolean onDown(MotionEvent e) {
if(!mScroller.isFinished() ) { // is flinging
mScroller.forceFinished(true); // to stop flinging on touch
}
return true; // else won't work
}
});

@Override
public boolean onTouchEvent(MotionEvent event) {
return mGD.onTouchEvent(event);
}

While OnGestureListener.onScroll() calls directly View.scrollBy(), for the onFling() method you'll need a Scroller.

Scroller is a simple object that, as reference says, encapsulates scrolling. It can be used for continuous scrolling or to react to flings. Scroller.fling() begin a "simulation" of fling scroll inside itself, and by watching it you can copy its smoothness with a continuous redrawing animation:

@Override
protected void onDraw(Canvas canvas) {
// ....your drawings....

// scrollTo invalidates, so until animation won't finish it will be called
// (used after a Scroller.fling() )
if(mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
}
}

that is, until animation is running, calculate the point we reached and scroll there.

As a last note: remember to return true in your OnGestureListener.onDown(), even if you don't want to do anything on down, or it won't work.

And be careful, because Scroller in Android 2.2 has a bug for which the fling animation will not actually end even if it reaches the limits you passed as arguments (yet computed offset respects them, so it won't actually move).

How to make RecyclerView scroll smoothly?

The typical source of "jerky" scrolling in Android is the app taking too much time on the main application thread updating the UI. In the case of RecyclerView, this would mean taking too much time in onBindViewHolder() or possibly in onCreateViewHolder(). Those each need to return in sub-millisecond times, meaning you cannot do disk I/O or network I/O in them.

think I found the problem. I am using holder.photo.setImageBitmap(BitmapFactory.decodeFile(itemList.get(position).get‌​AbsolutePath())); on onBindViewHolder() and the image file is around 100kb each with about a dozen images in the list

Yes, that will be doing disk I/O and image decoding on the main application thread. That will be slow enough to cause jank in the UI (i.e., "jerky" scrolling).

Consider using an image loading library, like Picasso or Universal Image Loader, as they can populate your ImageView from the bitmap asynchronously.

This sample app uses Universal Image Loader to help populate the contents of a RecyclerView (with GridLayoutManager), with the data source being the available videos on the device.

smooth scrolling for recyclerview

Its because your recycler view is inside a nested Scroll view.

<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior">

<android.support.v7.widget.RecyclerView
android:id="@+id/recycle2"
android:nestedScrollingEnabled="false"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

also in your code do this to support older devices :

 recyclerView.setNestedScrollingEnabled(false);

Auto smooth scrolling in Recycler view

I found this method and it works for me:

recyclerView.smoothScrollBy(dx, dy, new LinearInterpolator(), time);

Recyclerview inside ScrollView not scrolling smoothly

Try doing:

RecyclerView v = (RecyclerView) findViewById(...);
v.setNestedScrollingEnabled(false);

As an alternative, you can modify your layout using the support design library. I guess your current layout is something like:

<ScrollView >
<LinearLayout >

<View > <!-- upper content -->
<RecyclerView > <!-- with custom layoutmanager -->

</LinearLayout >
</ScrollView >

You can modify that to:

<CoordinatorLayout >

<AppBarLayout >
<CollapsingToolbarLayout >
<!-- with your content, and layout_scrollFlags="scroll" -->
</CollapsingToolbarLayout >
</AppBarLayout >

<RecyclerView > <!-- with standard layoutManager -->

</CoordinatorLayout >

However this is a longer road to take, and if you are OK with the custom linear layout manager, then just disable nested scrolling on the recycler view.

Edit (4/3/2016)

The v 23.2 release of the support libraries now includes a factory “wrap content” feature in all default LayoutManagers. I didn’t test it, but you should probably prefer it to that library you were using.

<ScrollView >
<LinearLayout >

<View > <!-- upper content -->
<RecyclerView > <!-- with wrap_content -->

</LinearLayout >
</ScrollView >

LazyColumnFor is not smooth scrolling

Currently (version 1.0.0-alpha02) Jetpack Compose has 2 Composable functions for loading image resources:

  1. imageResource(): this Composable function, load an image resource synchronously.

  2. loadImageResource(): this function loads the image in a background thread, and once the loading finishes, recompose is scheduled and this function will return deferred image resource with LoadedResource or FailedResource

So your lazyColumn is not scrolling smoothly since you are loading images synchronously.

So you should either use loadImageResource() or a library named Accompanist by Chris Banes, which can fetch and display images from external sources, such as network, using the Coil image loading library.

UPDATE:

Using CoilImage :

First, add Accompanist Gradle dependency, then simply use CoilImage composable function:

    CoilImage(data = R.drawable.header) 

Using loadImageResource() :

    val deferredImage = loadImageResource(
id = R.drawable.header,
)

val imageModifier = Modifier.preferredHeight(150.dp).fillMaxWidth()
.clip(shape = RoundedCornerShape(8.dp))
deferredImage.resource.resource?.let {
Image(
asset = it,
modifier = imageModifier
)
}

Note: I tried both ways in a LazyColumnFor, and although loadImageResource() performed better than imageResource() but still it didn't scroll smoothly.

So I highly recommend using CoilImage

Note 2: To use Glide or Picasso, check this repository by Vinay Gaba



Related Topics



Leave a reply



Submit