RecyclerView-Baumansicht (ohne Bibliotheken und untergeordnete Arrays von Drittanbietern)

Guten Tag, liebe Leser.

In meinem Artikel möchte ich eine Implementierung der Baumansicht für RecyclerView freigeben. Ohne zusätzliche Bibliotheken und ohne untergeordnetes Array.
Wen kümmert es bitte unter der Katze. Ich werde versuchen, so viel wie möglich zu beschreiben, was und wie.



Das Prinzip beim Erstellen einer Liste von Elementen besteht darin, dass untergeordnete Elemente angezeigt oder ausgeblendet werden.

Obwohl ich sagte, dass die Implementierung ohne zusätzliche Bibliotheken sein wird, müssen Standardbibliotheken noch verbunden werden.

Verbundene Bibliotheken
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' } 


Das Markup ist sehr gering - nur die RecyclerView-Liste.

Markup
 <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> 


Zusätzlich benötigen wir eine separate Klasse, in der wir die Listenwerte speichern.

Klasse für Daten 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; } } 


Die Kommentare sollten klar sein, aber ich werde es erklären. Für jedes Element der Liste speichern wir den Bezeichner valueId , den Namen valueText , den Bezeichner des übergeordneten Elements parentId , eine Bezeichnung, die angibt, dass das Element das übergeordnete ElementParent ist, und den Sichtbarkeitswert für die untergeordneten Elemente von childVisibility .

Der nächste vorbereitende Schritt besteht darin, ein Markup für das Listenelement selbst zu erstellen.

Markup für 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 wird benötigt, um den Status des übergeordneten Elements anzuzeigen. TextView - um den Wert eines Elements anzuzeigen. Die Ansicht dient nur zum Teilen.

Der letzte vorbereitende Schritt besteht darin, eine Klasse für den Listenadapter zu erstellen.

Adapter für Liste 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); } } } 


Die Hauptverarbeitung erfolgt in der Prozedur onBindViewHolder . Für jedes Element der Liste werden seine Kennung, sein Wert und seine Parameter des übergeordneten Werts erhalten. Ein- oder Ausblenden von untergeordneten Elementen sowie eines Statussymbols für das übergeordnete Element. Nun, die Verarbeitung von Klicks auf die Liste ist hängen geblieben. Dann entscheidet jeder, wie er die Liste bearbeiten muss. Das Beispiel zeigt einfach eine Nachricht mit ID und Elementwert.
Bei der Prozedur zum Ein- oder Ausblenden des untergeordneten setVisibility-Elements wird der Text für das untergeordnete Element zusätzlich mit 80 Pixel eingerückt.

Es bleibt nur, die Liste an der richtigen Stelle auszufüllen.

Listenerstellung
 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); 


Das Ergebnis ist eine so einfache Liste mit Unterstützung für untergeordnete Elemente. Mit dieser Implementierung können Sie mehrere verschachtelte Elemente ausfüllen. Sie müssen den Einzug für untergeordnete Elemente jedoch leicht verfeinern, wenn die Verschachtelungsebene mehr als 1 beträgt.

Vielen Dank für Ihre Aufmerksamkeit und Ihre erfolgreichen Projekte.

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


All Articles