Y a-t-il un moyen de conserver la position de défilement lorsque vous modifiez les données d'un ListView
dans un widget?Conserver la position de défilement lors de la modification de la disposition d'un widget ListView
J'utilise actuellement ce code pour mettre à jour les données du widget:
Le fournisseur:
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;
}
}
Le service:
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;
}
}
Le 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;
}
}
Wha t se passe maintenant (il va vers le haut après la mise en page de mise à jour et sauvegarder la position de défilement):