Kryptur
Kryptur

Reputation: 745

Android Widget with ListView Custom Items

I want to create a Widget for my App that displays a few lines of data which is loaded from the web.

I have a widget layout that contains a list view, an AppWidgetProvider, a RemoteViewsService and a RemoteViewsFactory. The service is registered in the manifest.

The problem is that I cannot use customized ListItem layouts. The only thing that works in the public RemoteViews getViewAt(int position) is using the android.R.layout.simple_list_item_1 as done in many basic tutorials. But when I try to use my own layout, I just get a "Loading..." entry for each entry (default loading view).
Here is the layout I would like to use:

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

        <TextView
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="@dimen/cardview_spacing"
            android:layout_marginEnd="@dimen/cardview_spacing"
            android:layout_gravity="center_horizontal"
            android:textSize="@dimen/textTitle"
            android:id="@+id/plan_entry_lesson" />

        <TextView
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="@dimen/cardview_spacing"
            android:layout_marginEnd="@dimen/cardview_spacing"
            android:layout_gravity="center_horizontal"
            android:textSize="@dimen/textTitle"
            android:id="@+id/plan_entry_class" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:layout_gravity="start"
            android:textSize="@dimen/textSmallTitle"
            android:id="@+id/plan_header"
            android:text="@string/plan_header"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/cardview_spacing"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:layout_gravity="start"
            android:id="@+id/plan"
            android:layout_marginLeft="@dimen/cardview_spacing" />


        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:layout_gravity="start"
            android:textSize="@dimen/textSmallTitle"
            android:id="@+id/subst_header"
            android:text="@string/subst_header"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/cardview_spacing"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:layout_gravity="start"
            android:id="@+id/subst"
            android:layout_marginLeft="@dimen/cardview_spacing" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:layout_gravity="start"
            android:textSize="@dimen/textSmallTitle"
            android:id="@+id/comment_header"
            android:text="@string/comment_header"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/cardview_spacing"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:layout_gravity="start"
            android:id="@+id/comment"
            android:layout_marginLeft="@dimen/cardview_spacing" />

    </LinearLayout>
</LinearLayout>

Since the data is loaded asynchronously I suggested that the data was not present at all or something like this, but my debug outputs show, that the data is available and the view I create is not null. However, I can only use the android example list item.

Any suggestions on this?

My getViewTypeCount() returns 1 at the moment! (Not 0 which seems to be a common problem)

For completeness: The RemoteViewsFactory:

public class WidgetDataProvider implements    RemoteViewsService.RemoteViewsFactory {
    private static final String TAG = "WidgetDataProvider";
    private Vplan plan;

    private List<VplanEntry> mCollection = new ArrayList<>();
    private Context mContext = null;

    public WidgetDataProvider(Context context, Intent intent) {
        mContext = context;
        plan = new Vplan(mContext, "today");
    }

    @Override
    public void onCreate() {
        initData();
    }

    @Override
    public void onDataSetChanged() {
        initData();
    }

    @Override
    public void onDestroy() {

    }

    @Override
    public int getCount() {
        return mCollection.size();
    }

    @Override
    public RemoteViews getViewAt(int position) {
        Log.d("WIDGET", "getViewAt "  + position);
        VplanEntry entry = mCollection.get(position);
        Log.d("WIDGET", "entry plan: " + entry.getPlan());

        RemoteViews view = new RemoteViews(mContext.getPackageName(),
                android.R.layout.simple_list_item_1);
        String text = entry.getCls() + " " + entry.getLesson() + ":\n"
                + entry.getPlan() +"\n"
                + entry.getSubstitution() + "\n"
                + entry.getComment();
        view.setTextViewText(android.R.id.text1, text);
        //view.setTextViewText(R.id.plan_entry_lesson, entry.getLesson());

        return view;
    }

    @Override
    public RemoteViews getLoadingView() {
        //return new RemoteViews(mContext.getPackageName(),
        //       R.layout.vplan_appwidget_loading);
        return null;
    }

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

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

    @Override
    public boolean hasStableIds() {
        return true;
    }

    private void initData() {
        mCollection.clear();
        if (plan.isLoaded() && plan.upToDate()) {
            mCollection.clear();
            Log.d("WIDGET", "Data present");
            for (VplanEntry entry : plan.getEntries()) {
                mCollection.add(entry);
            }
            Log.d("WIDGET", "Entries: " + mCollection.size());
            AppWidgetManager awm = AppWidgetManager.getInstance(mContext);
            awm.notifyAppWidgetViewDataChanged(awm.getAppWidgetIds(new ComponentName(mContext, WidgetService.class)), R.id.widgetListView);
        } else {
            Log.d("WIDGET", "Loading started");
            plan.load(new SuccessCallback() {
                @Override
                public void callback(boolean success) {
                    Log.d("WIDGET", "Loading finished: " + success);
                    if (success) {
                        initData();
                    }
                }
            });
        }

    }
}

Upvotes: 2

Views: 830

Answers (1)

Kryptur
Kryptur

Reputation: 745

The problem was that I the layout had a higher width than the minimum required Widget width...

Changing the width resolved the issue.

Upvotes: 1

Related Questions