2014-09-07 3 views
0

J'utilise un SQLiteCursorLoader en étendant AsyncTaskLoader avec un fragment de liste, j'ai réussi à conserver la position lorsque de nouvelles données arrivent en sauvegardant la position et la vue, puis j'utilise setSelectionFromTop(), cela fonctionnait parfaitement bien.Conserver la position dans List Fragment après avoir changé le curseur dans Android

Voilà comment cela travaille actuellement,

données DB avant reload du curseur,

Field1 int, timestamp long 
------------------ 
First row, now 
Second row, 1 minute ago 
Third row, 2 minutes ago -----> user is currently on this item in the listview 

DB après rechargement du curseur,

Field1 int, timestamp long 
------------------ 
Fourth row, now 
First row, 30 secon ago 
Second row, 1 minute + 30 seconds ago 
Third row, 2 minutes + 30 seconds ago --> go here using setSelectionFromTop(position, y) 

Après les rechargements de curseur, je conserve la position de la "troisième rangée" comme je sauve l'ancienne position, alors tout ce que je devais faire est de calculer l'ancienne position - le nouveau nombre de curseur

Maintenant j'ai une nouvelle exigence (montrée ci-dessous) où non seulement de nouvelles données viendront, mais aussi de vieilles données changeront qui dérangeront les positions, ce qui changera est l'horodatage des vieilles données, ainsi le résultat de la requête utilisée dans SQLiteCursorLoader sera différente, je ne peux plus utiliser l'ancienne méthode.

Field1 int, timestamp long 
------------------ 
First row, now 
Second row, 1 minute ago 
Third row, 2 minutes ago -----> user is currently on this item in the listview 

DB après rechargement du curseur,

Field1 int, timestamp long 
------------------ 
Third row, now 
First row, 30 secon ago 
Second row, 1 minute + 30 seconds ago 

Comme vous pouvez le voir la position ne sera pas la même chose maintenant. Maintenant, je dois utiliser getItemId pour obtenir l'identifiant de la base de données et l'enregistrer et quand le curseur se rechargera, je devrai le parcourir pour obtenir sa position.

Ma question est, est-il possible de le faire d'une autre manière/plus rapidement?

S'il vous plaît laissez-moi savoir si vous avez besoin de plus de précisions.

Répondre

0

solution pour cela de bloquer sélectivement ListView exposant ses enfants. pourquoi il ne conserve pas sa position est ListView exposant ses enfants pour afficher les nouveaux éléments à l'ancienne position. Si nous arrêtons la passe de mise en page des enfants, nous arrêtons le changement de position visible.

Faire un cutom Listview Widget comme ceci:

public class BlockingListView extends ListView { 

    private boolean mBlockLayoutChildren; 

    public BlockingListView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public void setBlockLayoutChildren(boolean block) { 
     mBlockLayoutChildren = block; 
    } 

    @Override 
    protected void layoutChildren() { 
     if (!mBlockLayoutChildren) { 
      super.layoutChildren(); 
     } 
    } 
} 

Et utiliser ce nouveau widget comme celui-ci ..

int firstVisPos = mListView.getFirstVisiblePosition(); 
View firstVisView = mListView.getChildAt(0); 
int top = firstVisView != null ? firstVisView.getTop() : 0; 

// Block children layout for now 
mListView.setBlockLayoutChildren(true); 

// Number of items added before the first visible item 
int itemsAddedBeforeFirstVisible = ...; 

// Change the cursor, or call notifyDataSetChanged() if not using a Cursor 
mAdapter.swapCursor(...); 

// Let ListView start laying out children again 
mListView.setBlockLayoutChildren(false); 

// Call setSelectionFromTop to change the ListView position 
mListView.setSelectionFromTop(firstVisPos + itemsAddedBeforeFirstVisible, top); 
Questions connexes