Vista de árbol RecyclerView (sin bibliotecas de terceros y matrices secundarias)

Buen día, queridos lectores.

En mi artículo, quiero compartir una implementación de vista de árbol con RecyclerView. Sin usar ninguna biblioteca adicional y sin usar una matriz secundaria.
A quién le importa, por favor, debajo del gato. Trataré de describir lo más posible qué y cómo.



El principio de formar una lista de elementos es que los elementos secundarios se mostrarán u ocultarán.

Aunque dije que la implementación será sin bibliotecas adicionales, sin embargo, las bibliotecas estándar todavía necesitan estar conectadas.

Bibliotecas conectadas
dependencies { implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.android.support:design:26.1.0' implementation 'com.android.support:recyclerview-v7:26.1.0' } 


El marcado será muy mínimo, solo la lista RecyclerView.

Marcado
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/recycler_list"> </android.support.v7.widget.RecyclerView> </RelativeLayout> 


Además, necesitamos una clase separada con la que almacenaremos los valores de la lista.

Clase para datos Data.java
 public final class Data { private String valueText = ""; //  private int valueId = 0; //  private boolean itemParent = false; //    private int parentId = -1; //id ,    private boolean childVisibility = false; //   //     public boolean isItemParent() { return itemParent; } //    public void setItemParent(boolean newItemParent) { itemParent = newItemParent; } //    public boolean isChildVisibility() { return childVisibility; } //     public void setChildVisibility(boolean newChildVisibility) { childVisibility = newChildVisibility; } //    public int getParentId() { return parentId; } //    public void setParentId(int newParentId) { parentId = newParentId; } //   public String getValueText() { return valueText; } //   public void setValueText(String newValueText) { valueText = newValueText; } //   public int getValueId() { return valueId; } //   public void setValueId(int newValueId) { valueId = newValueId; } } 


Los comentarios deben ser claros, pero lo explicaré. Para cada elemento de la lista, almacenaremos su identificador valueId , nombre valueText , identificador del elemento padre parentId , una etiqueta que indica que el elemento es un elemento padre principal y el valor de visibilidad para los elementos hijos de childVisibility .

El siguiente paso preparatorio es crear un marcado para el elemento de la lista en sí.

Marcado para item.xml
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/item" android:layout_width="match_parent" android:layout_height="wrap_content"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <!--     --> <android.support.v7.widget.AppCompatImageView android:id="@+id/icon_tree" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/icon_hide" android:visibility="gone" app:backgroundTint="@color/colorPrimary" android:layout_centerVertical="true"/> <LinearLayout android:id="@+id/block_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_toRightOf="@+id/icon_tree"> <!--  --> <TextView android:id="@+id/value_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:foreground="?android:attr/selectableItemBackground" android:text="sdfdsf"/> </LinearLayout> <!--  --> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/colorPrimary" android:layout_below="@+id/block_text" android:layout_marginTop="4dp" android:layout_marginLeft="4dp" android:layout_marginRight="4dp"/> </RelativeLayout> </LinearLayout> 


AppCompatImageView es necesario para mostrar el estado del elemento primario. TextView : para mostrar el valor de un elemento. La vista es solo para compartir.

El último paso preparatorio es crear una clase para manejar el adaptador de lista.

Adaptador para la lista RecyclerViewAdapter.java
 public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> { private View vv; private List<Data> allRecords; //   public RecyclerViewAdapter(List<Data> records) { allRecords = records; } @Override public RecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false); return new RecyclerViewAdapter.ViewHolder(v); } @Override public void onBindViewHolder(final RecyclerViewAdapter.ViewHolder viewHolder, int i) { Data record = allRecords.get(i); String value = record.getValueText(); int id = record.getValueId(); int parentId = record.getParentId(); final int position = i; final String text = "#" + id + ": " + value + " (id  : " + parentId + ")"; //   ,    if (parentId >= 0) { //      setVisibility(viewHolder.item, allRecords.get(parentId).isChildVisibility(), parentId); } else { //  ,   setVisibility(viewHolder.item, true, parentId); } //      if (record.isItemParent()) { viewHolder.iconTree.setVisibility(View.VISIBLE); //   if (record.isChildVisibility()) //   viewHolder.iconTree.setBackgroundResource(R.drawable.icon_show); else //   viewHolder.iconTree.setBackgroundResource(R.drawable.icon_hide); } else //   viewHolder.iconTree.setVisibility(View.GONE); //   if (!TextUtils.isEmpty(value)) { viewHolder.valueText.setText(value); } //     viewHolder.valueText.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Data dataItem = allRecords.get(position); if (dataItem.isItemParent()) { //   ,     dataItem.setChildVisibility(!dataItem.isChildVisibility()); notifyDataSetChanged(); } else { //   ,    Snackbar snackbar = Snackbar.make(vv, text, Snackbar.LENGTH_LONG); snackbar.show(); } } }); } //   private void setVisibility(View curV, boolean visible, int parentId) { // ,      LinearLayout vPadding = curV.findViewById(R.id.block_text); LinearLayout.LayoutParams params; if (visible) { params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); if (vPadding != null) { if (parentId >= 0) { //  ,   vPadding.setPadding(80, 0, 0, 0); } else { vPadding.setPadding(0, 0, 0, 0); } } } else params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0); curV.setLayoutParams(params); } @Override public int getItemCount() { return allRecords.size(); } class ViewHolder extends RecyclerView.ViewHolder { private LinearLayout item; private TextView valueText; private AppCompatImageView iconTree; public ViewHolder(View itemView) { super(itemView); vv = itemView; item = vv.findViewById(R.id.id_item); valueText = vv.findViewById(R.id.value_name); iconTree = vv.findViewById(R.id.icon_tree); } } } 


El procesamiento principal tiene lugar en el procedimiento onBindViewHolder . Para cada elemento de la lista, se obtienen su identificador, valor y parámetros del valor principal. Mostrar u ocultar elementos secundarios, así como un icono de estado para el elemento primario. Bueno, el procesamiento de clics en la lista está colgado. Luego, todos deciden cómo necesita procesar la lista. El ejemplo simplemente muestra un mensaje con id y valor de elemento.
En el procedimiento para mostrar u ocultar el elemento secundario setVisibility , el texto se sangra adicionalmente para el elemento secundario a 80 píxeles.

Solo queda completar la lista en el lugar correcto.

Lista de construcción
 List<Data> records = new ArrayList<Data>(); //  Data record; RecyclerViewAdapter adapter; int parentId; RecyclerView recyclerView = findViewById(R.id.recycler_list); record = new Data(); record.setValueId(1); record.setValueText("  1"); record.setItemParent(true); //  records.add(record); parentId = records.size() -1; for (int ind = 1; ind <= 3; ind ++) { record = new Data(); record.setValueId(ind); record.setValueText(" " + ind); record.setParentId(parentId); records.add(record); } record = new Data(); record.setValueId(1); record.setValueText("  "); record.setItemParent(true); //  records.add(record); parentId = records.size() -1; for (int ind = 4; ind <= 7; ind ++) { record = new Data(); record.setValueId(ind); record.setValueText("  " + ind); record.setParentId(parentId); records.add(record); } record = new Data(); record.setValueId(1); record.setValueText("  "); record.setItemParent(true); //  records.add(record); parentId = records.size() -1; for (int ind = 8; ind <= 12; ind ++) { record = new Data(); record.setValueId(ind); record.setValueText(" " + ind); record.setParentId(parentId); records.add(record); } for (int ind = 13; ind <= 18; ind ++) { record = new Data(); record.setValueId(ind); record.setValueText("  " + ind); records.add(record); } for (int ind = 19; ind <= 21; ind ++) { record = new Data(); record.setValueId(ind); record.setValueText("   " + ind); records.add(record); } record = new Data(); record.setValueId(1); record.setValueText("  "); record.setItemParent(true); //  records.add(record); parentId = records.size() -1; for (int ind = 22; ind <= 30; ind ++) { record = new Data(); record.setValueId(ind); record.setValueText(": " + ind); record.setParentId(parentId); records.add(record); } for (int ind = 31; ind <= 45; ind ++) { record = new Data(); record.setValueId(ind); record.setValueText("   " + ind); records.add(record); } adapter = new RecyclerViewAdapter(records); RecyclerView.ItemAnimator itemAnimator = new DefaultItemAnimator(); LinearLayoutManager layoutManager = new LinearLayoutManager(this); recyclerView.setAdapter(adapter); recyclerView.setLayoutManager(layoutManager); recyclerView.setItemAnimator(itemAnimator); 


El resultado es una lista tan simple con soporte para elementos secundarios. Esta implementación le permite completar varios elementos anidados. Pero debe refinar ligeramente la sangría de los elementos secundarios si el nivel de anidación es superior a 1.

Gracias a todos por su atención y proyectos exitosos.

Source: https://habr.com/ru/post/es431718/


All Articles