Wie erstelle ich eine horizontale Listenansicht mit RecyclerView?

336

Ich muss eine horizontale Listenansicht in meiner Android-Anwendung implementieren. Ich habe ein bisschen recherchiert und bin auf Wie kann ich eine horizontale ListView in Android erstellen? und horizontale ListView in Android?Diese Fragen wurden jedoch gestellt, bevor Recyclerview veröffentlicht wurde. Gibt es eine bessere Möglichkeit, dies jetzt mit Recyclerview zu implementieren?

Andre Perkins
quelle
12
Verwenden Sie einfach eine LinearLayoutManagermit Ausrichtung auf HORIZONTAL.
Egor Neliuba
@EgorN Ich habe das versucht, es macht es horizontal, aber es scheint, dass es sogar die untergeordneten Elemente der Adapterzeile in horizontal ändert. Ich habe ein RelativeLayout. Ich bin nicht sicher, wie ich das beheben soll.
Muhammad Umar

Antworten:

738

Gibt es eine bessere Möglichkeit, dies jetzt mit Recyclerview zu implementieren?

Ja.

Wenn Sie a verwenden RecyclerView, müssen Sie a angeben LayoutManager, das für das Layout jedes Elements in der Ansicht verantwortlich ist. Mit LinearLayoutManagerkönnen Sie eine Ausrichtung festlegen, wie dies bei einem normalen LinearLayoutGerät der Fall wäre.

Um eine horizontale Liste mit zu erstellen RecyclerView, können Sie Folgendes tun:

LinearLayoutManager layoutManager
    = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);

RecyclerView myList = (RecyclerView) findViewById(R.id.my_recycler_view);
myList.setLayoutManager(layoutManager);
Bryan Herbst
quelle
Ich habe das versucht, es macht es horizontal, aber es scheint, dass es sogar die Kinder der Adapterzeile in horizontal ändert. Ich habe ein RelativeLayout. Ich bin nicht sicher, wie ich das beheben soll.
Muhammad Umar
2
RelativeLayouthat kein Konzept von horizontal gegen vertikal, daher verstehe ich die Frage nicht wirklich.
Bryan Herbst
2
Anscheinend gibt es einige Probleme mit RecyclerView und dem horizontal scrollenden LayoutManager ... code.google.com/p/android/issues/detail?id=74772 - habe es gefunden, weil ich auch
Probleme hatte
Zainodis, hast du herausgefunden, was du dann verwenden sollst? LinearLayoutManager wird für mich nicht einmal als Import angezeigt? Vermisse ich etwas
Lion789
@ Tanis.7x Das funktioniert gut für mich, aber es füllt die Liste von links nach rechts. Weiß jemand, ob es eine Möglichkeit gibt, von rechts nach links zu füllen? (Das erste Element befindet sich ganz rechts in der Liste, das Element in Index 1 befindet sich dann links usw.)
erhöht
169
 <android.support.v7.widget.RecyclerView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
Gekochtes Wasser
quelle
Wie stelle ich dann den LayoutManager ein?
Kai Wang
@kaiwang pls siehe oben "Tanis.7x" Antwort.
gekochtes Wasser
app:layoutManager="android.support.v7.widget.LinearLayoutManager"funktioniert nicht für Release Build. Ich habe dieses Problem Release Build konfrontiert.
Abu Yousuf
Ich suchte nach einer Möglichkeit, dies im Interface Builder anzuzeigen. tools: Orientierung = "horizontal" Werkzeuge: layoutManager = "android.support.v7.widget.LinearLayoutManager" hat mich gerettet, danke.
Mohammad Tabbara
'<androidx.recyclerview.widget.RecyclerView android: layout_width = "match_parent" android: layout_height = "70dp" android: layout_gravity = "bottom" android: orientierung = "horizontal" app: layoutManager = "androidx.recyclerview.widget.LinearLayoutManager" /> '
Yanny
74

Vollständiges Beispiel

Geben Sie hier die Bildbeschreibung ein

Der einzige wirkliche Unterschied zwischen einem vertikalen RecyclerViewund einem horizontalen besteht darin, wie Sie das einrichten LinearLayoutManager. Hier ist das Code-Snippet. Das vollständige Beispiel finden Sie unten.

LinearLayoutManager horizontalLayoutManagaer = new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(horizontalLayoutManagaer);

Dieses ausführlichere Beispiel ist meiner vertikalen RecyclerViewAntwort nachempfunden .

Aktualisieren Sie Gradle-Abhängigkeiten

Stellen Sie sicher, dass die folgenden Abhängigkeiten in Ihrer App- gradle.buildDatei enthalten sind:

implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:recyclerview-v7:27.1.1'

Sie können die Versionsnummern auf die aktuellsten aktualisieren .

Aktivitätslayout erstellen

Fügen Sie das RecyclerViewIhrem XML-Layout hinzu.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rvAnimals"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>

Elementlayout erstellen

Jeder Artikel in unserem RecyclerViewwird ein einzelnes ein farbiges Viewüber ein haben TextView. Erstellen Sie eine neue Layoutressourcendatei.

recyclerview_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="10dp">

    <View
        android:id="@+id/colorView"
        android:layout_width="100dp"
        android:layout_height="100dp"/>

    <TextView
        android:id="@+id/tvAnimalName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"/>

</LinearLayout>

Erstellen Sie den Adapter

Sie RecyclerViewbenötigen einen Adapter, um die Ansichten in jeder Zeile (horizontales Element) mit Ihren Daten zu füllen. Erstellen Sie eine neue Java-Datei.

MyRecyclerViewAdapter.java

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {

    private List<Integer> mViewColors;
    private List<String> mAnimals;
    private LayoutInflater mInflater;
    private ItemClickListener mClickListener;

    // data is passed into the constructor
    MyRecyclerViewAdapter(Context context, List<Integer> colors, List<String> animals) {
        this.mInflater = LayoutInflater.from(context);
        this.mViewColors = colors;
        this.mAnimals = animals;
    }

    // inflates the row layout from xml when needed
    @Override
    @NonNull
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = mInflater.inflate(R.layout.recyclerview_item, parent, false);
        return new ViewHolder(view);
    }

    // binds the data to the view and textview in each row
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        int color = mViewColors.get(position);
        String animal = mAnimals.get(position);
        holder.myView.setBackgroundColor(color);
        holder.myTextView.setText(animal);
    }

    // total number of rows
    @Override
    public int getItemCount() {
        return mAnimals.size();
    }

    // stores and recycles views as they are scrolled off screen
    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        View myView;
        TextView myTextView;

        ViewHolder(View itemView) {
            super(itemView);
            myView = itemView.findViewById(R.id.colorView);
            myTextView = itemView.findViewById(R.id.tvAnimalName);
            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
        }
    }

    // convenience method for getting data at click position
    public String getItem(int id) {
        return mAnimals.get(id);
    }

    // allows clicks events to be caught
    public void setClickListener(ItemClickListener itemClickListener) {
        this.mClickListener = itemClickListener;
    }

    // parent activity will implement this method to respond to click events
    public interface ItemClickListener {
        void onItemClick(View view, int position);
    }
}

Anmerkungen

  • Obwohl dies nicht unbedingt erforderlich ist, habe ich die Funktionalität zum Abhören von Klickereignissen für die Elemente hinzugefügt. Dies war in der alten verfügbar ListViewsund ist ein allgemeines Bedürfnis. Sie können diesen Code entfernen, wenn Sie ihn nicht benötigen.

Initialisieren Sie RecyclerView in Aktivität

Fügen Sie Ihrer Hauptaktivität den folgenden Code hinzu.

MainActivity.java

public class MainActivity extends AppCompatActivity implements MyRecyclerViewAdapter.ItemClickListener {

    private MyRecyclerViewAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // data to populate the RecyclerView with
        ArrayList<Integer> viewColors = new ArrayList<>();
        viewColors.add(Color.BLUE);
        viewColors.add(Color.YELLOW);
        viewColors.add(Color.MAGENTA);
        viewColors.add(Color.RED);
        viewColors.add(Color.BLACK);

        ArrayList<String> animalNames = new ArrayList<>();
        animalNames.add("Horse");
        animalNames.add("Cow");
        animalNames.add("Camel");
        animalNames.add("Sheep");
        animalNames.add("Goat");

        // set up the RecyclerView
        RecyclerView recyclerView = findViewById(R.id.rvAnimals);
        LinearLayoutManager horizontalLayoutManager
                = new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, false);
        recyclerView.setLayoutManager(horizontalLayoutManager);
        adapter = new MyRecyclerViewAdapter(this, viewColors, animalNames);
        adapter.setClickListener(this);
        recyclerView.setAdapter(adapter);
    }

    @Override
    public void onItemClick(View view, int position) {
        Toast.makeText(this, "You clicked " + adapter.getItem(position) + " on item position " + position, Toast.LENGTH_SHORT).show();
    }
}

Anmerkungen

  • Beachten Sie, dass die Aktivität das implementiert ItemClickListener, was wir in unserem Adapter definiert haben. Auf diese Weise können wir Artikelklickereignisse in verarbeiten onItemClick.

Fertig

Das ist es. Sie sollten jetzt in der Lage sein, Ihr Projekt auszuführen und etwas Ähnliches wie das Bild oben zu erhalten.

Anmerkungen

Suragch
quelle
12

Wenn Sie a RecyclerViewmit dem verwenden möchten, können Sie auf GridLayoutManagerdiese Weise einen horizontalen Bildlauf durchführen.

recyclerView.setLayoutManager(
new GridLayoutManager(recyclerView.getContext(), rows, GridLayoutManager.HORIZONTAL, false));
José Cabrera
quelle
Das funktioniert gut für mich ... hauptsächlich, weil Sie die Zeilennummer festlegen können ... ist es möglich, dies auch im LinearLayoutManager zu tun?
SuperUser
9

Der Versuch, eine horizontale ListView zu erstellen, nimmt zu viel Zeit in Anspruch. Ich habe es auf zwei Arten gelöst.

1.Mit einem ViewPager, dessen Adapter von PagerAdapter ausgeht.

2. Verwenden Sie RecyclerView wie oben. Sie müssen LayoutManager wie im folgenden Code anwenden:

LinearLayoutManager layoutManager
    = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);

RecyclerView myList = (RecyclerView) findViewById(R.id.my_recycler_view);
myList.setLayoutManager(layoutManager);
Jayman Jani
quelle
6

Wenn Sie die horizontale Recycler-Ansicht als ViewPager verwenden möchten, ist dies jetzt mit Hilfe von möglich LinearSnapHelper die Support Library Version 24.2.0 hinzugefügt wird.

Fügen Sie zunächst RecyclerView zu Ihrer Aktivität / Ihrem Fragment hinzu

<android.support.v7.widget.RecyclerView
        android:layout_below="@+id/sign_in_button"
        android:layout_width="match_parent"
        android:orientation="horizontal"
        android:id="@+id/blog_list"
        android:layout_height="match_parent">
    </android.support.v7.widget.RecyclerView>

In meinem Fall habe ich ein CardViewInside the verwendetRecyclerView

blog_row.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView 

    xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_margin="15dp"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:orientation="vertical">

            <com.android.volley.toolbox.NetworkImageView
                android:id="@+id/imageBlogPost"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:adjustViewBounds="true"
                android:paddingBottom="15dp"
                android:src="@drawable/common_google_signin_btn_text_light_normal" />

            <TextView
                android:id="@+id/TitleTextView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
               android:layout_marginBottom="20dp"

                android:text="Post Title Here"
                android:textSize="16sp" />

            <TextView
                android:id="@+id/descriptionTextView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Post Description Here"
                android:paddingBottom="15dp"
                android:textSize="14sp" />
        </LinearLayout>

    </android.support.v7.widget.CardView>

In Ihrer Aktivität / Fragment

    private RecyclerView mBlogList;




 LinearLayoutManager layoutManager
                    = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
            mBlogList = (RecyclerView) findViewById(R.id.blog_list);

            mBlogList.setHasFixedSize(true);
            mBlogList.setLayoutManager(layoutManager);

LinearSnapHelper snapHelper = new LinearSnapHelper() {
            @Override
            public int findTargetSnapPosition(RecyclerView.LayoutManager lm, int velocityX, int velocityY) {
                View centerView = findSnapView(lm);
                if (centerView == null)
                    return RecyclerView.NO_POSITION;

                int position = lm.getPosition(centerView);
                int targetPosition = -1;
                if (lm.canScrollHorizontally()) {
                    if (velocityX < 0) {
                        targetPosition = position - 1;
                    } else {
                        targetPosition = position + 1;
                    }
                }

                if (lm.canScrollVertically()) {
                    if (velocityY < 0) {
                        targetPosition = position - 1;
                    } else {
                        targetPosition = position + 1;
                    }
                }

                final int firstItem = 0;
                final int lastItem = lm.getItemCount() - 1;
                targetPosition = Math.min(lastItem, Math.max(targetPosition, firstItem));
                return targetPosition;
            }
        };
        snapHelper.attachToRecyclerView(mBlogList);

Der letzte Schritt besteht darin, den Adapter auf RecyclerView einzustellen

mBlogList.setAdapter(firebaseRecyclerAdapter);
AndroidBeginner
quelle
4

Mit der Veröffentlichung der RecyclerView-Bibliothek können Sie jetzt eine Liste von Bildern, die mit Text verbunden sind, einfach ausrichten. Mit LinearLayoutManager können Sie die Richtung angeben, in der Sie Ihre Liste entweder vertikal oder horizontal ausrichten möchten, wie unten gezeigt.

Geben Sie hier die Bildbeschreibung ein

Sie können eine voll funktionsfähige Demo von diesem Beitrag herunterladen

Daniel Nyamasyo
quelle
2
 <HorizontalScrollView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            >
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal"
            android:scrollbars="vertical|horizontal" />
        </HorizontalScrollView>

    import androidx.appcompat.app.AppCompatActivity;
    import android.content.Context;
    import android.content.ContextWrapper;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.os.Environment;
    import android.view.View;
    import android.widget.ImageView;
    import android.widget.Toast;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    public class MainActivity extends AppCompatActivity
     {
        ImageView mImageView1;
        Bitmap bitmap;
        String mSavedInfo;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mImageView1 = (ImageView) findViewById(R.id.image);
        }
        public Bitmap getBitmapFromURL(String src) {
            try {
                java.net.URL url = new java.net.URL(src);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setDoInput(true);
                connection.connect();
                InputStream input = connection.getInputStream();
                Bitmap myBitmap = BitmapFactory.decodeStream(input);
                return myBitmap;
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
        public void button2(View view) {
            new DownloadImageFromTherad().execute();
        }
        private class DownloadImageFromTherad extends AsyncTask<String, Integer, String> {
            @Override
            protected String doInBackground(String... params) {
                bitmap = getBitmapFromURL("https://cdn.pixabay.com/photo/2016/08/08/09/17/avatar-1577909_960_720.png");
                return null;
            }

            @Override
            protected void onPostExecute(String s) {
                super.onPostExecute(s);
                File sdCardDirectory = Environment.getExternalStorageDirectory();
                File image = new File(sdCardDirectory, "test.png");
                boolean success = false;
                FileOutputStream outStream;
                mSavedInfo = saveToInternalStorage(bitmap);
                if (success) {
                    Toast.makeText(getApplicationContext(), "Image saved with success", Toast.LENGTH_LONG).show();
                } else {
                    Toast.makeText(getApplicationContext(), "Error during image saving" + mSavedInfo, Toast.LENGTH_LONG).show();
                }
            }
        }
        private String saveToInternalStorage(Bitmap bitmapImage) {
            ContextWrapper cw = new ContextWrapper(getApplicationContext());
            // path to /data/data/yourapp/app_data/imageDir
            File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
            File mypath = new File(directory, "profile.jpg");
            FileOutputStream fos = null;
            try {
                fos = new FileOutputStream(mypath);
                bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return directory.getAbsolutePath();
        }
        private void loadImageFromStorage(String path) {
            try {
                File f = new File(path, "profile.jpg");
                Bitmap b = BitmapFactory.decodeStream(new FileInputStream(f));
                mImageView1.setImageBitmap(b);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
        public void showImage(View view) {
            loadImageFromStorage(mSavedInfo);
        }
    }
Syed Danish Haider
quelle
1

Es gibt eine RecyclerView-Unterklasse mit dem Namen HorizontalGridView , mit der Sie die horizontale Richtung festlegen können. VerticalGridView für die vertikale Richtung

Andrew Luca
quelle
5
Ist HorizontalGridView überhaupt für Nicht-TV-Geräte gedacht? Afaik die Leanback-Bibliothek ist für Fernseher
gedacht
2
Wenn Sie Leanback verwenden, wird die minSdkVersion Ihrer App auf 17
Jemand irgendwo am
1

Es ist sowohl für horizontal als auch für vertikal.

RecyclerView recyclerView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_recycler);
    recyclerView = (RecyclerView)findViewById(R.id.recyclerViewId);

    RecyclAdapter adapter = new RecyclAdapter();

    //Vertical RecyclerView
    RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
    recyclerView.setLayoutManager(mLayoutManager);

    //Horizontal RecyclerView
    //recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext(),LinearLayoutManager.HORIZONTAL,false));

    recyclerView.setAdapter(adapter);

}
Akbar Khan
quelle
1

Recycler-Ansicht in horizontaler Dynamik.

Implementierung der Recycler-Ansicht

RecyclerView musicList = findViewById(R.id.MusicList);

// RecyclerView musiclist = findViewById(R.id.MusicList1);
// RecyclerView musicLIST = findViewById(R.id.MusicList2);
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
musicList.setLayoutManager(layoutManager);

String[] names = {"RAP", "CH SHB", "Faheem", "Anum", "Shoaib", "Laiba", "Zoki", "Komal", "Sultan","Mansoob Gull"};
musicList.setAdapter(new ProgrammingAdapter(names));'

Adapterklasse für die Recycler-Ansicht, in der sich ein Ansichtshalter für die Ansicht dieses Recyclers befindet

public class ProgrammingAdapter 
     extendsRecyclerView.Adapter<ProgrammingAdapter.programmingViewHolder> {

private String[] data;

public ProgrammingAdapter(String[] data)
{
    this.data = data;
}

@Override
public programmingViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    View view = inflater.inflate(R.layout.list_item_layout, parent, false);

    return new programmingViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull programmingViewHolder holder, int position) {
    String title = data[position];
    holder.textV.setText(title);
}

@Override
public int getItemCount() {
    return data.length;
}

public class programmingViewHolder extends RecyclerView.ViewHolder{
    ImageView img;
    TextView textV;
    public programmingViewHolder(View itemView) {
        super(itemView);
        img =  itemView.findViewById(R.id.img);
        textV =  itemView.findViewById(R.id.textt);
    }
}
Faheem Khan
quelle
1
recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false));

recyclerView.setAdapter(adapter);
Hamza Ali
quelle
0

Versuche dies:

myrecyclerview.setLayoutManager(
        new LinearLayoutManager(getActivity(),
                                LinearLayoutManager.HORIZONTAL,false));
myrecyclerview.setAdapter(recyclerAdapter);

Nur für den Fall, dass Sie eine Recycler-Ansicht mit einigen Fragmenten haben.

John Vergara
quelle