Changing background color of ListView items on And

2019-01-01 03:27发布

问题:

How can I change background color of ListView items on a per-item basis. When I use android:backgroundColor in the ListView item layout I can achieve this, however the list selector is no longer visible. I can make the selector visible again by setting drawSelectorOnTop to true but then the selector overlays the whole item.

Any ideas how to change those background colors and keep the selector?

PS I would rather not change the selector itself.

EDIT: Authors of GMail application have managed to achieve exactly this so it\'s definitely possible.

回答1:

You have to create a different state drawable for each color you want to use.

For example: list_selector_read.xml and list_selector_unread.xml.

All you need to do is set everything to transparent except the android:state_window_focused=\"false\" item.

Then when you are drawing your list you call setBackgroundResource(R.drawable.list_selector_unread/read) for each row.

You don\'t set a listSelector on the ListView at all. That will maintain the default selector for your particular flavor of Android.



回答2:

This is a modification based on the above code, a simplest code:

private static int save = -1;

public void onListItemClick(ListView parent, View v, int position, long id) { 

    parent.getChildAt(position).setBackgroundColor(Color.BLUE);

    if (save != -1 && save != position){
        parent.getChildAt(save).setBackgroundColor(Color.BLACK);
    }

    save = position;                

}

I hope you find it useful

greetings!



回答3:

Ok, I got it to work like this:

<?xml version=\"1.0\" encoding=\"utf-8\"?>
<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">
    <item android:state_pressed=\"false\" android:drawable=\"@color/BackgroundColor\" />
    <item android:drawable=\"@color/transparent\" />
</selector>

YMMV!



回答4:

No one seemed to provide any examples of doing this solely using an adapter, so I thought I would post my code snippet for displaying ListViews where the \"curSelected\" item has a different background:

final ListView lv = (ListView)findViewById(R.id.lv);
lv.setAdapter(new BaseAdapter()
{
    public View getView(int position, View convertView, ViewGroup parent)
    {
        if (convertView == null)
        {
            convertView = new TextView(ListHighlightTestActivity.this);
            convertView.setPadding(10, 10, 10, 10);
            ((TextView)convertView).setTextColor(Color.WHITE);
        }

        convertView.setBackgroundColor((position == curSelected) ? 
            Color.argb(0x80, 0x20, 0xa0, 0x40) : Color.argb(0, 0, 0, 0));
        ((TextView)convertView).setText((String)getItem(position));

        return convertView;
    }

    public long getItemId(int position)
    {
        return position;
    }

    public Object getItem(int position)
    {
        return \"item \" + position;
    }

    public int getCount()
    {
        return 20;
    }
});

This has always been a helpful approach for me for when appearance of list items needs to change dynamically.



回答5:

mAgendaListView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//view.setBackgroundColor(Color.RED);

for(int i=0; i<parent.getChildCount(); i++)
{
     if(i == position)
     {
               parent.getChildAt(i).setBackgroundColor(Color.BLUE);
     }
     else
     {
               parent.getChildAt(i).setBackgroundColor(Color.BLACK);
     }

 }


回答6:

From the source code of Android\'s 2.2 Email App:

<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">
    <item android:state_window_focused=\"false\" android:state_selected=\"true\"
        android:drawable=\"@android:color/transparent\" />
    <item android:state_selected=\"true\"
        android:drawable=\"@android:color/transparent\" />
    <item android:state_pressed=\"true\" android:state_selected=\"false\"
        android:drawable=\"@android:color/transparent\" />
    <item android:state_selected=\"false\"
        android:drawable=\"@color/message_item_read\" />
</selector>

Nothing more to say...



回答7:

the easiest way is this. Inside your ListArrayAdapter just do this

if(your condition here) rowView.setBackgroundColor(Color.parseColor(\"#20FFFFFF\"));

don\'t over complicate



回答8:

Simple code to change all in layout of item (custom listview extends baseadapter):

lv.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                long arg3) {

            RelativeLayout layout=(RelativeLayout) arg1.findViewById(R.id.rel_cell_left);
            layout.setBackgroundColor(Color.YELLOW);



        }
    });


回答9:

Did you mean to change the background color of the custom listitems when you click on it?

If so:

You just add the following code to your listview layout in xml.


android:drawSelectorOnTop=\"true\" android:listSelector=\"@android:drawable/list_selector_background\"


The list selector here uses default selector which has a dark grey color. You can make your own drawable and assign it to the list selector as above.

Hope this is what you wanted.



回答10:

Following way very slowly in the running

mAgendaListView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//view.setBackgroundColor(Color.RED);

for(int i=0; i<parent.getChildCount(); i++)
{
     if(i == position)
     {
               parent.getChildAt(i).setBackgroundColor(Color.BLUE);
     }
     else
     {
               parent.getChildAt(i).setBackgroundColor(Color.BLACK);
     }

 }

Replaced by the following

int pos = 0;
int save = -1;
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
            long id) {
            //Always set the item clicked blue background
            view.setBackgroundColor(Color.BLUE);

            if (pos == 0) {
                if (save != -1) {
                    parent.getChildAt(save).setBackgroundColor(Color.BLACK);
                }
                save = position;
                pos++;
                Log.d(\"Pos = 0\", \"Running\");

            } else {
                parent.getChildAt(save).setBackgroundColor(Color.BLACK);
                save = position;
                pos = 0;
                Log.d(\"Pos # 0\", \"Running\");
            }


回答11:

Take a look at List14 example. In getView() you can call convertView.setBackgroundDrawable() for each entry. You could have a class member counter to decide which background to call it with to get alternating backgrounds, for example.



回答12:

In the list view you can add android:listselector=color name that you want.

this work fine in my app.



回答13:

The best tutorial on this can be found here.

Key sections:

  1. Surely call view.setSelected(true) in onItemClick, otherwise the you can\'t see the selected item background
  2. Preserve the order of states in your selector otherwise you\'ll see unpredictable behavior in background colors (state_selected followed by state_pressed)


回答14:

By changing a code of Francisco Cabezas, I got the following:

private int selectedRow = -1;

...

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    parent.getChildAt(position).setBackgroundResource(R.color.orange);
    if (selectedRow != -1 && selectedRow != position) {
        parent.getChildAt(selectedRow).setBackgroundResource(R.color.black);
    }
    selectedRow = position;


回答15:

If the setBackgroundColor is added for onItemClick event, it will not work unless you can put it after the click event.

Try to add debug code in the adapter\'s getView method, you will find that getView will be called again whenever you click on the screen. So, after you set the background color, the system will redraw the screen with original setting. Don\'t know why it waste resource to rebuild the screen whenever it\'s being click, there already have other way that we can notify the system to redraw the screen when needed.

Maybe you can add some control flag to determine the background color for individual row, then modify the getView method to set the color according to this control flag. So, the background color will be changed when it redraw the screen.

I\'m also looking for an official solution on it.



回答16:

I tried all answers above .. none worked for me .. this is what worked eventually and is used in my application .. it will provide read/unread list items colors while maintaining listselector styles for both states :

<ListView
                android:id=\"@+id/list\"
                android:layout_width=\"match_parent\"
                android:layout_height=\"match_parent\"
                android:listSelector=\"@drawable/selectable_item_background_general\"
                android:drawSelectorOnTop=\"true\"
                android:fadingEdge=\"none\"
                android:scrollbarStyle=\"outsideOverlay\"
                android:choiceMode=\"singleChoice\" />

selectable_item_background_general.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/bg_item_selected_drawable\" />
    <item android:state_pressed=\"true\" android:drawable=\"@drawable/bg_item_selected_drawable\" />
    <item android:drawable=\"@android:color/transparent\" />
</selector>

bg_item_selected_drawable.xml :

<shape xmlns:android=\"http://schemas.android.com/apk/res/android\">
    <solid android:color=\"#12000000\" />
</shape>

notification_list_itemlayout.xml :

<RelativeLayout 
            xmlns:android=\"http://schemas.android.com/apk/res/android\"
            android:id=\"@+id/rowItemContainer\"
            android:layout_width=\"fill_parent\"
            android:layout_height=\"wrap_content\">

    <RelativeLayout 
        android:layout_width=\"fill_parent\"
        android:layout_height=\"wrap_content\"
        android:padding=\"8dp\"
        android:paddingLeft=\"16dp\"
        android:paddingStart=\"16dp\"
        android:paddingRight=\"16dp\"
        android:paddingEnd=\"16dp\">

            <ImageView
                android:id=\"@+id/imgViewIcon\"
                android:layout_width=\"60dp\"
                android:layout_height=\"60dp\"
                android:src=\"@drawable/cura_logo_symbol_small\"
                android:layout_alignParentLeft=\"true\"
                android:layout_alignParentStart=\"true\"
                android:layout_marginRight=\"8dp\"
                android:layout_marginEnd=\"8dp\" />
            <TextView
                android:id=\"@+id/tvNotificationText\"
                android:layout_width=\"wrap_content\"
                android:layout_height=\"wrap_content\"
                android:layout_alignTop=\"@+id/imgViewIcon\"
                android:layout_toRightOf=\"@+id/imgViewIcon\"
                android:layout_toEndOf=\"@+id/imgViewIcon\"
                android:textSize=\"@dimen/subtitle\"
                android:textStyle=\"normal\" />
            <TextView
                android:id=\"@+id/tvNotificationTime\"
                android:layout_width=\"fill_parent\"
                android:layout_height=\"wrap_content\"
                android:layout_marginTop=\"1dip\"
                android:layout_below=\"@+id/tvNotificationText\"
                android:layout_toRightOf=\"@+id/imgViewIcon\"
                android:layout_toEndOf=\"@+id/imgViewIcon\"
                android:textSize=\"@dimen/subtitle\" />
        </RelativeLayout>
</RelativeLayout>

Finally, in your adapter :

if (!Model.Read)
    rowItemContainer.SetBackgroundColor (Android.Graphics.Color.ParseColor (\"#FFFDD0\")); // unread color
else
    rowItemContainer.SetBackgroundColor (Android.Graphics.Color.White); // read color


回答17:

You can do This.

 final List<String> fruits_list = new ArrayList<String>(Arrays.asList(fruits));

    // Create an ArrayAdapter from List
    final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>
            (this, android.R.layout.simple_list_item_1, fruits_list){
        @Override
        public View getView(int position, View convertView, ViewGroup parent){
            // Get the current item from ListView
            View view = super.getView(position,convertView,parent);
            if(position %2 == 1)
            {
                // Set a background color for ListView regular row/item
                view.setBackgroundColor(Color.parseColor(\"#FFB6B546\"));
            }
            else
            {
                // Set the background color for alternate row/item
                view.setBackgroundColor(Color.parseColor(\"#FFCCCB4C\"));
            }
            return view;
        }
    };

    // DataBind ListView with items from ArrayAdapter
    lv.setAdapter(arrayAdapter);
}

}