Jak zbudować poziomy ListView za pomocą RecyclerView?


338

Muszę wdrożyć poziomy widok listy w mojej aplikacji na Androida. Przeprowadziłem trochę badań i natknąłem się na to Jak mogę zrobić poziomy ListView w Androidzie? i widok poziomy ListView w Androidzie? jednak pytania te zostały zadane przed wydaniem Recyclerview. Czy istnieje lepszy sposób na wdrożenie tego teraz za pomocą Recyclerview?


12
Wystarczy użyć LinearLayoutManagerz orientacją ustawioną na HORIZONTAL.
Egor Neliuba,

@EgorN Próbowałem tego, robi to poziomo, ale wydaje się, że nawet zmienia elementy potomne rzędu adaptera na poziome. mam RelativeLayout. nie jestem pewien jak to naprawić?
Muhammad Umar

Odpowiedzi:


739

Czy jest teraz lepszy sposób na wdrożenie tego za pomocą Recyclerview?

Tak.

Kiedy używasz a RecyclerView, musisz określić, LayoutManagerktóry jest odpowiedzialny za ułożenie każdego elementu w widoku. LinearLayoutManagerPozwala określić orientację, podobnie jak normalny LinearLayoutbędzie.

Aby utworzyć listę poziomą RecyclerView, możesz zrobić coś takiego:

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

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

próbowałem tego, robi to poziomo, ale wydaje się, że nawet zmienia dzieci potomne rzędu adaptera na poziome. mam RelativeLayout. nie jestem pewien jak to naprawić?
Muhammad Umar

2
RelativeLayoutnie ma pojęcia pozioma kontra pionowa, więc tak naprawdę nie rozumiem pytania.
Bryan Herbst

2
Najwyraźniej istnieją pewne problemy z RecyclerView i przewijanym poziomo LayoutManager ... code.google.com/p/android/issues/detail?id=74772 - znalazłem go, ponieważ miałem również problemy z faktycznym użyciem przewijanego poziomo RecyclerView
AgentKnopf

Zainodis, czy wiesz, czego użyć? LinearLayoutManager nawet nie pojawia się jako import? Czy coś mi brakuje
Lion789,

@ Tanis.7x Działa to dla mnie świetnie, ale wypełnia listę od lewej do prawej. Czy ktoś wie, czy istnieje sposób na zaludnienie od prawej do lewej? (Pierwszy element jest najbardziej na liście na prawo, element o indeksie 1 jest następnie w lewo, i tak dalej ...)
podniesiony i oszklony

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

jak wtedy ustawić LayoutManager?
Kai Wang

@kaiwang pls patrz wyżej odpowiedź „Tanis.7x”.
gotowana woda

app:layoutManager="android.support.v7.widget.LinearLayoutManager"nie będzie działać w kompilacji wersji. Napotkałem ten problem Kompilacja wydania.
Abu Yousuf,

Szukałem, jak to pokazać w kreatorze interfejsów. tools: orientacja = „poziome” narzędzia: layoutManager = "android.support.v7.widget.LinearLayoutManager” uratował mi dzięki.
Mohammad Tabbara,

'<androidx.recyclerview.widget.RecyclerView android: layout_width = "match_parent" android: layout_height = "70dp" android: layout_gravity = "bottom" android: orientacja = "pozioma" aplikacja: layoutManager = "androidx.recyclerview.widget.LinearLayoutManager" /> '
Yanny

74

Kompletny przykład

wprowadź opis zdjęcia tutaj

Jedyną prawdziwą różnicą między pionową RecyclerViewa poziomą jest sposób konfiguracji LinearLayoutManager. Oto fragment kodu. Pełny przykład znajduje się poniżej.

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

Ten pełniejszy przykład jest wzorowany na mojej RecyclerViewodpowiedzi pionowej .

Zaktualizuj zależności Gradle

Upewnij się, że w Twojej aplikacji występują następujące zależności gradle.build pliku :

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

Możesz zaktualizować numery wersji na cokolwiek jest najnowszej .

Utwórz układ aktywności

Dodaj RecyclerViewdo swojego układu 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>

Utwórz układ elementu

Każdy przedmiot w naszym RecyclerViewbędzie miał pojedynczy kolor Viewnad TextView. Utwórz nowy plik zasobów układu.

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>

Utwórz adapter

RecyclerViewWymaga adaptera do wypełnienia widoki w każdym rzędzie (pozycja pozioma) z danymi. Utwórz nowy plik 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);
    }
}

Notatki

  • Chociaż nie jest to absolutnie konieczne, dołączyłem funkcję nasłuchiwania zdarzeń kliknięcia na elementach. To było dostępne w starymListViews i jest powszechną potrzebą. Możesz usunąć ten kod, jeśli go nie potrzebujesz.

Zainicjuj RecyclerView w działaniu

Dodaj następujący kod do swojej głównej działalności.

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

Notatki

  • Zauważ, że działanie implementuje to ItemClickListener, co zdefiniowaliśmy w naszym adapterze. To pozwala nam obsługiwać zdarzenia kliknięcia elementu w onItemClick.

Skończone

Otóż ​​to. Powinieneś być teraz w stanie uruchomić swój projekt i uzyskać coś podobnego do obrazu na górze.

Notatki


12

Jeśli chcesz używać RecyclerViewz GridLayoutManager, jest to sposób na uzyskanie przewijania w poziomie.

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

Działa to dla mnie dobrze ... głównie dlatego, że możesz ustawić wiersze num ... czy jest to również możliwe w LinearLayoutManager?
superUser

9

Próba zbudowania poziomego ListView zajmuje zbyt dużo czasu. Rozwiązałem to na dwa sposoby.

1.Za pomocą ViewPager, którego adapter wystaje z PagerAdapter.

2.Za pomocą RecyclerView tak jak powyżej. Musisz zastosować LayoutManager jak w następującym kodzie:

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

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

6

Jeśli chcesz używać Widoku Recyklera Poziomego do działania jako ViewPager, jest to teraz możliwe dzięki pomocy LinearSnapHelperdodanej w Bibliotece pomocy w wersji 24.2.0.

Najpierw dodaj RecyclerView do swojej aktywności / fragmentu

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

W moim przypadku użyłem CardViewwnętrzaRecyclerView

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>

W twojej aktywności / fragmencie

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

Ostatnim krokiem jest ustawienie adaptera na RecyclerView

mBlogList.setAdapter(firebaseRecyclerAdapter);

4

Wraz z wydaniem biblioteki RecyclerView możesz teraz łatwo wyrównać listę zdjęć powiązanych z tekstem. Możesz użyć LinearLayoutManager, aby określić kierunek, w którym chcesz ustawić swoją listę, pionową lub poziomą, jak pokazano poniżej.

wprowadź opis zdjęcia tutaj

Możesz pobrać w pełni działającą wersję demo z tego postu


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

Istnieje podklasa RecyclerView o nazwie HorizontalGridView, której można użyć do uzyskania kierunku poziomego. VerticalGridView dla kierunku pionowego


5
Czy HorizontalGridView jest nawet przeznaczony do użytku w urządzeniach innych niż TV? Afaik, biblioteka Leanback, przeznaczona jest do telewizorów
AgentKnopf

2
użycie Leanback podbije wartość minSdkVersion Twojej aplikacji do 17
Someone Somewhere

1

To jest zarówno dla poziomej i pionowej.

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

Recycler View in Dynamic Dynamic.

Recycler View Implementation

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

Klasa adaptera do widoku recyklera, w której znajduje się uchwyt widoku do trzymania widoku tego recyklera

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

Spróbuj tego:

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

tylko w przypadku, gdy masz widok recyklera z kilkoma fragmentami.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.