È possibile utilizzare voci di elenco espandibili con il nuovo RecyclerView? Ti piace ExpandableListView?
È possibile utilizzare voci di elenco espandibili con il nuovo RecyclerView? Ti piace ExpandableListView?
Risposte:
Questo è semplice da fare con i LayoutManagers di serie, tutto dipende da come gestisci l'adattatore.
Quando si desidera espandere una sezione, è sufficiente aggiungere nuovi elementi all'adattatore dopo l'intestazione. Ricordarsi di chiamare notifyItemRangeInserted quando si esegue questa operazione. Per comprimere una sezione è sufficiente rimuovere gli elementi rilevanti e chiamare notifyItemRangeRemoved (). Per qualsiasi modifica ai dati opportunamente notificata, la vista riciclatore animerà le viste. Quando si aggiungono elementi, viene creata un'area da riempire con i nuovi elementi, con i nuovi elementi che si dissolvono. La rimozione è l'opposto. Tutto quello che devi fare oltre alle cose dell'adattatore è modellare le tue viste per trasmettere la struttura logica all'utente.
Aggiornamento: Ryan Brooks ha ora scritto un articolo su come farlo.
Ottieni l'implementazione del codice di esempio da qui
Impostare ValueAnimator all'interno di onClick di 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();
}
Ecco il codice finale
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", perché il contenuto espanso in quel caso è un elenco stesso con elementi provenienti dall'adattatore. Questa è una soluzione degenerata con solo 1 elemento consentito come bambini all'interno del gruppo.
https://github.com/gabrielemariotti/cardslib
Questa libreria ha un'implementazione di un elenco espandibile con una visualizzazione di riciclo (fare riferimento all'app demo in "CardViewNative" -> "Elenco, griglia e RecyclerView" -> "Schede espandibili"). Ha anche molte altre fantastiche combinazioni di carte / elenchi.
Qualcuno si è lamentato del fatto che la soluzione sopra menzionata non è utilizzabile con una visualizzazione elenco come contenuto espandibile. Ma c'è una soluzione semplice: crea una listview e riempila manualmente con le tue righe .
Soluzione per i pigri: c'è una soluzione semplice se non vuoi cambiare molto il tuo codice. Basta usare manualmente l'adattatore per creare visualizzazioni e aggiungerle al file LinearLayout.
Ecco l'esempio:
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);
}
funzioni di supporto: 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;
}
}
classe di supporto: ExpandUtils
Kavin Varnan ha già postato su come animare un layout ... Ma se vuoi usare la mia classe, sentiti libero di farlo, ho pubblicato una sintesi: https://gist.github.com/MichaelFlisar/738dfa03a1579cc7338a
recyclerviewe puoi espandere / nascondere questa nidificata e utilizzare tutte le ottimizzazioni delrecyclerview
Puoi usare ExpandableLayout che come un'animazione di espansione / compressione uniforme CheckBox, quindi puoi usarlo come CheckBox in ListView e RecyclerView.
Questo è il codice di esempio per ciò che è menzionato da @TonicArtos per aggiungere e rimuovere elementi e per animarlo mentre lo fa, questo è preso da RecyclerView Animations e GitHub sample
1) Aggiungi Listener all'interno del tuo onCreateViewHolder () per registrarti a onClick
2) Crea il tuo OnClickListener personalizzato all'interno del tuo Adapter
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) Aggiungi il tuo addItem () e 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) Se RecyclerViewAdapter non è nella stessa attività di Recycler View , passare l'istanza di recyclerView all'adapter durante la creazione
5) itemList è un ArrayList di tipo mObject che aiuta a mantenere gli stati dell'elemento (Open / Close), il nome, il tipo di Item (subItems / mainItem) e imposta il tema in base ai valori
public class mObject{
private String label;
private int type;
private boolean checked;
}