在更改窗口小部件中的ListView
数据时,有没有办法保留滚动位置?
我目前正在使用此代码更新小部件的数据:
提供者:
public class OtpListWidgetProvider extends AppWidgetProvider {
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
for (final int widgetId : appWidgetIds) {
final RemoteViews widget = getFirstWidget(context, widgetId);
appWidgetManager.updateAppWidget(widgetId, widget);
}
}
@Override
public void onReceive(final Context context, final Intent intent) {
super.onReceive(context, intent);
if (OtpListWidgetService.ACTION_SHOW_CODE.equals(intent.getAction())) {
int appWidgetId = intent.getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
final int codePosition = intent.getIntExtra(OtpListWidgetService.EXTRA_CODE_POSITION, 0);
final Intent serviceIntent = new Intent(context, OtpListWidgetService.class)
.setAction(OtpListWidgetService.ACTION_SHOW_CODE)
.putExtra(OtpListWidgetService.EXTRA_CODE_POSITION, codePosition);
// Intent.filterEquals doesn't take into account the extras on an Intent,
// so we have to set its data.
serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)));
Toast.makeText(context,
"Calling show with values codePosition=" + codePosition + " appWidgetId=" + appWidgetId,
Toast.LENGTH_SHORT).show();
final RemoteViews widget = getWidgetWithAdapter(context, serviceIntent);
AppWidgetManager.getInstance(context).partiallyUpdateAppWidget(appWidgetId, widget);
}
}
private RemoteViews getFirstWidget(Context context, int widgetId) {
final Intent serviceIntent = new Intent(context, OtpListWidgetService.class);
final RemoteViews widget = getWidgetWithAdapter(context, serviceIntent);
widget.setEmptyView(R.id.list_widget, android.R.id.empty);
final Intent showCodeIntent = new Intent(context, OtpListWidgetProvider.class)
.setAction(OtpListWidgetService.ACTION_SHOW_CODE)
.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
showCodeIntent.setData(Uri.parse(showCodeIntent.toUri(Intent.URI_INTENT_SCHEME)));
final PendingIntent showCodeIntentTemplate =
PendingIntent.getBroadcast(context, 0, showCodeIntent, PendingIntent.FLAG_UPDATE_CURRENT);
widget.setPendingIntentTemplate(R.id.list_widget, showCodeIntentTemplate);
return widget;
}
private RemoteViews getWidgetWithAdapter(Context context, Intent serviceIntent) {
final RemoteViews widget = new RemoteViews(context.getPackageName(), R.layout.list_widget);
widget.setRemoteAdapter(R.id.list_widget, serviceIntent);
return widget;
}
}
服务:
public class OtpListWidgetService extends RemoteViewsService {
public static final String ACTION_SHOW_CODE = "org.fedorahosted.freeotp.widget.ACTION_SHOW_CODE";
public static final String EXTRA_CODE_POSITION = "EXTRA_CODE_POSITION";
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
final OtpListWidgetViewsFactory factory = new OtpListWidgetViewsFactory(getApplicationContext());
boolean shouldShowCode = ACTION_SHOW_CODE.equals(intent.getAction());
if (shouldShowCode) {
int codePosition = intent.getIntExtra(EXTRA_CODE_POSITION, 0);
factory.setCodePositionToShow(codePosition);
}
return factory;
}
}
RemoteViewFactory:
public class OtpListWidgetViewsFactory implements RemoteViewsService.RemoteViewsFactory {
private final Context context;
private final TokenPersistence persistence;
private int showCodePosition;
private boolean shouldShowCode;
public OtpListWidgetViewsFactory(final Context context) {
this.context = context;
persistence = new TokenPersistence(context);
}
@Override
public int getCount() {
return persistence.length();
}
@Override
public RemoteViews getViewAt(int position) {
final Token token = persistence.get(position);
final RemoteViews row = new RemoteViews(context.getPackageName(), R.layout.widget_row);
try {
Bitmap b = Picasso.with(context).load(token.getImage()).get();
if (b == null) {
row.setImageViewResource(R.id.widget_image, R.drawable.logo);
} else {
row.setImageViewBitmap(R.id.widget_image, b);
}
} catch (IOException e) {
e.printStackTrace();
}
final String code;
if (shouldShowCode && showCodePosition == position) {
code = token.generateCodes().getCurrentCode();
} else {
code = "------";
}
row.setTextViewText(R.id.widget_code, code);
row.setTextViewText(R.id.widget_issuer, token.getIssuer());
row.setTextViewText(R.id.widget_label, token.getLabel());
final Intent intent = new Intent();
intent.putExtra(OtpListWidgetService.EXTRA_CODE_POSITION, position);
row.setOnClickFillInIntent(R.id.widget_row_container, intent);
return row;
}
public void setCodePositionToShow(int codePosition) {
shouldShowCode = true;
showCodePosition = codePosition;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getViewTypeCount() {
return 1;
}
@Override
public void onCreate() {
// no-op
}
@Override
public void onDataSetChanged() {
// no-op
}
@Override
public void onDestroy() {
// no-op
}
@Override
public RemoteViews getLoadingView() {
return null;
}
@Override
public boolean hasStableIds() {
return true;
}
}
现在发生了什么(在更新布局后,它会转到顶部,并保存滚动位置):
答案 0 :(得分:0)
您应该拨打
,而不是调用新的Service
来更新ListView
的布局。
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.list_widget);
在WidgetProvider
中,并通过共享对象或字段将数据传递给RemoteViewsFactory
。