8

I have experienced strange behaviour with smooth scroll on listview. I have 30 items in list. When I smooth scroll via

listview.smoothScrollToPositionFromTop(29, 0);

there will be some extra space at the end of screen. Actually listview shifts up a little. Image attached below. But if I scroll manually there will be no space. What can be done to resolve this behaviour?

Image 1

Here is my layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_orange_light">

<ListView
    android:id="@+id/listview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

</RelativeLayout>
Alaattin KAYRAK
  • 1,084
  • 2
  • 12
  • 29

7 Answers7

4

As you have said, I think it's an Android issue. It appears to be part of the animation for over scroll, it seems to get 'stuck' before completing the animation. I've had similar experience with SwipeToRefresh, where the progress indicator doesn't fully disappear after refresh.

Anyway, you can workaround by turning off the animation

    listView.setOverScrollMode(View.OVER_SCROLL_NEVER);

Unfortunately, this loses the animation even if manually scrolled. If you can live with that, I think this will fix your problem.

AbsListView#setOverScrollMode(int)

EDIT: (after original answer was accepted)

I have also found another work around. This one preserves the over scroll animation. Unfortunately, it has another drawback. If the user auto scrolls before doing anything else, the same problem of the border at the bottom exists. If the user manually scrolls to the bottom 1st, no problem from then on. If the user auto scrolls and gets the border, then manually scrolls, no more problem. So, here is the alternate method.

    Drawable drawable = ResourcesCompat.getDrawable(getResources(), R.drawable.invisible_footer, null);
    listView.setOverscrollFooter(drawable);

In the drawable folder, "invisible_footer.xml"

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="2dp"
    android:width="10dp"

    android:viewportWidth="10"
    android:viewportHeight="2">

    <!-- a horizontal line -->
    <path android:pathData="M 1 1 H 10"
        android:strokeColor="#00000000" android:strokeWidth="1" />

</vector>

ListView.html#setOverscrollHeader()

This gives choices:

  1. Lose over scroll animation
  2. Retain animation but risk user seeing bottom border 1 time
Gary99
  • 1,750
  • 1
  • 19
  • 33
1

i have implemented. but, at initial first time it keep the padding at bottom but, from second time its working fine.

    <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.socialintegration.ListAct">
<ListView
    android:id="@+id/listTemp"
    android:layout_width="match_parent"
    android:layout_height="match_parent"></ListView>

</RelativeLayout>

CODE :

public class ListAct extends AppCompatActivity {
ListView l;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_list);
    String str[] = new String[50];
    for (int i = 0; i < 50; i++) {
        str[i] = "poistion" + i;
    }
    ArrayAdapter adpt = new ArrayAdapter(ListAct.this, android.R.layout.simple_dropdown_item_1line, str);
    l = (ListView) findViewById(R.id.listTemp);
    l.setAdapter(adpt);

    l.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            l.smoothScrollToPositionFromTop(29, 0);
        }
    });
}
}
Jaimin Modi
  • 1,530
  • 4
  • 20
  • 72
1

Did you try to set the height of your ListView to wrap_content instead of match_parent?

Even in [this tutorial] all the attributes are set to wrap_content. So replace your ListView attributes on width and height to:

<ListView
    android:id="@+id/listview"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
Zoe
  • 27,060
  • 21
  • 118
  • 148
1

There is an other SO post link which describes a similar problem. I guess the solution in that post should solve your problem.

Community
  • 1
  • 1
Bharat
  • 342
  • 3
  • 7
1

try this to your xml:

<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="0dp"
android:clipToPadding="false"/>
Hamid Goodarzi
  • 1,364
  • 2
  • 13
  • 22
0
<ListView>
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  app:layout_behavior="@string/appbar_scrolling_view_behavior/>

Ok so try: app:layout_behavior="@string/appbar_scrolling_view_behavior"

Bro
  • 53
  • 6
0

I strongly believe to move to RecyclerView. If you don't want to move. Here is work around. Just add this method to your activity, and call it.

private void smoothScrollToTop(final int pos) {
    listView.smoothScrollToPositionFromTop(pos, 0);
    listView.post(new Runnable() {
        @Override
        public void run() {
            listView.smoothScrollToPosition(pos);
        }
    });
}

This is well tested. and worked for me. And here is output.

enter image description here

Moinkhan
  • 12,732
  • 5
  • 48
  • 65