Android RemoteViews ListView Scroll

时间:2014-09-02 08:09:35

标签: android

我正在尝试将ListView滚动到AppWidget中的特定位置。

然而,它没有做任何事情,我也尝试了 setPosition 方法,但没有工作。

也没有错误或堆栈跟踪。

代码:

                    if (list.size() == 0) {
                        loadLayout(R.layout.rooster_widget_header);
                        views.addView(R.id.header_container,
                                views);
                    } else {
                        views.setRemoteAdapter(R.id.lvWidget, svcIntent);
                        views.setScrollPosition(R.id.lvWidget, 3);
                    }

4 个答案:

答案 0 :(得分:5)

问题ListView在显示之前没有任何子项。因此,在设置adpater后立即调用setScrollPosition无效。以下是AbsListView中的代码,用于检查:

final int childCount = getChildCount();
if (childCount == 0) {
    // Can't scroll without children.
    return;
}

解决方案:理想情况下,我会使用ViewTreeObserver.OnGlobalLayoutListener来设置ListView滚动位置,但在远程视图的情况下则不可能。设置滚动位置并在运行中调用partiallyUpdateAppWidget并延迟一些。我修改了Android天气小部件代码并在git hub中共享。

public class MyWidgetProvider extends AppWidgetProvider {

    private static HandlerThread sWorkerThread;
    private static Handler sWorkerQueue;

    public MyWidgetProvider() {
        // Start the worker thread
        sWorkerThread = new HandlerThread("MyWidgetProvider-worker");
        sWorkerThread.start();
        sWorkerQueue = new Handler(sWorkerThread.getLooper());
    }

    public void onUpdate(Context context, final AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        for (int i = 0; i < appWidgetIds.length; ++i) {
            ...
            final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
            views.setRemoteAdapter(R.id.lvWidget, svcIntent);

            sWorkerQueue.postDelayed(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    views.setScrollPosition(R.id.list, 3);
                    appWidgetManager.partiallyUpdateAppWidget(appWidgetIds[i], views);
                }

            }, 1000);

            appWidgetManager.updateAppWidget(appWidgetIds[i], views);
            ...
        }
    }
}

这是屏幕记录。它滚动到第5位。

Auto scrolling of ListView in app widget

答案 1 :(得分:0)

我想我有解决方案,我在自己的代码中使用它。 有关信息,我有一些页面&amp;想要按需出示:

getListView().setSelection(((moreServices-1)*20)+1);

对你而言,它将是:

yourListView.setSelection(3);

希望它有所帮助...

修改

我认为你应该看到......那个更老了,但也许永远不会改变

How to make a scrollable app widget?

答案 2 :(得分:0)

根据我的信息,我认为小部件不会使自己无效,所以它不会对其进行更改。所以我建议刷新你的小部件。有两种方法可以做到这一点,第一种方法是:

appWidgetManager.updateAppWidget(widgetId, remoteViews);

并且只有在我们无法直接访问AppWidgetManager

的情况下才有第二种方式
/**
 * Refresh the views on the widget
 * NOTE: Use only in case we dont have direct acces to AppWidgetManager
 */
private void invalidateWidget() {
    ComponentName widget = new ComponentName(this, YourWidgetProvider.class);
    AppWidgetManager manager = AppWidgetManager.getInstance(this);
    manager.updateAppWidget(widget, mRv);
}

就像那样,更改应该反映在小部件中。如果这不起作用,我将需要更多细节来找出问题并编辑这个答案。希望它有所帮助。

答案 3 :(得分:0)

两件事:

views.setScrollPosition(R.id.lvWidget, 3);

是正确的电话。在内部,setScrollPosition(int, int)调用RemoteViews#setInt(viewId, "smoothScrollToPosition", position);

viewId                   :    your ListView's id
"smoothScrollToPosition" :    method name to invoke on the ListView
position                 :    position to scroll to

所以, 调用正确的方法。

以下是对AppWidgetManager#partiallyUpdateAppWidget(int, RemoteViews)方法的评论 - 取自AppWidgetManager.java的源代码。我相信它会回答您的问题:... Use with {RemoteViews#showNext(int)}, {RemoteViews#showPrevious(int)},{RemoteViews#setScrollPosition(int, int)} and similar commands...

/**
 * Perform an incremental update or command on the widget specified by appWidgetId.
 *
 * This update  differs from {@link #updateAppWidget(int, RemoteViews)} in that the RemoteViews
 * object which is passed is understood to be an incomplete representation of the widget, and
 * hence is not cached by the AppWidgetService. Note that because these updates are not cached,
 * any state that they modify that is not restored by restoreInstanceState will not persist in
 * the case that the widgets are restored using the cached version in AppWidgetService.
 *
 * Use with {RemoteViews#showNext(int)}, {RemoteViews#showPrevious(int)},
 * {RemoteViews#setScrollPosition(int, int)} and similar commands.
 *
 * <p>
 * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast,
 * and outside of the handler.
 * This method will only work when called from the uid that owns the AppWidget provider.
 *
 * <p>
 * This method will be ignored if a widget has not received a full update via
 * {@link #updateAppWidget(int[], RemoteViews)}.
 *
 * @param appWidgetId      The AppWidget instance for which to set the RemoteViews.
 * @param views            The RemoteViews object containing the incremental update / command.
 */
public void partiallyUpdateAppWidget(int appWidgetId, RemoteViews views) {
    partiallyUpdateAppWidget(new int[] { appWidgetId }, views);
}

如评论所示,请在partiallyUpdateAppWidget(appWidgetId, views)之后致电views.setScrollPosition(R.id.lvWidget, 3)

评论还警告你:This method will be ignored if a widget has not received a full update via {#updateAppWidget(int[], RemoteViews)}。这可能意味着以下调用:

views.setRemoteAdapter(R.id.lvWidget, svcIntent);
views.setScrollPosition(R.id.lvWidget, 3);

不应在一次更新中进行。我建议你将这些调用分成两个单独的更新:

首先:

views.setRemoteAdapter(R.id.lvWidget, svcIntent);
mAppWidgetManager.updateAppWidget(appWidgetIds, views);

第二

views.setScrollPosition(R.id.lvWidget, 3);
mAppWidgetManager.partiallyUpdateAppWidget(appWidgetId, views);

请注意,第一个是完整更新,而第二个只是部分