Android RemoteViews ListView Scroll
Я пытаюсь прокрутить 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 ответа
Выпуск: ListView
не имеет детей, пока не отобразится. Отсюда зовет setScrollPosition
сразу после установки adpater не действует. Ниже приведен код в 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 позицию.
Две вещи:
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);
Обратите внимание, что первый является полным обновлением, а второй только частичным.
Что касается имеющейся у меня информации, то я думаю, что виджет не делает себя недействительным, поэтому не вносит изменений в него. Поэтому я бы предложил обновить ваш виджет. Есть два способа сделать это, первый:
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);
}
Так что изменения должны быть отражены в виджете. Если это не сработает, мне нужно больше деталей, чтобы выяснить проблему и отредактировать этот ответ. Надеюсь, поможет.
Я думаю, что у меня есть решение, я использую его в своем собственном коде. Для информации у меня есть несколько страниц, и я хочу показать их по запросу:
getListView().setSelection(((moreServices-1)*20)+1);
Для вас это будет:
yourListView.setSelection(3)
;
Надеюсь, поможет...
РЕДАКТИРОВАТЬ
Я думаю, вы должны это видеть... это старше, но, возможно, это никогда не менялось