Android RemoteViews ListView Scroll

前端 未结 4 1900
花落未央
花落未央 2021-01-01 06:01

Im trying to scroll a ListView to a particular position in an AppWidget.

However it does not do anything, i also tried the setPosit

相关标签:
4条回答
  • 2021-01-01 06:40

    I think i have the solution, i use it in my own code. For information, i have some pages & want to show them on demand :

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

    For you, it will be :

    yourListView.setSelection(3);

    Hope it helps...

    EDIT

    I think you should see that... that's older, but maybe that's never changed

    How to make a scrollable app widget?

    0 讨论(0)
  • 2021-01-01 06:40

    Two things:

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

    is the correct call. Internally, setScrollPosition(int, int) calls RemoteViews#setInt(viewId, "smoothScrollToPosition", position);.

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

    So, you are calling the correct method.

    Following is a comment for the method AppWidgetManager#partiallyUpdateAppWidget(int, RemoteViews) - taken from the source code of AppWidgetManager.java. I believe it answers your question: ... 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);
    }
    

    As the comment indicates, call partiallyUpdateAppWidget(appWidgetId, views) after views.setScrollPosition(R.id.lvWidget, 3).

    The comment also warns you: This method will be ignored if a widget has not received a full update via {#updateAppWidget(int[], RemoteViews)}. This might mean that the following calls:

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

    should not be made in one update. I suggest that you break these calls into two separate updates:

    First:

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

    Second:

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

    Note that the first one is a full update, while the second one is only partial.

    0 讨论(0)
  • 2021-01-01 06:50

    Whit the information I have, I think that the widget doesn't invalidate itself so it doesn't so the changes on it. So I would suggest to refresh your widget. There are two ways to do that, the first one is:

    appWidgetManager.updateAppWidget(widgetId, remoteViews);
    

    and there is a second way only in case we don't have direct access to 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);
    }
    

    Like that the changes should be reflected in the widget. If this doesn't work I am gonna need more details to figure out the problem and edit this answer. Hope it helps.

    0 讨论(0)
  • 2021-01-01 06:57

    Issue: ListView does not have any children until it is displayed. Hence calling setScrollPosition right after setting adpater has no effect. Following is the code in AbsListView which does this check:

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

    Solution: Ideally I would have used ViewTreeObserver.OnGlobalLayoutListener for setting the ListView scroll position, but it is not possible in case of remote views. Set the scroll position and invoke partiallyUpdateAppWidget in a runnable with some delay. I've modified the Android weather widget code and shared in 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);
                ...
            }
        }
    }
    

    Here is the screen record. It scrolls to 5th position.

    Auto scrolling of ListView in app widget

    0 讨论(0)
提交回复
热议问题