Android ListView mit verschiedenen Layouts für jede Zeile

Ich versuche, den besten Weg zu finden, ein einzelnes ListView zu haben, das unterschiedliche Pläne für jede Reihe enthält. Ich weiß, wie man eine benutzerdefinierte Zeile + einen benutzerdefinierten Array-Adapter erstellt, um eine benutzerdefinierte Zeile für die gesamte Listenansicht zu unterstützen, aber wie kann ich viele verschiedene Zeilenstile in der ListView implementieren?

Solutions Collecting From Web of "Android ListView mit verschiedenen Layouts für jede Zeile"

Da Sie wissen, wie viele Arten von Layout Sie haben – es ist möglich, diese Methoden zu verwenden.

getViewTypeCount() – Diese Methode gibt Informationen darüber zurück, wie viele Arten von Zeilen Sie in Ihrer Liste haben

getItemViewType(int position)getItemViewType(int position) Informationen zurück, welchen getItemViewType(int position) Sie basierend auf der Position verwenden sollten

Dann getItemViewType Sie das Layout nur auf, wenn es null ist, und bestimmen den Typ mit getItemViewType .

Sehen Sie sich dieses Tutorial für weitere Informationen an.

Um einige Optimierungen in der Struktur zu erreichen, die Sie im Kommentar beschrieben haben, würde ich vorschlagen:

  • Ansichten im Objekt namens ViewHolder findViewById() würde die Geschwindigkeit erhöhen, da Sie findViewById() jedes Mal in der getView Methode getView . Siehe Liste 14 in API-Demos .
  • Erstellen Sie ein generisches Layout, das allen Kombinationen von Eigenschaften entspricht und einige Elemente ausblendet, wenn die aktuelle Position es nicht enthält.

Ich hoffe, dass dir das weiterhilft. Wenn Sie einen XML-Stub mit Ihrer Datenstruktur und Informationen darüber zur Verfügung stellen könnten, wie genau Sie ihn in eine Zeile einordnen möchten, wäre ich in der Lage, Sie genauer zu beraten. Nach Pixel.

Ich weiß, wie man eine benutzerdefinierte Zeile + einen benutzerdefinierten Array-Adapter erstellt, um eine benutzerdefinierte Zeile für die gesamte Listenansicht zu unterstützen. Aber wie kann eine Listenansicht viele verschiedene Zeilenstile unterstützen?

Du kennst schon die Grundlagen. Sie müssen nur Ihren benutzerdefinierten Adapter abrufen, um basierend auf den bereitgestellten Zeilen- / Cursorinformationen ein anderes Layout / eine andere Ansicht zurückzugeben.

Ein ListView kann mehrere ListView unterstützen, da es von AdapterView abgeleitet ist :

Ein AdapterView ist eine Ansicht, deren untergeordnete Elemente von einem Adapter bestimmt werden.

Wenn Sie sich den Adapter ansehen, sehen Sie Methoden, die die Verwendung von zeilenspezifischen Sichten berücksichtigen:

 abstract int getViewTypeCount() // Returns the number of types of Views that will be created ... abstract int getItemViewType(int position) // Get the type of View that will be created ... abstract View getView(int position, View convertView, ViewGroup parent) // Get a View that displays the data ... 

Die beiden letztgenannten Methoden stellen die Position bereit , anhand derer Sie den Ansichtstyp bestimmen können, den Sie für diese Zeile verwenden möchten .


Natürlich verwenden Sie AdapterView und Adapter im Allgemeinen nicht direkt, sondern verwenden oder leiten von einer ihrer Unterklassen ab. Die Unterklassen von Adapter können zusätzliche functionen hinzufügen, die ändern, wie benutzerdefinierte Layouts für verschiedene Zeilen abgerufen werden. Da die für eine bestimmte Zeile verwendete Ansicht vom Adapter gesteuert wird, besteht der Trick darin, dass der Adapter die gewünschte Ansicht für eine bestimmte Zeile zurückgibt. Wie dies zu tun ist, hängt vom jeweiligen Adapter ab.

Um beispielsweise ArrayAdapter zu verwenden,

  • überschreiben Sie getView() , um die gewünschte Ansicht für die angegebene Position aufzublasen, getView() und zurückzugeben. Die Methode getView() enthält eine Opportunity, bei der Ansichten über den Parameter convertView werden.

Aber um Derivate von CursorAdapter zu verwenden ,

  • Überschreiben Sie newView() , um die gewünschte Ansicht für den aktuellen Cursor-Status (dh die aktuelle “Zeile”) aufzublasen, newView() und zurückzugeben [Sie müssen bindView auch überschreiben, damit das Widget Ansichten wiederverwenden kann]

Um SimpleCursorAdapter zu verwenden,

  • Definieren Sie einen SimpleCursorAdapter.ViewBinder mit einer setViewValue() -Methode, um die gewünschte Ansicht für eine gegebene Zeile (aktueller Cursor-Status) und Daten “Spalte” aufzublasen, setViewValue() und zurückzugeben. Die Methode kann nur die “speziellen” Ansichten definieren und auf das Standardverhalten von SimpleCursorAdapter für die “normalen” Bindungen verzichten.

Schau dir die spezifischen Beispiele / Tutorials für die Art von Adapter an, die du verwendest.

Schauen Sie in den Code unten.

Zuerst erstellen wir benutzerdefinierte Layouts. In diesem Fall vier Arten.

gerade.xml

    

odd.xml

    

weiß.xml

    

schwarz.xml

    

Dann erstellen wir das Listenansichtselement. In unserem Fall mit einer Zeichenkette und einem Typ.

 public class ListViewItem { private String text; private int type; public ListViewItem(String text, int type) { this.text = text; this.type = type; } public String getText() { return text; } public void setText(String text) { this.text = text; } public int getType() { return type; } public void setType(int type) { this.type = type; } } 

Danach erstellen wir einen View Holder. Dies wird dringend empfohlen, da Android OS die Layoutreferenz beibehält, um das Element wieder zu verwenden, wenn es verschwindet und auf dem Bildschirm angezeigt wird. Wenn Sie diesen Ansatz nicht verwenden, erstellt Android OS jedes Mal, wenn Ihr Element auf dem Bildschirm angezeigt wird, ein neues und führt dazu, dass Ihre App Speicher verliert.

 public class ViewHolder { TextView text; public ViewHolder(TextView text) { this.text = text; } public TextView getText() { return text; } public void setText(TextView text) { this.text = text; } } 

Schließlich erstellen wir unseren benutzerdefinierten Adapter, der getViewTypeCount () und getItemViewType (int position) überschreibt.

 public class CustomAdapter extends ArrayAdapter { public static final int TYPE_ODD = 0; public static final int TYPE_EVEN = 1; public static final int TYPE_WHITE = 2; public static final int TYPE_BLACK = 3; private ListViewItem[] objects; @Override public int getViewTypeCount() { return 4; } @Override public int getItemViewType(int position) { return objects[position].getType(); } public CustomAdapter(Context context, int resource, ListViewItem[] objects) { super(context, resource, objects); this.objects = objects; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder = null; ListViewItem listViewItem = objects[position]; int listViewItemType = getItemViewType(position); if (convertView == null) { if (listViewItemType == TYPE_EVEN) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.type_even, null); } else if (listViewItemType == TYPE_ODD) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.type_odd, null); } else if (listViewItemType == TYPE_WHITE) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.type_white, null); } else { convertView = LayoutInflater.from(getContext()).inflate(R.layout.type_black, null); } TextView textView = (TextView) convertView.findViewById(R.id.text); viewHolder = new ViewHolder(textView); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.getText().setText(listViewItem.getText()); return convertView; } } 

Und unsere Aktivität ist in etwa so:

 private ListView listView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // here, you can create a single layout with a listview listView = (ListView) findViewById(R.id.listview); final ListViewItem[] items = new ListViewItem[40]; for (int i = 0; i < items.length; i++) { if (i == 4) { items[i] = new ListViewItem("White " + i, CustomAdapter.TYPE_WHITE); } else if (i == 9) { items[i] = new ListViewItem("Black " + i, CustomAdapter.TYPE_BLACK); } else if (i % 2 == 0) { items[i] = new ListViewItem("EVEN " + i, CustomAdapter.TYPE_EVEN); } else { items[i] = new ListViewItem("ODD " + i, CustomAdapter.TYPE_ODD); } } CustomAdapter customAdapter = new CustomAdapter(this, R.id.text, items); listView.setAdapter(customAdapter); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView adapterView, View view, int i, long l) { Toast.makeText(getBaseContext(), items[i].getText(), Toast.LENGTH_SHORT).show(); } }); } } 

Erstellen Sie nun eine Listenansicht in der Datei "mainactivity.xml"

 < ?xml version="1.0" encoding="utf-8"?>        

In Ihrem benutzerdefinierten Array-Adapter überschreiben Sie die Methode getView (), die Sie vermutlich kennen. Dann müssen Sie nur noch eine switch-statement oder eine if-statement verwenden, um abhängig vom position-Argument, das an die getView-Methode übergeben wird, eine bestimmte benutzerdefinierte Ansicht zurückzugeben. Android ist insofern clever, als es dir nur eine convertView des passenden Typs für deine Position / Zeile gibt; Sie müssen nicht überprüfen, ob es vom richtigen Typ ist. Sie können Android dabei helfen, indem Sie die Methoden getItemViewType () und getViewTypeCount () entsprechend überschreiben.

Wenn wir in der Listenansicht einen anderen Ansichtstyp anzeigen müssen, ist es empfehlenswert, getViewTypeCount () und getItemViewType () im Adapter zu verwenden, anstatt die Ansicht VIEW.GONE und VIEW.VISIBLE zu wechseln. Dies kann eine sehr teure Aufgabe innerhalb von getView () sein Auswirkungen auf die Liste blättern.

Bitte überprüfen Sie dieses für die Verwendung von getViewTypeCount () und getItemViewType () in Adapter.

Link: Der -Verwendungszweck

ListView war für einfache Anwendungsfälle wie die gleiche statische Ansicht für alle Zeilenelemente gedacht.
Da Sie ViewHolder erstellen und getItemViewType() und dynamisch verschiedene getItemViewType() Layout- getItemViewType() anzeigen müssen, sollten Sie dies mit dem RecyclerView tun, der in Android API 22 verfügbar ist. Er bietet eine bessere Unterstützung und Struktur für die Mehrfachansicht Arten.

In diesem Tutorial erfahren Sie, wie Sie mit RecyclerView das tun können, wonach Sie suchen.