Question

So, everything is working great on smartphones. However, on tablets, my ListView is meant to be displayed as a left navigation element, with the currently activated item appearing expanded in the detail fragment. And that works great too. However, the ListFragment's activated item doesn't display as selected. I've set android:choiceMode to singleChoice. I've got the right selector active, and the background drawable appears when an item is pressed. The selector has the right item for android:state_activated="true". I'm specifying android:activatedBackgroundIndicator in my styles.xml file. When I log the output of listView.getCheckedItemCount() inside of onListItemClick it gives me back 1 as I'd expect.

Once upon a time, a few weeks ago, I even had this all working exactly as intended with an ArrayAdapter, before I started wiring up my data source for real, and before I started using a custom list view item layout. And then somewhere along the way I did something that made activated items show up incorrectly, but I'm not sure what it was.

selectable_background.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android"
        android:exitFadeDuration="@android:integer/config_mediumAnimTime" >
    <item android:state_pressed="false" android:state_focused="true" android:drawable="@drawable/list_focused" />
    <item android:state_pressed="true" android:drawable="@drawable/pressed_background" />

    <!-- selected -->
    <item android:state_activated="true" android:drawable="@drawable/pressed_background" />
    <item android:state_checked="true" android:drawable="@drawable/pressed_background" /> <!-- paranoia -->
    <item android:state_selected="true" android:drawable="@drawable/pressed_background" /> <!-- paranoia -->

    <!-- default -->
    <item android:drawable="@android:color/transparent" />
</selector>

fragment_list.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="match_parent" >

    <ListView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@id/android:list"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight="1"
        android:choiceMode="singleChoice"
        android:listSelector="@drawable/selectable_background" >
    </ListView>
    <TextView android:id="@id/android:empty"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingTop="16dp"
        android:paddingBottom="16dp"
        android:paddingLeft="12dp"
        android:paddingRight="12dp"
        android:text="@string/empty_list" />
</LinearLayout>

list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <ImageView android:id="@+id/item_image"
        android:layout_width="63dp"
        android:layout_height="63dp"
        android:contentDescription="@string/list_image"
        android:src="@drawable/ic_thumbnail_placeholder"
        android:background="#f0f0f0" />

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/item_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceListItemSmall"
        android:gravity="center_vertical"
        android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
        android:paddingRight="?android:attr/listPreferredItemPaddingRight"
        android:minHeight="?android:attr/listPreferredItemHeightSmall" />
</LinearLayout>

MyListFragment.java

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.getActivity().getLoaderManager().initLoader(ALL_ITEMS_LOADER, null, this);
    listAdapter = new SimpleCursorAdapter(
            this.getActivity(),
            R.layout.list_item,
            null,
            new String[] { Item.NAME },
            new int[] { R.id.item_name },
            CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER
    );
    this.setListAdapter(listAdapter);
}

@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
    Uri queryUri;
    switch (i) {
        case ALL_ITEMS_LOADER:
            queryUri = Item.CONTENT_URI;
            return new CursorLoader(this.getActivity(), queryUri, null, null, null, null);
        default:
            throw new IllegalArgumentException("Unknown loader ID: " + i);
    }
}

@Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
    if (listAdapter == null) {
        throw new IllegalStateException("List adapter is missing!");
    } else {
        Log.d(TAG, "Load finished. Cursor swapped.");
        listAdapter.swapCursor(cursor);
    }
}

Update:

I also tried replacing the SimpleCursorAdapter with the ArrayAdapter that I had working before, but no dice:

listAdapter = new ArrayAdapter<String>(
        this.getActivity(),
        R.layout.list_item,
        R.id.item_name,
        new String[] {"1", "2", "3"}
);

Update 2:

Ahah! A clue!

listAdapter = new ArrayAdapter<String>(
        this.getActivity(),
        android.R.layout.simple_list_item_activated_1,
        android.R.id.text1,
        new String[] {"1", "2", "3"}
);

This works. But since I actually need to use my own layout, it doesn't solve my own question. What's so different between R.layout.list_item and android.R.layout.simple_list_item_activated_1?

Était-ce utile?

La solution

Once upon a time, a few weeks ago, I even had this all working exactly as intended ... before I started using a custom list view item layout.

My guess is you were using one of the simple_list_item_activated_x layouts before, which define the activated drawable in their background drawable definition. The one thing the framework does is separate out the pressed logic from the activated logic (the former is part of the list selector, while the latter is on the list item), but it doesn't need to be done that way, you can place them all in the list item backgrounds and disable the selector altogether.

I would recommend placing your custom drawable as the background of each list item as opposed to the list selector; activated is a state applied to each individual item view. Then you can set android:listSelector="@null" since you have a transparent background in some states and you don't want the default selector to show through.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top