2017-04-17 2 views
0

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):

enter image description here

Répondre

0

Au lieu d'appeler une nouvelle Service de mettre à jour la mise en page du ListView, vous devez faire un appel à

appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.list_widget); 

dans votre WidgetProvider, et de transmettre les données à votre RemoteViewsFactory par un objet partagé ou sur le terrain.