Come costruire un ListView orizzontale con RecyclerView?


338

Devo implementare una visualizzazione elenco orizzontale nella mia applicazione Android. Ho fatto un po 'di ricerche e mi sono imbattuto in Come posso creare un ListView orizzontale in Android? e ListView orizzontale in Android? tuttavia, queste domande sono state poste prima del rilascio di Recyclerview. Esiste un modo migliore per implementarlo ora con Recyclerview?


12
Basta usare a LinearLayoutManagercon l'orientamento impostato su HORIZONTAL.
Egor Neliuba,

@EgorN l'ho provato, lo rende orizzontale ma sembra che cambi anche i figli della riga dell'adattatore in orizzontale. ho un RelativeLayout. non sono sicuro di come risolvere questo?
Muhammad Umar,

Risposte:


740

C'è un modo migliore per implementarlo ora con Recyclerview adesso?

Sì.

Quando si utilizza a RecyclerView, è necessario specificare un LayoutManagerresponsabile per la disposizione di ciascun elemento nella vista. Ciò LinearLayoutManagerconsente di specificare un orientamento, proprio come LinearLayoutfarebbe un normale .

Per creare un elenco orizzontale con RecyclerView, potresti fare qualcosa del genere:

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

RecyclerView myList = (RecyclerView) findViewById(R.id.my_recycler_view);
myList.setLayoutManager(layoutManager);

l'ho provato, lo rende orizzontale ma sembra che cambi anche i figli della riga dell'adattatore anche in orizzontale. ho un RelativeLayout. non sono sicuro di come risolvere questo?
Muhammad Umar,

2
RelativeLayoutnon ha il concetto di orizzontale vs verticale, quindi non capisco davvero la domanda.
Bryan Herbst,

2
Apparentemente ci sono alcuni problemi con RecyclerView e il LayoutManager a scorrimento orizzontale ... code.google.com/p/android/issues/detail?id=74772 - l'ho trovato perché stavo faticando a usare un RecyclerView a scorrimento orizzontale
AgentKnopf

Zainodis hai capito cosa usare allora? LinearLayoutManager non si presenta nemmeno come importazione per me? Mi sto perdendo qualcosa
Lion789,

@ Tanis.7x Questo funziona alla grande per me, ma popola l'elenco da sinistra a destra. Qualcuno sa se c'è un modo per popolare da destra a sinistra? (Il primo oggetto è quello più a destra nell'elenco, l'elemento all'indice 1 è quindi a sinistra, e così via ...)
raisedandglazed

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" />

come impostare LayoutManager quindi?
Kai Wang,

@kaiwang vedi sopra la risposta "Tanis.7x".
acqua bollita,

app:layoutManager="android.support.v7.widget.LinearLayoutManager"non funzionerà per la versione di rilascio. Ho riscontrato questo problema Build build.
Abu Yousuf,

Stavo cercando come mostrarlo nel generatore di interfacce. strumenti: orientamento = "orizzontale" strumenti: layoutManager = "android.support.v7.widget.LinearLayoutManager" mi ha salvato grazie.
Mohammad Tabbara,

'<androidx.recyclerview.widget.RecyclerView android: layout_width = "match_parent" android: layout_height = "70dp" android: layout_gravity = "bottom" android: orientamento = "orizzontale" app: layoutManager = "androidx.recyclerview.widget.LinearLayoutManager" /> '
Yanny

74

Esempio completo

inserisci qui la descrizione dell'immagine

L'unica vera differenza tra una verticale RecyclerViewe una orizzontale è la configurazione di LinearLayoutManager. Ecco lo snippet di codice. L'esempio completo è di seguito.

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

Questo esempio più completo è modellato sulla mia RecyclerViewrisposta verticale .

Aggiorna dipendenze Gradle

Assicurarsi che le seguenti dipendenze siano nel gradle.buildfile dell'app :

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

È possibile aggiornare i numeri di versione a quelli più attuali .

Crea layout attività

Aggiungi il RecyclerViewal tuo layout xml.

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>

Crea layout oggetto

Ogni articolo nel nostro RecyclerViewavrà un singolo a colorato Viewsu a TextView. Crea un nuovo file di risorse di layout.

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>

Crea l'adattatore

È RecyclerViewnecessario un adattatore per popolare le visualizzazioni in ogni riga (elemento orizzontale) con i tuoi dati. Crea un nuovo file java.

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);
    }
}

Appunti

  • Sebbene non strettamente necessario, ho incluso la funzionalità per l'ascolto degli eventi clic sugli elementi. Questo era disponibile nel vecchio ListViewsed è un bisogno comune. Puoi rimuovere questo codice se non ti serve.

Inizializza RecyclerView in Activity

Aggiungi il seguente codice alla tua attività principale.

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();
    }
}

Appunti

  • Si noti che l'attività implementa ItemClickListenerciò che abbiamo definito nel nostro adattatore. Questo ci consente di gestire gli eventi di clic degli articoli in onItemClick.

Finito

Questo è tutto. Dovresti essere in grado di eseguire il tuo progetto ora e ottenere qualcosa di simile all'immagine in alto.

Appunti


12

Se si desidera utilizzare a RecyclerViewcon GridLayoutManager, questo è il modo per ottenere lo scorrimento orizzontale.

recyclerView.setLayoutManager(
new GridLayoutManager(recyclerView.getContext(), rows, GridLayoutManager.HORIZONTAL, false));

Questo funziona bene per me ... principalmente perché è possibile impostare il numero di righe ... è possibile farlo anche nel LinearLayoutManager?
superUser

9

Cercare di costruire un ListView orizzontale richiede troppo tempo. L'ho risolto in due modi.

1. Utilizzando un ViewPager il cui adattatore si estende da PagerAdapter.

2. Utilizzando RecyclerView proprio come sopra. È necessario applicare LayoutManager come nel seguente codice:

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

RecyclerView myList = (RecyclerView) findViewById(R.id.my_recycler_view);
myList.setLayoutManager(layoutManager);

6

Se si desidera utilizzare la vista Riciclatore orizzontale per agire come ViewPager, ora è possibile con l'aiuto del LinearSnapHelperquale è aggiunto nella Libreria di supporto versione 24.2.0.

Innanzitutto aggiungi RecyclerView alla tua attività / frammento

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

Nel mio caso ho usato un CardViewinterno alRecyclerView

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>

Nella tua attività / frammento

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

L'ultimo passo è impostare l'adattatore su RecyclerView

mBlogList.setAdapter(firebaseRecyclerAdapter);

4

Con il rilascio della libreria RecyclerView, ora è possibile allineare facilmente un elenco di immagini da associare al testo. È possibile utilizzare LinearLayoutManager per specificare la direzione in cui si desidera orientare l'elenco, verticale o orizzontale, come mostrato di seguito.

inserisci qui la descrizione dell'immagine

Puoi scaricare una demo completa funzionante da questo post


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);
        }
    }

1

Esiste una sottoclasse RecyclerView denominata HorizontalGridView che puoi usare per avere una direzione orizzontale. VerticalGridView per direzione verticale


5
HorizontalGridView è pensato anche per l'uso con dispositivi non TV? Afaik la libreria leanback è pensata per i televisori
AgentKnopf,

2
l'utilizzo di leanback porterà la minSdkVersion della tua app su 17
Someone Somewhere

1

È sia per orizzontale che per verticale.

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

}

1

Vista del riciclatore in orizzontale dinamica.

Riciclatore Visualizza implementazione

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));'

Classe dell'adattatore per la vista del riciclatore, in cui è presente un supporto per la vista per tenere la vista di quel riciclatore

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);
    }
}

1
recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false));

recyclerView.setAdapter(adapter);

0

Prova questo:

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

solo nel caso in cui tu abbia una vista del riciclatore con alcuni frammenti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.