Java – How to keep listview items highlighted after a device orientation change in android

How to keep listview items highlighted after a device orientation change in android… here is a solution to the problem.

How to keep listview items highlighted after a device orientation change in android

I have a ListView populated with data. The user can press and hold a row, it will be highlighted, and the contextual action bar will show that it is selected. If the user selects more rows, the number of rows selected in the context action bar increases. However, as soon as I change the orientation of my device, the highlighting disappears, but the list item appears as selected. I tried using selectors but it didn’t work. In XML, I have each line with activatedBackgroundIndicator as its background.

Does anyone know why the highlights disappear? Thank you.

This is the onSaveInstanceState code:

@Override
public void onSaveInstanceState(Bundle outState) {
    check if any items are selected
    if (listView.getCheckedItemCount() > 0) {
        get the list of selected items and convert it to an int Array
        because SparseBooleanArray cannot be stored in a bundle
        SparseBooleanArray selectedItems = listView.getCheckedItemPositions();
        int[] selectedItems_intArray = new int[listView.getCheckedItemCount()];
        for (int i = 0; i < selectedItems.size(); i++) {
            if (selectedItems.valueAt(i) == false)
                continue;
            selectedItems_intArray[i] = selectedItems.keyAt(i);
        }
        outState.putIntArray("Selected Items", selectedItems_intArray);
    }
}

This is the code in onCreate:

       if (savedInstanceState != null) {
            int[] checkedItems = savedInstanceState.getIntArray("Selected Items");
            if (checkedItems != null) {

for (int i = 0; i < checkedItems.length; i++) {
                   listView.setItemChecked(checkedItems[i], true);
                    adapter.setNewSelection(checkedItems[i], true);

}
            }
        }

Edit:

This is the part of the ListView activity:

    <activity
        android:name="com.newapp.MainListActivity"
        android:label="@string/app_name"
        android:configChanges="orientation"
        >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

Solution

When you rotate the device, the current activity is destroyed and recreated.

You can store the selected element in onPause() and then select it in onResume(), or you can use a simpler solution: don’t allow Android to break your activity while the device is spinning.

To do this, you can add AndroidManifest to the section of the activity:

<activity android:configChanges="orientation|screenSize"
...
</activity>

Note: You can also do the same for the entire application if needed (add the same android:configChanges="orientation|screenSize" to the application section).

Edit:

My first answer was to use android:configChanges="orientation". My second is using android:configChanges="orientation|screenSize".

For those wondering why, the thing is simple:

  1. By adding direction to the list, you are telling Android “don’t worry about the direction change, I can handle it”. Therefore, when the orientation of the device changes, Android does not need to worry about destroying and recreating the activity.

  2. Adding screenSize to the list is telling Android “don’t worry about the screen size change, I can handle it”. In our case this is not required, but it can. The reason is that some versions of Android (I don’t really remember which ones) are a bit silly about it. When you have a device in a vertical position, it has 480×800 pixels; When you put it horizontally, it has 800×480 pixels. So, the screen size has really changed. Some versions of Android are smart enough to recognize this “screen size change” that they see it as part of the android:configChanges="orientation" setting; Some Android versions are not that smart, and you have to specify both.

Note: When you use this technique, be aware that Android does not handle device rotation. Therefore, if the layout of portrait mode and landscape mode is different, you have to change it yourself (but I recommend against using this method, even if it is easier for an application with only one layout type).

Related Problems and Solutions