I have an XML with two ListView, one with a list of clients filled by a select query (lv_cli) and the other with the details of the client selected (lv_cli_det). I would like to keep the client selected in the lv_cli while the lv_cli_det show the details.

XML:

<ListView
    android:id="@+id/cli_lista"
    android:layout_width="512dp"
    android:layout_height="wrap_content"
    android:fadeScrollbars="false"
    >
</ListView>

<ListView
    android:id="@+id/cli_lista_det"
    android:layout_width="512dp"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@+id/cli_lista"
    android:fadeScrollbars="false" >
</ListView>

Java:

Cursor cursor = db.rawQuery("Select NrCl||';'||Nome From Clientes", null);
final ListView t = (ListView)findViewById(R.id.cli_lista);
ArrayAdapter<String> myarrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1, listItems);
t.setAdapter(myarrayAdapter);

final ListView td = (ListView)findViewById(R.id.cli_lista_detalhe);
final ArrayAdapter<String> myarrayAdapter2 = new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1, listItems2);

t.setOnItemClickListener(new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        String item = ((TextView)view).getText().toString();
        String[] strArray = item.split("\\;");

        cli.load(strArray[0].toString());
        td.setAdapter(myarrayAdapter2);
        listItems2.clear();
        listItems2.add("Nome: " + cli.getNome());
        listItems2.add("Morada: " + cli.getMorada());
        listItems2.add("Localidade: " + cli.getLoca());
        listItems2.add("Código Postal: " + cli.getCp());
        listItems2.add("Pais: " + cli.getPais());
        listItems2.add("Nif: " + cli.getNif());
        listItems2.add("Tel: " + cli.getTel());
        listItems2.add("Tlm: " + cli.getTlm());
        listItems2.add("Tipo Preço: " + cli.getTipoPvn());
        listItems2.add("Cond. Pagamento: " + cli.getCpg());
        listItems2.add("Obs: " + cli.getObs());
        td.setAdapter(myarrayAdapter2);
        myarrayAdapter2.notifyDataSetChanged(); 
    }
});

Solution 1

I found the proper way. It's very simple. In resource describe following:

android:choiceMode="singleChoice"
android:listSelector="#666666"

(or you may specify a resource link instead of color value)

Programmatical:

listView.setSelector(Drawable selector);
listView.setSelector(int resourceId);
listView.setChoiceMode(int mode);

mode can be one of these: AbsListView.CHOICE_MODE_SINGLE, AbsListView.CHOICE_MODE_MULTIPLE, AbsListView.CHOICE_MODE_NONE (default)

(AbsListView is the abstract ancestor for the ListView class)

P.S. manipulations with onItemClick and changing view background are bankrupt, because a view itself is a temporary object. Hence you must not to track a view.

If our list is long enough, the views associated with scrolled out items will be removed from hierarchy, and will be recreated when those items will shown again (with cached display options, such as background). So, the view we have tracked is now not an actual view of the item, and changing its background does nothing to the actual item view. As a result we have multiple items selected.

Solution 2

To hold the color of listview item when you press it, include the following line in your listview item layout:

android:background="@drawable/bg_key"

Then define bg_key.xml in drawable folder like this:

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

Finally, include this in your ListView onClickListener:

listView.setOnItemClickListener(new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,long arg3) {
        view.setSelected(true);
        ... // Anything
    }
});

This way, only one item will be color-selected at any time. You can define your color values in res/values/colors.xml with something like this:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="pressed_color">#4d90fe</color>
    <color name="default_color">#ffffff</color>
</resources>

Solution 3

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {

            for (int j = 0; j < adapterView.getChildCount(); j++)
                adapterView.getChildAt(j).setBackgroundColor(Color.TRANSPARENT);

            // change the background color of the selected element
            view.setBackgroundColor(Color.LTGRAY);
});

Perhaps you might want to save the current selected element in a global variable using the index i.

Solution 4

Simplistic way is,if you are using listview in a xml,use this attributes on your listview,

android:choiceMode="singleChoice"
android:listSelector="#your color code"

if not using xml,by programatically

listview.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
listview.setSelector(android.R.color.holo_blue_light);

Solution 5

You need selector like this:

<selector xmlns:android="http://schemas.android.com/apk/res/android">

<!-- State when a row is being pressed, but hasn't yet been activated (finger down) -->
<item android:drawable="@color/app_primary_color_light" android:state_pressed="true" />

<!-- Used when the view is "activated". -->
<item android:drawable="@color/app_primary_color" android:state_activated="true" />

<!-- Default, "just hangin' out" state. -->
<item android:drawable="@android:color/transparent" /></selector>

And then set android:choiceMode="singleChoice" to your ListView.

Solution 6

From Avinash Kumar Pankaj's example

View v;

then at oncreate method

v = new View(getActivity());

and then onlistitemclick method i wrote

public void onListItemClick(ListView listView, View view, int position,
       long id) {
   v.setBackgroundResource(0);
   view.setBackgroundResource(R.color.green);
   v = view;
}

It worked for me. Thank you.

I replaced

v = new View(getActivity());

to

v = new View(this);

and the code worked well.

It is necessary the xml files 'colors' and 'bg_key' from previous examples too, as well as ListView attribute android:background="@drawable/bg_key"

Mauro

Solution 7

*please be sure there is no Ripple at your root layout of list view container

add this line to your list view

android:listSelector="@drawable/background_listview"

here is the "background_listview.xml" file

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/white_background" android:state_pressed="true" />
<item android:drawable="@color/primary_color" android:state_focused="false" /></selector>

the colors that used in the background_listview.xml file :

<color name="primary_color">#cc7e00</color>
<color name="white_background">#ffffffff</color>

after these

(clicked item contain orange color until you click another item)

Solution 8

One way you can do this, is to Keep track of the current selected position in your activity:

@Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int position,
            long arg3) {
        currentPosition = position
        lv_cli.notifyDataSetChanged();
    }

Now, be sure you assign an ID to the parent layout (linearLayout, boxLayout, relativeLayout, .. Whatever you prefer) of your list item.

Then in your ListView you can do something Like this:

layoutBackground = (LinearLayout) convertView.findViewById(R.id.layout_background);

if (YourActivity.this.currentPosition == position) {
    layoutBackground.setBackgroundColor(YourActivity.this.getResources().getColor(R.color.hilight_color));
} else{
    layoutBackground.setBackgroundResource(R.drawable.list_item_drawable);
}

Basically, you just set the hilight color to the layout as a background when it equals your current selected position. Notice how I set a drawable background resource when the item is not selected. This could be in your case different (since you posted no code). In my case, this drawable is a selector which makes sure the item is hi-lighted when pressed.

NOTE: This simple code doesn't use a view-holder, but I really recommend using one.

Solution 9

Use the id instead:

This is the easiest method that can handle even if the list is long:

public View getView(final int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    Holder holder=new Holder();
    View rowView;
    rowView = inflater.inflate(R.layout.list_item, null);
    //Handle your items.
    //StringHolder.mSelectedItem is a public static variable.
    if(getItemId(position)==StringHolder.mSelectedItem){
        rowView.setBackgroundColor(Color.LTGRAY);

    }else{
        rowView.setBackgroundColor(Color.TRANSPARENT);
    }
    return rowView;
}

And then in your onclicklistener:

list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
            StringHolder.mSelectedItem = catagoryAdapter.getItemId(i-1);
            catagoryAdapter.notifyDataSetChanged();
.....