Можно ли использовать расширяемые элементы списка с новым RecyclerView? Нравится ExpandableListView?
Можно ли использовать расширяемые элементы списка с новым RecyclerView? Нравится ExpandableListView?
Ответы:
Это просто сделать с помощью стандартных LayoutManager, все зависит от того, как вы управляете своим адаптером.
Если вы хотите расширить раздел, вы просто добавляете новые элементы в свой адаптер после заголовка. Не забудьте при этом вызвать notifyItemRangeInserted. Чтобы свернуть раздел, вы просто удаляете соответствующие элементы и вызываете notifyItemRangeRemoved (). Для любых изменений данных, о которых сообщается должным образом, представление ресайклера анимирует представления. При добавлении элементов создается область для заполнения новыми элементами, при этом новые элементы постепенно появляются. Удаление происходит наоборот. Все, что вам нужно сделать помимо материала адаптера, - это стилизовать ваши представления, чтобы передать логическую структуру пользователю.
Обновление: Райан Брукс написал статью о том, как это сделать.
Получите пример реализации кода отсюда
Установите ValueAnimator внутри onClick ViewHolder
@Override
public void onClick(final View view) {
if (mOriginalHeight == 0) {
mOriginalHeight = view.getHeight();
}
ValueAnimator valueAnimator;
if (!mIsViewExpanded) {
mIsViewExpanded = true;
valueAnimator = ValueAnimator.ofInt(mOriginalHeight, mOriginalHeight + (int) (mOriginalHeight * 1.5));
} else {
mIsViewExpanded = false;
valueAnimator = ValueAnimator.ofInt(mOriginalHeight + (int) (mOriginalHeight * 1.5), mOriginalHeight);
}
valueAnimator.setDuration(300);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = (Integer) animation.getAnimatedValue();
view.getLayoutParams().height = value.intValue();
view.requestLayout();
}
});
valueAnimator.start();
}
Вот окончательный код
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView mFriendName;
private int mOriginalHeight = 0;
private boolean mIsViewExpanded = false;
public ViewHolder(RelativeLayout v) {
super(v);
mFriendName = (TextView) v.findViewById(R.id.friendName);
v.setOnClickListener(this);
}
@Override
public void onClick(final View view) {
if (mOriginalHeight == 0) {
mOriginalHeight = view.getHeight();
}
ValueAnimator valueAnimator;
if (!mIsViewExpanded) {
mIsViewExpanded = true;
valueAnimator = ValueAnimator.ofInt(mOriginalHeight, mOriginalHeight + (int) (mOriginalHeight * 1.5));
} else {
mIsViewExpanded = false;
valueAnimator = ValueAnimator.ofInt(mOriginalHeight + (int) (mOriginalHeight * 1.5), mOriginalHeight);
}
valueAnimator.setDuration(300);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = (Integer) animation.getAnimatedValue();
view.getLayoutParams().height = value.intValue();
view.requestLayout();
}
});
valueAnimator.start();
}
}
ExpandableListView
», потому что расширенное содержимое в этом случае представляет собой сам список с элементами, поступающими от адаптера. Это вырожденное решение, в котором в качестве детей в группе разрешен только 1 элемент.
https://github.com/gabrielemariotti/cardslib
В этой библиотеке реализована реализация расширяемого списка с помощью recyclerview (см. Демонстрационное приложение в разделе «CardViewNative» -> «Список, сетка и RecyclerView» -> «Расширяемые карты»). Также в нем есть много других интересных комбинаций карт / списков.
Кто-то жаловался на то, что вышеупомянутое решение нельзя использовать со списком в качестве расширяемого содержимого. Но есть простое решение: создать список и заполнить его вручную своими строками. .
Решение для ленивых: есть простое решение, если вы не хотите сильно менять код. Просто используйте адаптер вручную для создания представлений и добавления их вLinearLayout
.
Вот пример:
if (mIsExpanded)
{
// llExpandable... is the expandable nested LinearLayout
llExpandable.removeAllViews();
final ArrayAdapter<?> adapter = ... // create your adapter as if you would use it for a ListView
for (int i = 0; i < adapter.getCount(); i++)
{
View item = adapter.getView(i, null, null);
// if you want the item to be selectable as if it would be in a default ListView, then you can add following code as well:
item.setBackgroundResource(Functions.getThemeReference(context, android.R.attr.selectableItemBackground));
item.setTag(i);
item.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// item would be retrieved with:
// adapter.getItem((Integer)v.getTag())
}
});
llExpandable.addView(item);
}
ExpandUtils.expand(llExpandable, null, 500);
}
else
{
ExpandUtils.collapse(llExpandable, null, 500);
}
вспомогательные функции: getThemeReference
public static int getThemeReference(Context context, int attribute)
{
TypedValue typeValue = new TypedValue();
context.getTheme().resolveAttribute(attribute, typeValue, false);
if (typeValue.type == TypedValue.TYPE_REFERENCE)
{
int ref = typeValue.data;
return ref;
}
else
{
return -1;
}
}
вспомогательный класс: ExpandUtils
Кавин Варнан уже научился анимировать макет ... Но если вы хотите использовать мой класс, не стесняйтесь, я опубликовал суть: https://gist.github.com/MichaelFlisar/738dfa03a1579cc7338a
recyclerview
и вы можете развернуть / скрыть этот вложенный и использовать все оптимизацииrecyclerview
Вы можете использовать ExpandableLayout, который похож на плавную анимацию развертывания / свертывания CheckBox, поэтому вы можете использовать его как CheckBox в ListView и RecyclerView.
Это пример кода для того, что упоминается @TonicArtos для добавления и удаления элементов, а также для его анимации при выполнении, это взято из RecyclerView Animations и образца GitHub
1) Добавьте Listener в свой onCreateViewHolder (), чтобы зарегистрироваться для onClick
2) Создайте свой собственный OnClickListener внутри вашего адаптера
private View.OnClickListener mItemListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
TextView tv = (TextView) v.findViewById(R.id.tvItems);
String selected = tv.getText().toString();
boolean checked = itemsList.get(recyclerView.getChildAdapterPosition(v)).isChecked();
switch (selected){
case "Item1":
if(checked){
deleteItem(v);
itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(false);
}else {
addItem(v);
itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(true);
}
break;
case "Item2":
if(checked){
deleteItem(v);
itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(false);
}else {
addItem(v);
itemsList.get(recyclerView.getChildAdapterPosition(v)).setChecked(true);
}
break;
default:
//In my case I have checkList in subItems,
//checkItem(v);
break;
}
}
};
3) Добавьте свои addItem () и deleteItem ()
private void addItem(View view){
int position = recyclerView.getChildLayoutPosition(view);
if (position != RecyclerView.NO_POSITION){
navDrawItems.add(position+1,new mObject());
navDrawItems.add(position+2,new mObject());
notifyItemRangeInserted(position+1,2);
}
}
private void deleteItem(View view) {
int position = recyclerView.getChildLayoutPosition(view);
if (position != RecyclerView.NO_POSITION) {
navDrawItems.remove(position+2);
navDrawItems.remove(position+1);
notifyItemRangeRemoved(position+1,2);
}
}
4) Если ваш RecyclerViewAdapter не находится в том же Activity, что и Recycler View , передайте экземпляр recyclerView адаптеру при создании
5) itemList - это список ArrayList типа mObject, который помогает поддерживать состояния элемента (Open / Close), имя, тип элемента (subItems / mainItem) и устанавливать тему на основе значений
public class mObject{
private String label;
private int type;
private boolean checked;
}