alanhchoi
alanhchoi

Reputation: 1250

Android widget: Changing item layout in ListView on notifyAppWidgetViewDataChanged

I want to update the layout of some items a in a ListView in an android app widget if a trigger is given. So I implemented below in getView() method in RemoteViewsService.RemoteViewsFactory.

public RemoteViews getViewAt(int position) {
    ...
    int remoteViewId;

    if (some condition) {
        remoteViewId = R.layout.highlighted_item;
    } else {
        remoteViewId = R.layout.item;
    }

    RemoteViews rv = new RemoteViews(mContext.getPackageName(), remoteViewId);

This code works when the widget is loaded for the first time, but when updated using notifyAppWidgetViewDataChanged the layout persists and is not changed. How can I update xml layout used for a ListView item?

Upvotes: 1

Views: 923

Answers (1)

s.schleu
s.schleu

Reputation: 1361

Change background

If my assumption is right and you are trying to highlight a list item by changing the background color or something similar I´d suggest to use a selector drawable instead of changing the layout programmatically:

drawable/list_item_selector.xml

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

    <item 
        android:state_activated="true"
        android:drawable="@drawable/list_item_background_activated" />
    
    <item 
        android:state_pressed="true"
        android:drawable="@drawable/list_item_background_pressed" />

    <item
        android:drawable="@drawable/list_item_background" />

</selector>

drawable/list_item_background.xml
drawable/list_item_background_pressed.xml
drawable/list_item_background_activated.xml

Define such a drawable for each state in the selector and replace the 'color' with an appropriate color resource.

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

    <stroke
        android:width="1dp"
        android:color="color" />

</shape>

Apply the list selector to the ListView in the widget´s layout:

<ListView
    android:id="@android:id/list"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:listSelector="@drawable/list_item_selector" />

I use this for my own widget and it works perfectly. For further information on state lists see this link.


Change entire layout

In order to change the entire layout try the following:

public class WidgetListProvider implements RemoteViewsFactory {

    private boolean alternateLayout = 1;

    @Override
    public void onDataSetChanged() {
        
        alternateLayout = alternateLayout == 1 ? 2 : 1;
    }

    @Override
    public RemoteViews getViewAt(int position) {
        
        final RemoteViews rv = new RemoteViews(_context.getPackageName(),
                alternateLayout == 1 ? R.layout.list_row : R.layout.list_row2);

        [...]
        
        return rv;
    }

    @Override
    public int getViewTypeCount() {
        
        return 2;
    }

    [...]    
}    

Important: Note getViewTypeCount() - Because you use two different layouts, you have to return 2 here. If you return 1, a loading view will be displayed for the second layout.

Upvotes: 5

Related Questions