57 votes

Comment créer un ListView fermé (circulaire)?

Je veux créer et personnaliser une ListView (ou similaire) qui se comporte comme un fermé (circulaire):

  1. le défilement vers le bas après le dernier point a été atteint la première commence (.., n-1, n, 1, 2, ..)
  2. défilement vers le haut après le premier point a été atteint le dernier commence (.., 2, 1, n, n-1, ..)

Cela paraît simple sur le plan conceptuel, mais, apparemment, il n'y a pas de façon simple de le faire. Quelqu'un peut-il m'indiquer la bonne solution ? Merci!!!!

J'ai déjà reçu une réponse (dans les Rues De Boston sur Android, les Développeurs de google groups), mais il sonne comme quelque chose de beau :) -

Je l'ai fait en créant mon propre liste de l'adaptateur (sous-classé de BaseAdapter).

J'ai codé mon propre liste de l'adaptateur dans une telle manière à ce que son getCount() la méthode retourne un HUUUUGE nombre.

Et si l'élément " x " est sélectionné, puis ce élément correspond à la carte position='adaptateur.getCount()/2+x'

Et pour mon adaptateur méthode getItem(int position), je regarde dans mon tableau qui que la sauvegarde de la carte et chercher le point sur l'index: (position-getCount()/2) % myDataItems.longueur

Vous avez besoin de faire un peu plus "spécial" des trucs pour les faire fonctionner correctement, mais vous obtenez l'idée.

En principe, il est toujours possible de atteindre la fin ou le début de la liste, mais si vous définissez getCount() pour autour d'un millions de dollars, ou alors, c'est dur à faire :-)

84voto

Dawson Points 663

Mon collègue Joe, et je crois que nous avons trouvé un moyen plus simple de résoudre le même problème. Dans notre solution, bien qu'au lieu de l'extension de BaseAdapter nous prolongeons ArrayAdapter.

Le code est comme la jachère :


public class CircularArrayAdapter extends ArrayAdapter
{   

        public static final int HALF_MAX_VALUE = Integer.MAX_VALUE/2;
        public final int MIDDLE;
        private T[] objects;

        public CircularArrayAdapter(Context context, int textViewResourceId, T[] objects)
        {
            super(context, textViewResourceId, objects);
            this.objects = objects;
            MIDDLE = HALF_MAX_VALUE - HALF_MAX_VALUE % objects.length;
        }

        @Override
        public int getCount()
        {
            return Integer.MAX_VALUE;
        }

        @Override
        public T getItem(int position) 
        {
            return objects[position % objects.length];
        }
 }

Donc, cela crée une classe appelée CircularArrayAdapter qui prend un objet de type T (qui peut être n'importe quoi) et l'utilise pour créer une liste de tableau. T est généralement une chaîne de caractères si peut-être rien.

Le constructeur est la même pour ArrayAdapter si initialise une constante appelée milieu. C'est le milieu de la liste. Quelle que soit la longueur de la rangée du MILIEU peut être utilisé pour le centre de la ListView dans le milieu de la liste.

getCount est surdéfinie pour retourner une valeur énorme, comme on le fait au-dessus de la création d'une liste énorme.

getItem est surdéfinie de retour de la fausse position sur le tableau. Ainsi, lors du remplissage de la liste la liste est rempli avec des objets dans une boucle.

À ce stade, CircularArrayAdapter remplace simplement ArrayAdapter dans le fichier de la création de la Liste.

Au centre de la ListView la mise en jachère de la ligne doit être insérée dans votre fichier de création de la liste après la liste de l'objet a été initialisé:

listViewObject.setSelectionFromTop(nameOfAdapterObject.MIDDLE, 0);

et du MILIEU de la constante précédemment initialisé pour la liste de la vue est centrée par rapport au premier élément de la liste en haut de l'écran.

: ) ~ Encouragements, j'espère que cette solution est utile.

13voto

Romain Guy Points 57114

La solution que vous avez mentionnée est celle que j’avais dite aux autres développeurs d’utiliser par le passé. Dans getCount (), renvoyez simplement Integer.MAX_VALUE, il vous donnera environ 2 milliards d'éléments, ce qui devrait suffire.

9voto

Harry Points 61

J'ai, ou je pense que j'ai fait, sur la base des réponses ci-dessus. Espérons que cela vous aidera.

private static class RecipeListAdapter extends BaseAdapter {
    private static LayoutInflater   mInflater;
    private Integer[]               mCouponImages;
    private static ImageView        viewHolder;
    public RecipeListAdapter(Context c, Integer[] coupomImages) {
        RecipeListAdapter.mInflater = LayoutInflater.from(c);
        this.mCouponImages = coupomImages;
    }
    @Override
    public int getCount() {
        return Integer.MAX_VALUE;
    }

    @Override
    public Object getItem(int position) {
       // you can do your own tricks here. to let it display the right item in your array.
        return position % mCouponImages.length;
    }

    @Override
    public long getItemId(int position) {
        return position;
        // return position % mCouponImages.length;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.coupon_list_item, null);
            viewHolder = (ImageView) convertView.findViewById(R.id.item_coupon);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ImageView) convertView.getTag();
        }

        viewHolder.setImageResource(this.mCouponImages[position %     mCouponImages.length]);
        return convertView;
    }

}

Et vous souhaitez le faire si vous voulez faire défiler la liste vers le bas. Communément, nous pouvons suffit de faire défiler et de la liste puis faites défiler vers le bas.

// voir combien d'articles que nous aimerions sroll. dans ce cas, Entier.MAX_VALUE

int listViewLength = adapter.getCount();

// see how many items a screen can dispaly, I use variable "span"
    final int span = recipeListView.getLastVisiblePosition() - recipeListView.getFirstVisiblePosition();

// voir combien de pages, nous avons

int howManySpans = listViewLength / span;

// voir où voulez-vous être dès le début de la liste. vous n'avez pas à faire de la "-3" choses". c'est pour mon application a droit.

recipeListView.setSelection((span * (howManySpans / 2)) - 3);

1voto

ViliusK Points 1257

Si vous utilisez LoadersCallbacks, j'ai créé la classe MyCircularCursor qui enveloppe le curseur typique de la manière suivante:

 @Override
public void onLoadFinished(Loader<Cursor> pCursorLoader, Cursor pCursor) {
        mItemListAdapter.swapCursor(new MyCircularCursor(pCursor));
}
 

le code de classe de décorateur est ici:

 /**
 * {@link MyCircularCursor}<br/>
 * <br/>
 * @author Vilius Kraujutis
 * @since 31 Jan 2013 02:09:48
 *
 */
public class MyCircularCursor implements Cursor {

private Cursor mCursor;

/**
 * @param pCursor
 */
public MyCircularCursor(Cursor pCursor) {
    mCursor = pCursor;
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#getCount()
 */
@Override
public int getCount() {
    return mCursor.getCount() == 0 ? 0 : Integer.MAX_VALUE;
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#getPosition()
 */
@Override
public int getPosition() {
    return mCursor.getPosition();
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#move(int)
 */
@Override
public boolean move(int pOffset) {
    return mCursor.move(pOffset);
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#moveToPosition(int)
 */
@Override
public boolean moveToPosition(int pPosition) {
    int position = MathUtils.mod(pPosition, mCursor.getCount());
    return mCursor.moveToPosition(position);
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#moveToFirst()
 */
@Override
public boolean moveToFirst() {
    return mCursor.moveToFirst();
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#moveToLast()
 */
@Override
public boolean moveToLast() {
    return mCursor.moveToLast();
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#moveToNext()
 */
@Override
public boolean moveToNext() {
    if (mCursor.isLast()) {
        mCursor.moveToFirst();
        return true;
    } else {
        return mCursor.moveToNext();
    }
    // return mCursor.moveToNext();
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#moveToPrevious()
 */
@Override
public boolean moveToPrevious() {
    if (mCursor.isFirst()) {
        mCursor.moveToLast();
        return true;
    } else {
        return mCursor.moveToPrevious();
    }
    // return mCursor.moveToPrevious();
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#isFirst()
 */
@Override
public boolean isFirst() {
    // return mCursor.isFirst();
    return false;
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#isLast()
 */
@Override
public boolean isLast() {
    return false;
    // return mCursor.isLast();
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#isBeforeFirst()
 */
@Override
public boolean isBeforeFirst() {
    return false;
    // return mCursor.isBeforeFirst();
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#isAfterLast()
 */
@Override
public boolean isAfterLast() {
    return false;
    // return mCursor.isAfterLast();
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#getColumnIndex(java.lang.String)
 */
@Override
public int getColumnIndex(String pColumnName) {
    return mCursor.getColumnIndex(pColumnName);
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#getColumnIndexOrThrow(java.lang.String)
 */
@Override
public int getColumnIndexOrThrow(String pColumnName) throws IllegalArgumentException {

    return mCursor.getColumnIndexOrThrow(pColumnName);
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#getColumnName(int)
 */
@Override
public String getColumnName(int pColumnIndex) {

    return mCursor.getColumnName(pColumnIndex);
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#getColumnNames()
 */
@Override
public String[] getColumnNames() {

    return mCursor.getColumnNames();
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#getColumnCount()
 */
@Override
public int getColumnCount() {

    return mCursor.getColumnCount();
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#getBlob(int)
 */
@Override
public byte[] getBlob(int pColumnIndex) {

    return mCursor.getBlob(pColumnIndex);
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#getString(int)
 */
@Override
public String getString(int pColumnIndex) {

    return mCursor.getString(pColumnIndex);
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#getShort(int)
 */
@Override
public short getShort(int pColumnIndex) {

    return mCursor.getShort(pColumnIndex);
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#getInt(int)
 */
@Override
public int getInt(int pColumnIndex) {

    return mCursor.getInt(pColumnIndex);
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#getLong(int)
 */
@Override
public long getLong(int pColumnIndex) {

    return mCursor.getLong(pColumnIndex);
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#getFloat(int)
 */
@Override
public float getFloat(int pColumnIndex) {

    return mCursor.getFloat(pColumnIndex);
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#getDouble(int)
 */
@Override
public double getDouble(int pColumnIndex) {

    return mCursor.getDouble(pColumnIndex);
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#getType(int)
 */
@Override
public int getType(int pColumnIndex) {
    // return mCursor.getType(pColumnIndex);
    return 0;
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#isNull(int)
 */
@Override
public boolean isNull(int pColumnIndex) {

    return mCursor.isNull(pColumnIndex);
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#deactivate()
 */
@Override
public void deactivate() {
    mCursor.deactivate();
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#requery()
 */
@Override
@Deprecated
public boolean requery() {

    return mCursor.requery();
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#close()
 */
@Override
public void close() {
    mCursor.close();
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#isClosed()
 */
@Override
public boolean isClosed() {

    return mCursor.isClosed();
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#registerContentObserver(android.database.ContentObserver)
 */
@Override
public void registerContentObserver(ContentObserver pObserver) {
    mCursor.registerContentObserver(pObserver);
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#unregisterContentObserver(android.database.ContentObserver)
 */
@Override
public void unregisterContentObserver(ContentObserver pObserver) {
    mCursor.unregisterContentObserver(pObserver);
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#registerDataSetObserver(android.database.DataSetObserver)
 */
@Override
public void registerDataSetObserver(DataSetObserver pObserver) {
    mCursor.registerDataSetObserver(pObserver);
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#unregisterDataSetObserver(android.database.DataSetObserver)
 */
@Override
public void unregisterDataSetObserver(DataSetObserver pObserver) {
    mCursor.unregisterDataSetObserver(pObserver);
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#setNotificationUri(android.content.ContentResolver,
 * android.net.Uri)
 */
@Override
public void setNotificationUri(ContentResolver pCr, Uri pUri) {
    mCursor.setNotificationUri(pCr, pUri);
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#getWantsAllOnMoveCalls()
 */
@Override
public boolean getWantsAllOnMoveCalls() {

    return mCursor.getWantsAllOnMoveCalls();
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#getExtras()
 */
@Override
public Bundle getExtras() {

    return mCursor.getExtras();
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#respond(android.os.Bundle)
 */
@Override
public Bundle respond(Bundle pExtras) {

    return mCursor.respond(pExtras);
}

/*
 * (non-Javadoc)
 * @see android.database.Cursor#copyStringToBuffer(int, android.database.CharArrayBuffer)
 */
@Override
public void copyStringToBuffer(int pColumnIndex, CharArrayBuffer pBuffer) {
    mCursor.copyStringToBuffer(pColumnIndex, pBuffer);

}

}
 

1voto

Wesley Points 852

Je pouvais voir de bonnes réponses à cela. Un de mes amis a essayé d'y parvenir via une solution simple. Vérifiez le projet github .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X