Динамическое добавление Views в RecyclerView только к текущему элементу
Я динамически добавляю Views в мои элементы в RecyclerView
. Эти добавленные представления должны быть связаны только с элементом, к которому они добавлены, но у меня возникают проблемы при прокрутке. Кажется, что View
переработано и загружен новый элемент, но те ранее добавленные представления все еще существуют, только теперь на неправильном элементе.
Я предполагаю, что это происходит только из-за повторного использования ViewHolder
, поэтому добавленные элементы снова появляются с новым элементом при загрузке.
Как можно решить это?
Ответы
Ответ 1
Это был старый вопрос. На него была возложена щедрость, следовательно, всплеск популярности и многочисленные новые и нерелевантные ответы.
Как указано в моем комментарии к этому ответу и комментарию @CQM ниже моего исходного вопроса, ответ заключается в том, чтобы переопределить onViewRecycled()
и выполнять любые необходимые операции. Этот метод вызывается, когда представление перерабатывается, и любые операции очистки могут быть выполнены здесь.
Документацию по этому методу можно найти здесь.
В моем случае, это был вопрос об удалении невидимого TextView
, прикрепленного к представлению. Сам текст был удален, но точка зрения осталась. Если многие невидимые TextView
накапливаются в представлении и не перерабатываются при прокрутке, свиток начинает отставать.
Ответ 2
Вы можете использовать это! setItemViewCacheSize(int size)
Проверьте RecyclerViewDocumentation.
В кэше скрытого представления остается информация об изменениях в подключенном адаптере, что позволяет LayoutManager повторно использовать эти представления без изменений, не возвращаясь к адаптеру для их повторной привязки.
Ответ 3
Вам нужно отслеживать, какие представления были добавлены на основе данных резервного копирования. Возможно, я добавлю дополнительные лишние виды в onBindViewHolder()
и удалю все, что может присутствовать в onViewRecycled()
. Затем, когда вы хотите, чтобы один из них отображался динамически, измените любую переменную, которую вы отслеживаете, должна ли она быть видимой, и вызовите notifyItemChanged()
.
Ответ 4
Исходя из этого:
но те, которые ранее добавили "Представления", все еще существуют, но теперь на неправильном элементе.
В принципе, согласно документации RecyclerView, вы должны reset просматривать каждый раз внутри метода onBindViewHolder()
,
так что скажем, у вас есть метод, который устанавливает параметр view, если его профиль, поэтому код для него следующий,
if (list.get(position).getId()==PreferenceManager.getUserID())
{
// do some view change here
setViewParam(true);
}else
{
// reset the view change here
setViewParam(false);
}
Итак, что вы здесь делаете, дает возможность переустановить ViewHolder для reset.
Сделайте комментарий, если вам нужна помощь!
Ответ 5
Сохранять информацию по тегам для элементов с новым дочерним элементом при каждом запуске операции Add newView. (Например, в общем предпочтении)
Тег: создайте позицию позиции в приложении BindViewHolder.
...
SharedPreference sharedPref = getSharedPreference("text" + position, context);
SharedPreference.Editor editor = sharedPref.edit();
editor.putString("view", "ImageView");
...
когда адаптер нагрузки получает это значение и ставит значение по умолчанию как null.
Я не уверен в его эффективности, но я буду работать.
...
String viewType = sharedPref.getString("view", null);
//it will return ImageView
если вы знаете какие-то возможные типы viewTypes, например, всегда будут ImageView и TextView, поэтому с некоторым оператором if это будет нормально.
if(viewType.equals("ImageVIew")){
item(position).addView(new ImageVIew(context));
}
Удача
Ответ 6
Прежде всего, можете ли вы поделиться еще одним кодом?
Во-вторых, почему вы хотите динамически добавлять новые представления на лету? Почему бы вам не использовать разные VIEWTYPE или просто иметь это представление уже на вашем макете и просто сделать их видимыми/невидимыми или видимыми/ушедшими? (Я считаю, что это будет более эффективно).
Позвольте мне напомнить вам о RecyclerView, да, когда пользователь прокручивает viewHolder, они повторно используются (некоторые из них могут быть созданы, даже больше, чем нужно для заполнения экрана). Так что, если бы вы добавили некоторые взгляды на "элемент A", а пользователь прокрутил до "item Z", этот viewHolder можно повторно использовать для этого "элемента Z", следовательно, отображать ранее добавленные представления.
Как вы можете это решить?
Ну всегда проверяйте все элементы, если вам нужно добавлять новые представления, если да добавить их, если они еще не добавлены, а также всегда удалять эти представления (если есть), чтобы вернуться к состоянию состояния viewHolder по умолчанию (или тому, что вы его называете).
Надеюсь, это поможет вам.
Ответ 7
В вашем классе адаптера вашего recyclerView
,
в методе onBindViewHolder
создайте другой адаптер и выполните те же методы для вашего нового адаптера.
Иерархия будет,
mainRecyclerView → item1 (- > childRecyclerView1), item2 (- > childRecyclerView2), item3 (- > childRecyclerView3)
Таким образом, вы можете достичь того, чего хотите, без неправильных значений для просмотра на неправильных элементах.
Ответ 8
В макете дочерних элементов XML
вы должны взять любой пустую макет, например Linearlayout
, а затем добавить в нее теги Linearlayout
вашего конкретного элемента при прокрутке списка всех ваших дочерних видов, которые вы добавили на Linearlayout
также прокручивается с этим элементом.