2

I'd like to create an application for tablets using 2 panels. The left one as a menu and the right one as a content presenter. In fact the behavior I expect is similar to the one in Gmail app.

enter image description here

I'm currently using 2 fragments. One is basically a ListView with room names plus some buttons. The other one (the content) includes some information about the selected room.

The room I select in the left panel should stay highlighted - like in the Gmail app. I was trying for many hours to achieve this effect using selectors, but failed.

Moreover I found 2 different opinions about this approach..

1) "Do not try to keep the focus or selection in touch mode"

2) "In general, use the pane on the right to present more information about the item you selected in the left pane. Make sure to keep the item in the left pane selected in order to establish the relationship between the panels."

Can you tell me how to achieve this (just to keep the selected item distinguished from the rest)? Maybe a ListView isn't the best approach here?

UPDATE

Thanks to Christoph Eberhardt's answer I created a sample project that works fine. It's available on github.

Andrzej Gis
  • 13,706
  • 14
  • 86
  • 130
  • corrected sample in my old answer: first answer was copied from my code, that I used on a ListFragment, which actually works. My edited anwser should work now – Christoph Eberhardt Jun 18 '12 at 13:54

1 Answers1

3

Create an xml file in res/drawable/list_item_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true" android:drawable="@drawable/list_pressed" />
    <item android:drawable="@drawable/list_default" />
</selector>

For the list elements make an own xml file res/layout/list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:gravity="center_vertical"
    android:minHeight="?android:attr/listPreferredItemHeight"
    android:paddingLeft="20dp"
    android:background="@drawable/list_item_selector"
/>

Then when creating the list adapter do:

setListAdapter(new CustomAdapter<String>(getActivity(),
            R.layout.list_item, stringArray));

Now all you have to do is providing the drawables list_default and list_pressed and list_altered

The CustomAdpater looks like:

package com.test.listview_keep_selected;

import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.StateListDrawable;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class CustomAdapter<T> extends ArrayAdapter<T> {

    private Context m_cContext;

    public CustomAdapter(Context context, int textViewResourceId,
            T[] objects) {

        super(context, textViewResourceId, objects);
        this.m_cContext = context;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final View returnView = super.getView(position, convertView, parent);
        final ListView listView  = (ListView) ((Activity) m_cContext).findViewById(R.id.listViewTest);
        returnView.setOnClickListener(new OnClickListener(
                ) {


            @Override
            public void onClick(View v) {
                for(int i = 0; i< listView.getChildCount(); i++)
                    listView.getChildAt(i).setSelected(false);
                StateListDrawable states = new StateListDrawable();
                states.addState(new int[] {android.R.attr.state_selected},
                        m_cContext.getResources().getDrawable(R.drawable.list_pressed));
                states.addState(new int[] { },
                        m_cContext.getResources().getDrawable(R.drawable.list_altered));
                v.setBackgroundDrawable(states);
                v.setSelected(true);
            }
        });
        return returnView;
    }

}

Edit:

And if you don't have it already:

listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);

Edit: Don't set the choice mode with a plain ListView, only makes sense if you have e.g. a ListFragment as I have in my code

It's not perfect now, but from now on you should be fine after playing around a bit.

What also might help is: ListView item background via custom selector

Edit:

Now it should work as you want it^^

Community
  • 1
  • 1
  • I followed your instructions. This doesn't keep the selected item highlighted. Well in fact doesn't even get highlighted while it's being pressed. :( Here are my results: https://github.com/gisek/ListView_test Am I missing something? – Andrzej Gis Jun 18 '12 at 12:30
  • First of all thanks for your time. I think your list_item.xml is missing a line [android:background="@drawable/list_item_selector"]. Now it works a little better. List items are blue and when I touch one it turns red. But still it doesn't have the functionality that is crucial for me. When I release the item it turns blue, but should stay red until I press another one. – Andrzej Gis Jun 18 '12 at 14:15
  • mmh yeah you wrote that, what about writing your own adapter, catching the click event and then change the background of the listitem view, should be a matter of a few minutes – Christoph Eberhardt Jun 18 '12 at 14:19
  • In the screenshot you can see that the top item on the list is azure. I guess it stays azure as long as the user is reading the related email. I need something similar. I press "Kitchen" it turns red and stays red until I finish reading details about kitchen. Than I press "Living room". Kitchen turns back blue. Living room turns red. And so on. – Andrzej Gis Jun 18 '12 at 14:23
  • finally, I think this is what you want – Christoph Eberhardt Jun 18 '12 at 14:59
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/12702/discussion-between-christoph-eberhardt-and-gisek) – Christoph Eberhardt Jun 18 '12 at 15:07