Como criar um ListView horizontal com o RecyclerView?

337

Preciso implementar uma exibição de lista horizontal no meu aplicativo Android. Pesquisei um pouco e me deparei com Como faço para fazer um ListView horizontal no Android? e ListView horizontal no Android? no entanto, essas perguntas foram feitas antes do lançamento da Recyclerview. Existe uma maneira melhor de implementar isso agora com a Recyclerview?

Andre Perkins
fonte
12
Basta usar um LinearLayoutManagercom orientação definida como HORIZONTAL.
Egor Neliuba
@ EgorN Eu tentei isso, ele fica na horizontal, mas parece que até muda os filhos da linha do adaptador para horizontal também. Eu tenho um RelativeLayout. não sei como consertar isso?
Muhammad Umar

Respostas:

738

Existe uma maneira melhor de implementar isso agora com a Recyclerview agora?

Sim.

Quando você usa a RecyclerView, é necessário especificar um LayoutManagerresponsável pelo layout de cada item na exibição. O LinearLayoutManagerpermite especificar uma orientação, como LinearLayoutfaria normalmente .

Para criar uma lista horizontal com RecyclerView, você pode fazer algo assim:

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

RecyclerView myList = (RecyclerView) findViewById(R.id.my_recycler_view);
myList.setLayoutManager(layoutManager);
Bryan Herbst
fonte
Eu tentei isso, ele fica na horizontal, mas parece que até muda os filhos da linha do adaptador para horizontal também. Eu tenho um RelativeLayout. não sei como consertar isso?
Muhammad Umar
2
RelativeLayoutnão tem conceito de horizontal versus vertical, então eu realmente não entendo a pergunta.
Bryan Herbst
2
Aparentemente, existem alguns problemas com o RecyclerView e o LayoutManager de rolagem horizontal ... code.google.com/p/android/issues/detail?id=74772 - encontrei porque estava lutando também com o uso de um RecyclerView de rolagem horizontal
AgentKnopf
Zainodis, você já descobriu o que usar? O LinearLayoutManager nem aparece como uma importação para mim? Estou faltando alguma coisa
Lion789
@ Tanis.7x Isso funciona muito bem para mim, mas preenche a lista da esquerda para a direita. Alguém sabe se existe uma maneira de preencher da direita para a esquerda? (Primeiro item é direito mais na lista, item no índice 1 é, em seguida, à esquerda, e assim por diante ...)
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" />
água fervida
fonte
como definir o LayoutManager então?
Kai Wang
@kaiwang pls veja acima a resposta "Tanis.7x".
boiledwater
app:layoutManager="android.support.v7.widget.LinearLayoutManager"não funcionará para compilar o release. Eu enfrentei esse problema Versão de compilação.
Abu Yousuf
Eu estava procurando como mostrar isso no construtor de interfaces. ferramentas: orientação = "horizontal" ferramentas: layoutManager = "android.support.v7.widget.LinearLayoutManager" me salvou, obrigado.
Mohammad Tabbara
'<androidx.recyclerview.widget.RecyclerView android: layout_width = "match_parent" android: layout_height = "70dp" android: layout_gravity = "bottom" android: orientação = "horizontal" app: layoutManager = "androidx.recyclerview.widget.LinearLayoutManager" /> '
Yanny 14/11/19
74

Exemplo completo

insira a descrição da imagem aqui

A única diferença real entre vertical RecyclerViewe horizontal é como você configura o arquivo LinearLayoutManager. Aqui está o trecho de código. O exemplo completo está abaixo.

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

Este exemplo mais completo é modelado após a minha RecyclerViewresposta vertical .

Atualizar dependências Gradle

Verifique se as seguintes dependências estão no seu gradle.buildarquivo de aplicativo :

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

Você pode atualizar os números de versão para o que for mais atual .

Criar layout de atividade

Adicione o RecyclerViewao seu 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>

Criar layout de item

Cada item em nosso RecyclerViewterá um único colorido Viewsobre um TextView. Crie um novo arquivo de recurso de 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>

Crie o adaptador

É RecyclerViewnecessário um adaptador para preencher as visualizações em cada linha (item horizontal) com seus dados. Crie um novo arquivo 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);
    }
}

Notas

  • Embora não seja estritamente necessário, incluí a funcionalidade para ouvir eventos de clique nos itens. Isso estava disponível no passado ListViewse é uma necessidade comum. Você pode remover esse código se não precisar.

Inicializar RecyclerView na atividade

Adicione o seguinte código à sua atividade principal.

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

Notas

  • Observe que a atividade implementa o ItemClickListenerque definimos em nosso adaptador. Isso nos permite lidar com eventos de clique no item onItemClick.

Acabado

É isso aí. Agora você poderá executar seu projeto e obter algo semelhante à imagem na parte superior.

Notas

Suragch
fonte
12

Se você deseja usar a RecyclerViewcom GridLayoutManager, é este o caminho para obter a rolagem horizontal.

recyclerView.setLayoutManager(
new GridLayoutManager(recyclerView.getContext(), rows, GridLayoutManager.HORIZONTAL, false));
José Cabrera
fonte
Isso funciona bem para mim ... principalmente porque você pode definir o número de linhas ... é possível fazer isso também no LinearLayoutManager?
SuperUser 15/09/16
9

Tentar criar um ListView horizontal está demorando muito. Eu resolvi isso de duas maneiras.

1. Usando um ViewPager cujo adaptador se estende do PagerAdapter.

2. Usando o RecyclerView, como acima. É necessário aplicar o LayoutManager como no código a seguir:

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

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

Se você deseja usar o Horizontal Recycler View para atuar como um ViewPager, agora é possível com a ajuda LinearSnapHelperadicionada na Biblioteca de Suporte versão 24.2.0.

Adicione primeiro o RecyclerView à sua atividade / fragmento

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

No meu caso, usei um CardViewdentro doRecyclerView

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>

Em sua atividade / fragmento

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

O último passo é definir o adaptador para RecyclerView

mBlogList.setAdapter(firebaseRecyclerAdapter);
AndroidBeginner
fonte
4

Com o lançamento da biblioteca RecyclerView, agora você pode alinhar facilmente uma lista de imagens vinculadas ao texto. Você pode usar o LinearLayoutManager para especificar a direção na qual você deseja orientar sua lista, vertical ou horizontal, como mostrado abaixo.

insira a descrição da imagem aqui

Você pode baixar uma demonstração de trabalho completa desta postagem

Daniel Nyamasyo
fonte
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
fonte
1

Há uma subclasse RecyclerView chamada HorizontalGridView, que você pode usar para ter direção horizontal. VerticalGridView para direção vertical

Andrew Luca
fonte
5
O HorizontalGridView é para ser usado em dispositivos que não são de TV? Afaik a biblioteca Leanback é destinado a TVs
AgentKnopf
2
usar leanback aumentará o minSdkVersion do seu aplicativo para 17
Someone Somewhere
1

É para Horizontal e Vertical.

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

Vista do reciclador na dinâmica horizontal.

Implementação da exibição do reciclador

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 de adaptador para visualização de reciclador, na qual existe um suporte de visualização para manter a visualização desse reciclador

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
fonte
1
recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false));

recyclerView.setAdapter(adapter);
Hamza Ali
fonte
0

Tente o seguinte:

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

apenas no caso de você ter uma visão do reciclador com alguns fragmentos.

John Vergara
fonte