Keeping the last visible item of a ListView when the size of the ListView changes

What you Want

Last Visible Item Without Keyboard

Last Visible Item Without Keyboard

Last Visible Item With Keyboard

Last Visible Item With Keyboard

Last Visible Item With larger input

Last Visible Item With larger input

Here is how i did it.

Summary

  • Set android:stackFromBottom="true" and android:transcriptMode="alwaysScroll" in your list view
  • Set android:windowSoftInputMode="adjustPan" in Activity
  • Call adapter.notifyDataSetChanged(); when you add new chats so that the list view will always scroll to the last position
  • Set android:inputType="textMultiLine" & android:maxLines="4" in EditText for growing text box

Details

Activity

<activity android:name="MainActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan"></activity>

Chat View

<RelativeLayout
    android:id="@+id/chat_header"
    android:layout_width="fill_parent"
    android:layout_height="40dp"
    android:padding="3dp" >

    <Button
        android:id="@+id/btnBackChat"
        android:layout_width="35dp"
        android:layout_height="35dp"
        android:layout_alignParentLeft="true"
        android:background="@drawable/back_button" />

    <TextView
        android:id="@+id/txt_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/btnBackChat"
        android:layout_centerHorizontal="true"
        android:textColor="@android:color/white"
        android:textSize="18sp" />

    <ImageView
        android:id="@+id/imgViewProfileChat"
        android:layout_width="35dp"
        android:layout_height="35dp"
        android:layout_alignParentRight="true"
        />
</RelativeLayout>

<ListView
    android:id="@+id/listView1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_above="@+id/form"
    android:layout_below="@+id/chat_header"
    android:stackFromBottom="true"
    android:transcriptMode="alwaysScroll"/>

<RelativeLayout
    android:id="@+id/form"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:orientation="vertical" >

    <ImageButton
        android:id="@+id/btnAttach"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:contentDescription="@string/attach"
        android:src="@drawable/attach_icon" />

    <EditText
        android:id="@+id/txtChat"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@+id/btnSend"
        android:layout_toRightOf="@+id/btnAttach"
        android:inputType="textMultiLine"
        android:maxLines="4" />

    <Button
        android:id="@+id/btnSend"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:text="@string/send" />
</RelativeLayout>


I think you may want to use AdapterView.getLastVisiblePosition() before displaying the keyboard.

Two solutions here:

  • on EditText click
  • thanks to an OnScrollListener (and its onScroll function) listening to your ListView

then use the AdapterView.setSelection to jump to this item (or index - 2 or index - 3) after EditText focus.


You can use android:windowSoftInputMode="adjustPan" in your AndroidManifest.xml as below

 <activity android:name="com.example.SimpleListView"
            android:label="@string/app_name"
            android:windowSoftInputMode="adjustPan" >

This should produce the output you want. Official android documentation .

Optionally you can specify transcript mode(if you are working on some chat feature) for your list view if you want to scroll automatically to the end of listview. You can check the android:transcriptMode="normal" as well and see if that fits.

A related SO answer. Official android doc.

<ListView
android:id="@+id/comments"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:transcriptMode="alwaysScroll">

This should solve most of your issues, maybe except for the last one(in the image) which I haven't tested.