将 headerView 添加到小部件上的小部件中的 listView 调整大小 android

Posted

技术标签:

【中文标题】将 headerView 添加到小部件上的小部件中的 listView 调整大小 android【英文标题】:Add headerView to listView in widget on widget resize android 【发布时间】:2016-11-17 12:46:21 【问题描述】:

我想用ListView 实现小部件,当用户调整小部件的大小时,我想在列表中添加一个标题。我想实现这样的目标:

    这是初始WidgetView

    当用户调整小部件的大小时,我喜欢实现这一点:

这是布局的代码:

这是行项目的布局 (list_row.xml):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:orientation="horizontal"
    android:background="@android:color/black" >
    <TextView
        android:id="@+id/heading"
        android:layout_
        android:layout_
        android:layout_alignParentLeft="true"
        android:textColor="@color/white"
        android:singleLine="true"
        android:textSize="14sp"
        android:textStyle="bold"
        android:text="Heading"/>
    <TextView
        android:id="@+id/content"
        android:layout_
        android:layout_
        android:layout_alignParentLeft="true"
        android:layout_below="@id/heading"
        android:layout_marginTop="5dip"
        android:textSize="14sp"
        android:text="Content"/>
</RelativeLayout>

这是小部件初始布局的代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:orientation="vertical"
    android:background="@android:color/black" >
    <ListView
        android:id="@+id/listViewWidget"
        android:layout_
        android:layout_
        />
</LinearLayout>

这是表头布局的代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_
    android:layout_
    android:id="@+id/lay2">
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/textView1"
    android:layout_
    android:layout_
    android:layout_alignParentTop="true"
    android:text="Header List View"
    android:textColor="@color/pink"
    android:textAppearance="?android:attr/textAppearanceLarge"
    />
</RelativeLayout>

这是小部件元数据的代码:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/widget_layout"
    android:minHeight="40dip"
    android:minWidth="40dip"
    android:resizeMode="vertical|horizontal"
    android:updatePeriodMillis="1800000"
    >
</appwidget-provider>

这里是小部件提供者的代码:

public class WidgetProvider extends AppWidgetProvider 

@Override
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) 
    //super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);

    // See the dimensions and
    Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);

    // Get min width and height.
    int minWidth = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH);
    int minHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT);

    // Obtain appropriate widget and update it.
    appWidgetManager.updateAppWidget(appWidgetId, getRemoteViews(context, minWidth, minHeight));
    super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);


private RemoteViews getRemoteViews(Context context, int minWidth, int minHeight) 
    // First find out rows and columns based on width provided.
    int rows = getCellsForSize(minHeight);
    int columns = getCellsForSize(minWidth);
    // Now you changing layout base on you column count
    // In this code from 1 column to 4
    // you can make code for more columns on your own.
    switch (rows) 
        case 1:  return new RemoteViews(context.getPackageName(), R.layout.widget_layout);
        case 2:
            //return new RemoteViews(context.getPackageName(), R.layout.activity_layout_widget_4column);
            RemoteViews update2 = new RemoteViews(context.getPackageName(), R.layout.text_view_layout);
            //for(int i = 0; i < 3; i++) 
            RemoteViews textView = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
                //textView.setTextViewText(R.id.textView1, "TextView number " + String.valueOf(i));
            update2.addView(R.id.lay2, textView);
            //

            return update2;
        case 3:
            //return new RemoteViews(context.getPackageName(), R.layout.activity_layout_widget_4column);
            RemoteViews update3 = new RemoteViews(context.getPackageName(), R.layout.text_view_layout);
            //for(int i = 0; i < 3; i++) 
            RemoteViews textView1 = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
            //textView.setTextViewText(R.id.textView1, "TextView number " + String.valueOf(i));
            update3.addView(R.id.lay2, textView1);
            //

            return update3;
        case 4:
            //return new RemoteViews(context.getPackageName(), R.layout.activity_layout_widget_4column);
            RemoteViews update4 = new RemoteViews(context.getPackageName(), R.layout.text_view_layout);
            //for(int i = 0; i < 3; i++) 
            RemoteViews textView3 = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
            //textView.setTextViewText(R.id.textView1, "TextView number " + String.valueOf(i));
            update4.addView(R.id.lay2, textView3);
            //

            return update4;

        default: return null;
    


private static int getCellsForSize(int size) 
    int n = 2;
    while (70 * n - 30 < size) 
        ++n;
    
    return n - 1;



@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) 
    final int N = appWidgetIds.length;
    for (int i = 0; i < N; ++i) 
        RemoteViews remoteViews = updateWidgetListView(context,
                appWidgetIds[i]);
        appWidgetManager.updateAppWidget(appWidgetIds[i],
                remoteViews);
    
    super.onUpdate(context, appWidgetManager, appWidgetIds);



private RemoteViews updateWidgetListView(Context context,
                                         int appWidgetId) 

    //which layout to show on widget
    RemoteViews remoteViews = new RemoteViews(
            context.getPackageName(),R.layout.widget_layout);

    //RemoteViews Service needed to provide adapter for ListView
    Intent svcIntent = new Intent(context, WidgetService.class);
    //passing app widget id to that RemoteViews Service
    svcIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    //setting a unique Uri to the intent
    //don't know its purpose to me right now
    svcIntent.setData(Uri.parse(
            svcIntent.toUri(Intent.URI_INTENT_SCHEME)));
    //setting adapter to listview of the widget
    remoteViews.setRemoteAdapter(appWidgetId, R.id.listViewWidget,
            svcIntent);
    return remoteViews;


这是WidgetService的代码:

public class WidgetService extends RemoteViewsService

    @Override
    public RemoteViewsFactory onGetViewFactory(Intent intent) 
        int appWidgetId = intent.getIntExtra(
            AppWidgetManager.EXTRA_APPWIDGET_ID,
            AppWidgetManager.INVALID_APPWIDGET_ID);
        return (new ListProvider(this.getApplicationContext(), intent));
    

这是ListProvider的代码:

public class ListProvider implements RemoteViewsService.RemoteViewsFactory
    private ArrayList listItemList = new ArrayList();
    private Context context = null;
    private int appWidgetId;

    public ListProvider(Context context, Intent intent) 
        this.context = context;
        appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
            AppWidgetManager.INVALID_APPWIDGET_ID);
        populateListItem();
    

    private void populateListItem() 
        for (int i = 0; i < 6; i++) 
            ListItem listItem = new ListItem();
            listItem.heading = "Heading" + i;
            listItem.content = i + " This is the content of the app widget listview.Nice content though";
            listItemList.add(listItem);
        
    

    @Override
    public int getCount() 
        return listItemList.size();
    

    @Override
    public void onCreate() 
    

    @Override
    public void onDataSetChanged() 
    

    @Override
    public void onDestroy() 
    

    @Override
    public RemoteViews getLoadingView() 
        return null;
    

    @Override
    public int getViewTypeCount() 
        return 1;
    

    @Override
    public boolean hasStableIds() 
        return false;
    

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

    /*
    *Similar to getView of Adapter where instead of View
    *we return RemoteViews
    *
    */
    @Override
    public RemoteViews getViewAt(int position) 
        final RemoteViews remoteView = new RemoteViews(
            context.getPackageName(), R.layout.list_row);
        ListItem listItem = (ListItem)listItemList.get(position);
        remoteView.setTextViewText(R.id.heading, listItem.heading);
        remoteView.setTextViewText(R.id.content, listItem.content);
        return remoteView;
    

这是ListItem的代码:

public class ListItem 
    public String heading,content;

但是在调整大小时我得到了这个结果:

ListView 不见了。有人知道为什么吗?

【问题讨论】:

【参考方案1】:

我的列表视图是空的,因为在 getRemoteViews 方法中我创建了新的 RemoteViews,但我根本没有填充它。所以我对上面的代码做了一些修改:

private RemoteViews getRemoteViews(Context context, int minWidth, int minHeight, int appWidgetId) 
    int rows = getCellsForSize(minHeight);
    int columns = getCellsForSize(minWidth);
    switch (rows) 
        case 1:  return new RemoteViews(context.getPackageName(), R.layout.widget_layout);
        case 2:
            RemoteViews update2 = new RemoteViews(context.getPackageName(), R.layout.text_view_layout);
            RemoteViews textView = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
            update2.addView(R.id.lay2, textView); 
            Intent svcIntent = new Intent(context, WidgetService.class);
            svcIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
            svcIntent.setData(Uri.parse(
                    svcIntent.toUri(Intent.URI_INTENT_SCHEME)));
            update2.setRemoteAdapter(appWidgetId, R.id.listViewWidget,
                    svcIntent);
            return update2;
        case 3:
            RemoteViews update3 = new RemoteViews(context.getPackageName(), R.layout.text_view_layout);
            RemoteViews textView1 = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
            update3.addView(R.id.lay2, textView1);
            Intent svcIntent1 = new Intent(context, WidgetService.class);
            svcIntent1.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
            svcIntent1.setData(Uri.parse(
                    svcIntent1.toUri(Intent.URI_INTENT_SCHEME)));
            update3.setRemoteAdapter(appWidgetId, R.id.listViewWidget,
                    svcIntent1);
            return update3;
        case 4:
            RemoteViews update4 = new RemoteViews(context.getPackageName(), R.layout.text_view_layout);
            RemoteViews textView3 = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
            update4.addView(R.id.lay2, textView3);
            Intent svcIntent2 = new Intent(context, WidgetService.class);
            svcIntent2.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
            svcIntent2.setData(Uri.parse(
            svcIntent2.toUri(Intent.URI_INTENT_SCHEME)));
            update4.setRemoteAdapter(appWidgetId, R.id.listViewWidget,
                    svcIntent2);
            return update4;

        default: return null;
    

【讨论】:

以上是关于将 headerView 添加到小部件上的小部件中的 listView 调整大小 android的主要内容,如果未能解决你的问题,请参考以下文章

iOS将按钮添加到小部件扩展

PyQt5:如何将回溯显示到小部件中?

在 KivyMD 上的小部件之间添加数值

将应用程序目标文件管理器中的文件共享到小部件扩展目标

来自 Room 的小部件中的 setImageViewUri

锁屏上的小部件