Wie kann ich eine horizontale ListView in Android erstellen? [Duplikat

Mögliches Duplizieren:
Horizontal ListView in Android?

Wie viele Dinge in Android, würden Sie nicht denken, dass dies ein so schweres Problem sein würde, aber ohhh, von Gott, würden Sie sich irren. Und wie viele andere Dinge in Android bietet die API nicht einmal einen einigermaßen erweiterbaren Ausgangspunkt. Ich werde verdammt sein, wenn ich meine eigene ListView rollen werde, wenn alles, was ich will, ist, das Ding zu nehmen und es auf die Seite zu legen. \schimpfe

Okay, jetzt wo ich fertig bin, lass uns über das Problem selbst sprechen. Was ich brauche, ist im Grunde genau so etwas wie dasGallery, jedoch ohne Mittenverriegelung. Ich brauche nicht wirklichListView 's listSelector aber es ist schön zu haben. Meistens könnte ich mit einem @ machen was ich wiLinearLayout in einemScrollView, aber ich brauche die untergeordneten Ansichten, um von einem @ zu kommListAdapter und ich hätte echt gerne einen view recycler. Und ichJa wirklic möchte keinen Layout-Code schreiben.

Ich habe für einige dieser Klassen einen Blick in den Quellcode geworfen ...

Galerie Es sieht so aus, als ob ich die Gallery verwenden könnte, wenn ich die meisten 'onXyz'-Methoden überschreibe, den gesamten Quellcode kopiere, aber nicht @ aufrufscrollIntoSlots(). Aber ich bin mir sicher, dass wenn ich das tue, ich auf ein Mitgliedsfeld stoße, auf das nicht zugegriffen werden kann, oder auf eine andere unvorhergesehene Folge.

AbsSpinner: Seit dermRecycler field ist paket-privat. Ich bezweifle, dass ich diese Klasse erweitern kann.

AbsListView: Es sieht so aus, als ob diese Klasse nur für vertikales Scrollen gedacht ist, also gibt es keine Hilfe.

AdapterView: Ich musste diese Klasse noch nie direkt erweitern. Wenn du mir sagst, dass es einfach ist, und dass es einfach ist, mein eigenes @ zu rollRecycleBin, Ich werde sehr skeptisch sein, aber ich werde es versuchen.

Ich nehme an, ich könnte möglicherweise kopierenbeid AbsSpinner undGallery um zu bekommen, was ich will ... hoffentlich verwenden diese Klassen keine paketprivate Variable, auf die ich nicht zugreifen kann. Glaubst du, das ist eine gute Übung? Hat jemand Tutorials oder Lösungen von Drittanbietern, die mich in die richtige Richtung lenken könnten?

Aktualisieren
Die einzige Lösung, die ich bisher gefunden habe, ist, alles selbst zu machen. Seit ich diese Frage gestellt habe, habe ich @ überschriebAdapterView und implementierte meine eigene "HorizontalListView" von Grund auf neu. Die einzige Möglichkeit, die Center-Locking-Funktion der Galerie wirklich zu überschreiben, besteht darin, das private @ zu überschreibescrollIntoSlots -Methode, die meiner Meinung nach zur Laufzeit das Generieren einer Unterklasse erfordern würde. Wenn Sie mutig genug sind, dies zu tun, ist dies wahrscheinlich die beste Lösung, aber ich möchte mich nicht auf undokumentierte Methoden verlassen, die sich ändern könnten.

Swathi EP unten schlug vor, dass ich die @ gebGallery einOnTouchListener und überschreiben Sie die Bildlauffunktion. Wenn es Ihnen egal ist, ob Ihre Liste Schleuderunterstützung enthält, oder ob es in Ordnung ist, wenn die Ansichten am Ende der Schleuderanimation in der Mitte ausgerichtet werden, ist dieseswerde Arbeite für dich! Am Ende erweist es sich jedoch immer noch als unmöglich, die Mittenverriegelung zu entfernen, ohne die Schleuderstütze zu entfernen. Und ich frage dich, welche Art von Liste wirft nicht?

Also leider hat das bei mir nicht geklappt. :-( Aber wenn Sie an diesem Ansatz interessiert sind, lesen Sie weiter ...

Ich musste auch einige Ergänzungen an Swathis Code vornehmen, um das zu bekommen, was ich wollte. ImGestureListener.onTouch, zusätzlich zum Delegieren an den Gesten-Detektor, musste ich auch true für @ zurückgebACTION_UP undACTION_CANCEL Veranstaltungen. Dadurch wurde die Zentralverriegelungsfunktion erfolgreich deaktiviert, aber auch das Schleudern wurde deaktiviert. Ich konnte Fling wieder aktivieren, indem ich meinen eigenen GestureListener-Delegierten bei der Galerie hattonFling Methode. Wenn Sie es ausprobieren möchten, rufen Sie Ihren ApiDemos-Beispielcode auf und ersetzen Sie die Gallery1.java-Klasse durch den folgenden Code:

import com.example.android.apis.R;

import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.GestureDetector;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.View.OnTouchListener;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.Toast;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;

public class Gallery1 extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.gallery_1);

        // Reference the Gallery view
        final Gallery g = (Gallery) findViewById(R.id.gallery);

        // Set the adapter to our custom adapter (below)
        g.setAdapter(new ImageAdapter(this));

        // Set a item click listener, and just Toast the clicked position
        g.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView parent, View v, int position, long id) {
                Toast.makeText(Gallery1.this, "" + position, Toast.LENGTH_SHORT).show();
            }
        });

        // Gesture detection
        final GestureDetector gestureDetector = new GestureDetector(new MyGestureDetector(g));
        OnTouchListener gestureListener = new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                boolean retVal = gestureDetector.onTouchEvent(event);
                int action = event.getAction();
                if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
                    retVal = true;
                    onUp();
                }
                return retVal;
            }

            public void onUp() {
                // Here I am merely copying the Gallery's onUp() method.
                for (int i = g.getChildCount() - 1; i >= 0; i--) {
                    g.getChildAt(i).setPressed(false);
                }
                g.setPressed(false);
            }
        };
        g.setOnTouchListener(gestureListener);

        // We also want to show context menu for longpressed items in the gallery
        registerForContextMenu(g);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        menu.add(R.string.gallery_2_text);
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
        Toast.makeText(this, "Longpress: " + info.position, Toast.LENGTH_SHORT).show();
        return true;
    }

    public class ImageAdapter extends BaseAdapter {
        int mGalleryItemBackground;

        public ImageAdapter(Context c) {
            mContext = c;
            // See res/values/attrs.xml for the <declare-styleable> that defines
            // Gallery1.
            TypedArray a = obtainStyledAttributes(R.styleable.Gallery1);
            mGalleryItemBackground = a.getResourceId(
                    R.styleable.Gallery1_android_galleryItemBackground, 0);
            a.recycle();
        }

        public int getCount() {
            return mImageIds.length;
        }

        public Object getItem(int position) {
            return position;
        }

        public long getItemId(int position) {
            return position;
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            ImageView i = new ImageView(mContext);

            i.setImageResource(mImageIds[position]);
            i.setScaleType(ImageView.ScaleType.FIT_XY);
            i.setLayoutParams(new Gallery.LayoutParams(136, 88));

            // The preferred Gallery item background
            i.setBackgroundResource(mGalleryItemBackground);

            return i;
        }

        private Context mContext;

        private Integer[] mImageIds = {
                R.drawable.gallery_photo_1,
                R.drawable.gallery_photo_2,
                R.drawable.gallery_photo_3,
                R.drawable.gallery_photo_4,
                R.drawable.gallery_photo_5,
                R.drawable.gallery_photo_6,
                R.drawable.gallery_photo_7,
                R.drawable.gallery_photo_8
        };
    }

    public class MyGestureDetector extends SimpleOnGestureListener {

        private Gallery gallery;

        public MyGestureDetector(Gallery gallery) {
            this.gallery = gallery;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 
                float velocityY) {
            return gallery.onFling(e1, e2, velocityX, velocityY);
        }
    }

}

Antworten auf die Frage(16)

Ihre Antwort auf die Frage