Ответ 1
Проблема не в вашем коде. Убедитесь, что вы установите layout_height
на wrap_content
дочернего элемента RecyclerView.
После многих часов исследований я наконец консультирую официальную помощь.
У меня есть RecyclerView.Adapter и RecyclerView.ViewHolders, которые отлично работали. Но по некоторым причинам я не понимаю, RecyclerView.Adapter.onBindViewHolder не называется должным образом.
private class AttendeeAdapter extends RecyclerView.Adapter<AttendeeHolder> {
/*FIELDS*/
private List<Attendee> mAttendeeList;
/*CONSTRUCTORS*/
public AttendeeAdapter(List<Attendee> attendees) {
mAttendeeList = attendees;
//Log.i(TAG, "AttendeeAdapter size: " + getItemCount());
}
На основании сообщения журнала (элемент подсчитывается как размер списка, как ожидалось), я предполагаю, что AttendeeAdapter был правильно создан.
Поэтому я ожидаю, что метод onBindViewHolder (VH, int) будет вызываться столько раз, сколько размер списка, но это не так. Этот метод называется только ONCE!
/*METHODS*/
@Override
public AttendeeHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
View itemView = layoutInflater.inflate(R.layout.list_attendee, parent, false);
return new AttendeeHolder(itemView);
}
@Override
public void onBindViewHolder(AttendeeHolder holder, int position) {
Attendee attendee = mAttendeeList.get(position);
holder.bindAttendee(attendee, position);
Log.i(TAG, "Binding ViewHolder #" + position);
/* Binding ViewHolder #0 and that it */
}
@Override
public int getItemCount() {
return mAttendeeList.size();
}
}
Мой AttendeeHolder (расширение RecyclerView.ViewHolder) выглядит следующим образом:
private class AttendeeHolder extends RecyclerView.ViewHolder {
/*FIELDS*/
private EditText mAttendeeNameEditText;
private Attendee mAttendee;
/*CONSTRUCTOR*/
public AttendeeHolder(View itemView) {
super(itemView);
mAttendeeNameEditText = (EditText) itemView.findViewById(R.id.edit_text_list_item);
mAmountEditTextList = new ArrayList<>(eventMaxCount);
}
/*METHODS*/
public void bindAttendee(Attendee attendee, final int position) {
mAttendee = attendee;
String attendeeName = mAttendee.getName();
// Set the name to the EditText if a name has already been set
if (attendeeName != null) {
mAttendeeNameEditText.setText(attendeeName);
}
}
}
и реализован в основном коде как
List<Attendee> attendees = AttendeeLab.get().getAttendeeList();
mAttendeeAdapter = new AttendeeAdapter(attendees);
mAmountRecyclerView.setAdapter(mAttendeeAdapter);
Я думаю, что код будет работать (я думаю, что я не внес никаких изменений), но зависимости gradle могут быть неправильно установлены. Вот где я попытался изменить recyclerview-v7: 23.3.0 на recyclerview-v7: 23.1.0 или что-то еще (Ни один из них не работал).
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.3.0'
compile 'com.android.support:design:23.3.0'
compile 'com.android.support:support-v4:23.3.0'
compile 'com.android.support:recyclerview-v7:23.1.2'
}
Любая помощь или комментарий будут оценены. Хотел бы я попрощаться с головной болью через несколько часов.
Проблема не в вашем коде. Убедитесь, что вы установите layout_height
на wrap_content
дочернего элемента RecyclerView.
Позаботьтесь о поведении onBindViewHolder в циклах RecyclerView. RecyclerView.ViewHolder position 0 itemView
android:layout_height="match_parent"
занимает текущий отображаемый экран. Scroll и onBindViewHolder должны быть запущены, но убедитесь, что getItemCount был установлен соответствующим образом.
Решение:
android:layout_height="wrap_content"
Решение с ConstraintLayout в виде раздутого itemView:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"><!-- IMPORTANT -->
<!-- ... -->
</android.support.constraint.ConstraintLayout>
Используйте те же версии для всех ваших библиотек поддержки:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.3.0'
compile 'com.android.support:design:23.3.0'
compile 'com.android.support:support-v4:23.3.0'
compile 'com.android.support:recyclerview-v7:23.3.0' //<<< here
}
Кроме того, RecyclerView
должен быть добавлен с пакетом 'com.android.support:design:23.3.0'
- переписывание класса, независимо от того, какая магия Gradle
сделала в процессе сборки с этим "дублированным" пакетом, могла вызвать вашу проблему.
Для людей, которые недавно столкнулись с этой проблемой и используют бета-версии SDK 28 библиотеки поддержки, измените целевой SDK на 27 и используйте версию 27.1.1 библиотеки поддержки (самые последние версии на момент написания).
Я боролся с этой проблемой в библиотеках 28.0.0-alpha3, изменил версию на 27.1.1 в моем app.gradle, и проблема была решена.
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support:support-vector-drawable:27.1.1'
implementation 'com.android.support:recyclerview-v7:27.1.1'
Также проверьте, не установлена ли высота самого вашего RecyclerView на android:layout_height="wrap_content"
ИЛИ android:layout_height="match_parent"
. В обоих случаях он адаптирует высоту одного элемента и выглядит как один, но вы можете прокрутить список. Вместо этого установите высоту RecyclerView вручную.
В одном случае, с которым я столкнулся, был случай, когда мое окно повторного просмотра можно было прокручивать только горизонтально, а не вертикально.