Нет необходимости использовать сторонние библиотеки. Небольшая настройка метода, продемонстрированного в Google I / O 2016 и Гейзенберге на эту тему, делает свое дело.
Поскольку notifyDataSetChanged()
перерисовывает полныйRecyclerView
, notifyDataItemChanged()
это лучший вариант (не лучший), потому что у нас есть позиция и ViewHolder
в нашем распоряжении, и notifyDataItemChanged()
только перерисовывает конкретный ViewHolder
в данной позиции .
Но проблема в том, что преждевременное исчезновение ViewHolder
щелчка и его появление не устраняется, даже если notifyDataItemChanged()
используется.
Следующий код не прибегать к notifyDataSetChanged()
или notifyDataItemChanged()
и испытано на API 23 и работает как шарм при использовании на RecyclerView , где каждый ViewHolder имеет , CardView
как это корневой элемент:
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final boolean visibility = holder.details.getVisibility()==View.VISIBLE;
if (!visibility)
{
holder.itemView.setActivated(true);
holder.details.setVisibility(View.VISIBLE);
if (prev_expanded!=-1 && prev_expanded!=position)
{
recycler.findViewHolderForLayoutPosition(prev_expanded).itemView.setActivated(false);
recycler.findViewHolderForLayoutPosition(prev_expanded).itemView.findViewById(R.id.cpl_details).setVisibility(View.GONE);
}
prev_expanded = position;
}
else
{
holder.itemView.setActivated(false);
holder.details.setVisibility(View.GONE);
}
TransitionManager.beginDelayedTransition(recycler);
}
});
prev_position
глобальное целое число, инициализированное -1.
details
это полное представление, которое отображается в развернутом виде и скрыто при свертывании.
Как уже говорилось, корневой элемент ViewHolder
- это атрибуты CardView
with foreground
и stateListAnimator
определены точно так, как сказал Гейзенберг по этой теме.
ОБНОВЛЕНИЕ: Приведенная выше демонстрация свернет ранее развернутый элемент, если один из них развернут. Чтобы изменить это поведение и сохранить развернутый элемент таким, какой он есть, даже когда другой элемент развернут, вам потребуется следующий код.
if (row.details.getVisibility()!=View.VISIBLE)
{
row.details.setVisibility(View.VISIBLE);
row.root.setActivated(true);
row.details.animate().alpha(1).setStartDelay(500);
}
else
{
row.root.setActivated(false);
row.details.setVisibility(View.GONE);
row.details.setAlpha(0);
}
TransitionManager.beginDelayedTransition(recycler);
ОБНОВЛЕНИЕ: при развертывании последних элементов в списке, он может не отображаться в полной видимости, потому что расширенная часть находится ниже экрана. Чтобы получить полный элемент на экране, используйте следующий код.
LinearLayoutManager manager = (LinearLayoutManager) recycler.getLayoutManager();
int distance;
View first = recycler.getChildAt(0);
int height = first.getHeight();
int current = recycler.getChildAdapterPosition(first);
int p = Math.abs(position - current);
if (p > 5) distance = (p - (p - 5)) * height;
else distance = p * height;
manager.scrollToPositionWithOffset(position, distance);
ВАЖНО: чтобы вышеприведенные демонстрации работали, в их коде необходимо сохранить экземпляр RecyclerView и его LayoutManager (последний для гибкости)