Как построить горизонтальный ListView с RecyclerView?
Мне нужно реализовать горизонтальный просмотр списка в моем приложении Android. Я провел небольшое исследование и наткнулся на то, как сделать горизонтальный ListView в Android? и горизонтальный ListView в Android? однако эти вопросы были заданы до выхода Recyclerview. Есть ли лучший способ реализовать это сейчас с Recyclerview?
16 ответов
Is there a better way to implement this now with Recyclerview now?
Да.
Когда вы используете RecyclerView
нужно указать LayoutManager
that is responsible for laying out each item in the view. LinearLayoutManager
allows you to specify an orientation, just like a normal LinearLayout
было бы.
To create a horizontal list with RecyclerView
, вы можете сделать что-то вроде этого:
LinearLayoutManager layoutManager
= new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
RecyclerView myList = (RecyclerView) findViewById(R.id.my_recycler_view);
myList.setLayoutManager(layoutManager);
<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" />
Полный пример
Единственная реальная разница между вертикалью RecyclerView
и горизонтальный, как вы настраиваете LinearLayoutManager
, Вот фрагмент кода. Полный пример ниже.
LinearLayoutManager horizontalLayoutManagaer = new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(horizontalLayoutManagaer);
Этот более полный пример смоделирован после моей вертикали RecyclerView
ответ.
Обновите зависимости Gradle
Убедитесь, что в вашем приложении есть следующие зависимости gradle.build
файл:
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:recyclerview-v7:27.1.1'
Вы можете обновить номера версий до самых актуальных.
Создать макет деятельности
Добавить RecyclerView
к вашему 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>
Создать макет элемента
Каждый предмет в нашем RecyclerView
будет иметь один цветной View
через TextView
, Создайте новый файл ресурсов макета.
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>
Создать адаптер
RecyclerView
нужен адаптер для заполнения представлений в каждой строке (горизонтальный элемент) вашими данными. Создайте новый файл 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);
}
}
Заметки
- Хотя это и не является строго необходимым, я включил функцию прослушивания событий щелчка по элементам. Это было доступно в старом
ListViews
и это общая необходимость. Вы можете удалить этот код, если он вам не нужен.
Инициализируйте RecyclerView в действии
Добавьте следующий код к вашей основной деятельности.
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();
}
}
Заметки
- Обратите внимание, что действие реализует
ItemClickListener
что мы определили в нашем адаптере. Это позволяет нам обрабатывать события щелчка элемента вonItemClick
,
Законченный
Вот и все. Вы должны быть в состоянии запустить ваш проект сейчас и получить что-то похожее на изображение вверху.
Заметки
- Разноцветные виды в моем примере, конечно, можно заменить изображениями в реальном проекте.
- Вертикальный пример RecyclerView
Если вы хотите использовать RecyclerView
с GridLayoutManager
Это способ достижения горизонтальной прокрутки.
recyclerView.setLayoutManager(
new GridLayoutManager(recyclerView.getContext(), rows, GridLayoutManager.HORIZONTAL, false));
Вы можете определить ориентацию и layoutManager из файла макета или в файле java/kotlin.
Использование XML
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/my_recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
В Яве
LinearLayoutManager layoutManager
= new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false);
RecyclerView rv= (RecyclerView) findViewById(R.id.my_recyclerView);
rv.setLayoutManager(layoutManager);
В Котлине
val layoutManager
= LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
my_recyclerView.layoutManager = layoutManager
Попытка построить горизонтальный ListView занимает слишком много времени. Я решил это двумя способами.
1. Используя ViewPager, адаптер которого выходит из PagerAdapter.
2. Используя RecyclerView, как описано выше. Необходимо применить LayoutManager, как показано в следующем коде:
LinearLayoutManager layoutManager
= new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
RecyclerView myList = (RecyclerView) findViewById(R.id.my_recycler_view);
myList.setLayoutManager(layoutManager);
Если вы хотите использовать горизонтальный вид Recycler для работы в качестве ViewPager, то теперь это возможно с помощью LinearSnapHelper
который добавлен в библиотеку поддержки версии 24.2.0.
Сначала добавьте Recycler View к вашей деятельности / фрагменту.
<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>
В моем случае я использовал CardView
внутри RecyclerView
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>
В вашей деятельности / фрагмент
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);
Последний шаг - установить адаптер в Recycler View.
mBlogList.setAdapter(firebaseRecyclerAdapter);
С выпуском библиотеки RecyclerView теперь вы можете легко выровнять список изображений, связанных с текстом. Вы можете использовать LinearLayoutManager, чтобы указать направление, в котором вы хотите ориентировать свой список, вертикальный или горизонтальный, как показано ниже.
Вы можете скачать полную рабочую демонстрацию из этого поста
<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>
Вы можете изменить ориентацию либо в коде, либо в XML-файле макета.
В xml файле
В вашем макете xml файл установлен
orientation
к
horizontal
и к одному из
LinearLayoutManager
,
GridLayoutManager
,
StaggeredGridLayoutManager
. Выберите в соответствии с вашими требованиями.
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
В коде
Если вы хотите программно изменить ориентацию, установите
layoutManager
с горизонтальной ориентацией.
recyclerView.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false));
recyclerView.setAdapter(adapter);
Это как для горизонтальной, так и для вертикальной.
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);
}
Вид ресайклера в горизонтальной динамике.
Реализация Recycler View
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));'
Класс адаптера для представления ресайклера, в котором есть держатель представления для удержания вида этого ресайклера
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);
}
}
Существует подкласс RecyclerView с именем HorizontalGridView, который можно использовать для горизонтального направления. VerticalGridView для вертикального направления
Попробуй это:
myrecyclerview.setLayoutManager(
new LinearLayoutManager(getActivity(),
LinearLayoutManager.HORIZONTAL,false));
myrecyclerview.setAdapter(recyclerAdapter);
только в том случае, если у вас есть вид переработчика с некоторыми фрагментами на нем.
Просто добавьте эти атрибуты в RecyclerView в XML.
android:orientation="horizontal" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"