Anpassung ListView ist bei der Entwicklung von Anwendungen für Android OS üblich. ListView (List) ermöglicht es Ihnen, die gleiche Art von Informationen in Ihrer Anwendung anzuzeigen, z. B. die Produkte mit Preisen und Funktionen anzuzeigen, wenn Sie Anwendungen für den Online-Verkauf entwickeln. Da es sich jedoch tatsächlich um eine Routineoperation handelt, bringen einige Fragen für unerfahrene Entwickler eine Menge Unannehmlichkeiten mit sich. Einige dieser Unannehmlichkeiten und Fragen werden in diesem Artikel erörtert.
Projektstruktur
In dieser Lektion wird vorgeschlagen, eine kleine Liste mit den Flaggen der Länder, die als Währungen dieser Länder bezeichnet werden, und der Abkürzung des Landes zu erstellen.
Total wird verwendet, um eine Liste von vier Ländern zu erstellen: Russland, Südafrika, Singapur, Türkei. Flaggen dieser Länder befinden sich in der Ziehmappe. Außerdem gibt es eine XML-Datei zum Erstellen von Hintergrund-ListViewi-Flags. Zum Speichern von Namen und Abkürzungen verwendete Datei strings.xml. Außerdem eine separate XML-Datei zum Erstellen des ListView-Layouts.
Im Projekt gibt es drei Klassen:
- Hauptaktivität
- MyListAdapter - der für die Übertragung von Daten in Form eines Listeneintrags zuständig ist
- DataFlags - Klasse, die entwickelt wurde, um die Übertragung von Daten an den Adapter ListView zu erleichtern
Die Gestaltung des Layouts der ListView
Um in dieser Lektion eine gut aussehende Liste zu erstellen, verwenden Sie die folgenden Dateien:
- list_item.xml
- flag.xml
- listview_selector.xml
- style.xml
listview.xml
Diese Datei ist ein Markup-Element direkt in der Listenansicht.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="48dp" android:background="@drawable/listview_selector" android:orientation="horizontal"> <ImageView android:id="@+id/flagImage" android:src="@drawable/flag_russian" android:layout_width="48dp" android:layout_height="40dp" android:layout_marginStart="16dp" android:layout_marginLeft="16dp" android:layout_marginRight="8dp" android:layout_marginEnd="8dp" android:contentDescription="@string/flag" android:background="@drawable/flag" android:layout_gravity="center_vertical"/> <TextView android:id="@+id/abbreviation" android:layout_width="52dp" android:layout_height="30dp" android:textColor="@color/black" android:textSize="24sp" android:text="@string/russianRUB" android:layout_marginRight="6dp" android:layout_marginEnd="6dp" android:layout_gravity="center_vertical"/> <TextView android:id="@+id/name" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/black" android:textSize="14sp" android:text="@string/russian" android:gravity="center" android:layout_gravity="center" android:singleLine="false"/> </LinearLayout>
flag.xml
Diese Datei wird für den Hintergrund ImageView erstellt, der die Flagge anzeigt. Die Kanten des Substrats sind zur Fahne abgerundet. Und stellen Sie auch die Farbe des Substrats ein.
<?xml version="1.0" encoding="UTF-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="@color/blue_grey_100" /> <padding android:bottom="2dp" android:top="2dp" android:right="2dp" android:left="2dp"/> <corners android:radius="4dp"/> </shape>
listview_selector.xml
Diese Markierung wird als Hintergrund für die ListView verwendet. Diese Datei ist eine anpassbare Hintergrundfarbe des Elements im normalen Modus und wenn Sie auf ein Listenelement klicken.
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="false" android:state_pressed="false" android:drawable="@color/white" /> <item android:state_pressed="true" android:drawable="@color/blue_grey_100" /> <item android:state_selected="true" android:state_pressed="false" android:drawable="@color/blue_grey_100" /> </selector>
styles.xml
Dateistile, die jedem bekannt sind, der für Android entwickelt hat. In diesem Fall wird es nur zum Speichern von in diesem Beispiel verwendeten Farbcodes verwendet.
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> </style> <color name="white">#ffffff</color> <color name="black">#000000</color> <color name="blue_grey_100">#CFD8DC</color> </resources>
activity_main.xml
Layout der Hauptaktivität, um unsere benutzerdefinierte Listenansicht zu beherbergen
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/white" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <ListView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/listViews" /> </RelativeLayout>
Die Hauptprojektklasse - MainActivity.java
In dieser Klasse wird ein grundlegendes Activiti-Projekt gestartet, das eine benutzerdefinierte ListView anzeigt. Daten in ListView übertragen per ArrayList Liste, in der die Objekte für jedes Datenelement markiert sind. Die Gruppierung von Daten für die ListView wird von einer separaten Klasse erzeugt, die eine Datenstruktur bildet, in der eine Flaggenbild-ID, ID-Namen, die die Währung des Landes sowie die ID-Kette von Abkürzungen für die Währungen säumen, gespeichert werden.
Tatsächlich in dieser Klasse zur Standardeinstellung gemachte ListView, mit dem Unterschied, dass keine herkömmliche List verwendet wird, und eine ArrayList, die einem Objekt übergeben wird, und nicht einer einzelnen Zeile.
package ru.evileg.listview; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.Menu; import android.view.MenuItem; import android.widget.ListView; import java.util.ArrayList; public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Find the ListView in the markup Activiti ListView listView = (ListView) this.findViewById(R.id.listViews); // Create a ListView, in which the data for the list will be stored ArrayList<DataFlags> list = new ArrayList<>(); list.clear(); /* We fill List data. In this case, the data is transferred to the object that holds the id, * the flags indicating the resource, as well as strings, * which are registered names and abbreviations for the currencies of these currencies */ list.add(new DataFlags(R.drawable.flag_russian, R.string.russian, R.string.russianRUB)); list.add(new DataFlags(R.drawable.flag_africa, R.string.africa, R.string.africaZAR)); list.add(new DataFlags(R.drawable.flag_singapore, R.string.singapore, R.string.singaporeSGD)); list.add(new DataFlags(R.drawable.flag_turkish, R.string.turkish, R.string.turkishTRY)); /* Create an adapter that will transfer data from the List item in the ListView and connect it directly to ListView`u */ MyListAdapter myListAdaptery = new MyListAdapter(this, list); listView.setAdapter(myListAdaptery); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
Alle Zeilen, die für das ListView verwendet werden, werden direkt in der Ressourcendatei strings.xml gespeichert
<resources> <string name="app_name">ListView</string> <string name="action_settings">Settings</string> <string name="africaZAR">ZAR</string> <string name="russianRUB">RUB</string> <string name="singaporeSGD">SGD</string> <string name="turkishTRY">TRY</string> <string name="africa">South African\nrand</string> <string name="russian">Russian\nrouble</string> <string name="singapore">Singapore\ndollar</string> <string name="turkish">Turkish\nlira</string> <string name="flag">flag</string> </resources>
DataFlags.java
Diese Klasse wird zur Bildung des Objekts verwendet, in dem Daten für ListView-Elemente gespeichert werden. Jedes Objekt bedient eines der ListView-Elemente im Projekt. Eine Klasse ist eine gemeinsame Variable und eine Reihe von Get-Methoden zum Abrufen von Daten aus dem von dieser Klasse generierten Objekt.
package ru.evileg.listview; /** * Application ListView * Created by EvILeg on 21.07.2015. */ public class DataFlags { private int flagID; private int nameID; private int abbreviationID; public DataFlags (int _flagID, int _nameID, int _abbreviationID){ flagID = _flagID; nameID = _nameID; abbreviationID = _abbreviationID; } public int getFlagID(){ return flagID; } public int getNameID(){ return nameID; } public int getAbbreviationID() { return abbreviationID; } }
MyListAdapter-Klasse
Die wichtigste Klasse in dieser Lektion. Diese Klasse wird verwendet, um Daten von ArrayList an die ListView zu übertragen. Diese Klasse erweitert die übergeordnete Klasse BaseAdapter.
package ru.evileg.listview; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import java.util.ArrayList; /** * Application ListView * Created by EvILeg on 21.07.2015. */ public class MyListAdapter extends BaseAdapter { /* * Create objects for the display appearance element and a list of object that will be work */ private LayoutInflater LInflater; private ArrayList<DataFlags> list; /* * The class constructor. In this case, a broadcast data sheet in the adapter list, * which will be direct work */ public MyListAdapter(Context context, ArrayList<DataFlags> data){ list = data; LInflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); } /* * Next come the standard methods of the parent class BaseAdapter. * Please read carefully the differences in the methods and classroom techniques that automatically creates Android Studio. * These methods should be used to work directly with us and ArrayList data structure formed by class DataFlags */ @Override public int getCount() { return list.size(); } @Override public DataFlags getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } /* * The method in which the appearance of elements is formed with its filling */ @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; View v = convertView; /* * In that case, if the form element is not created, * produced with the help of its creation ViewHolder and tagging of a particular element holder object */ if ( v == null){ holder = new ViewHolder(); v = LInflater.inflate(R.layout.list_item, parent, false); holder.flag = (ImageView) v.findViewById(R.id.flagImage); holder.name = (TextView) v.findViewById(R.id.name); holder.abbreviation = ((TextView) v.findViewById(R.id.abbreviation)); v.setTag(holder); } /* * Once all elements are defined, the correlation is performed appearance data and the specific position in ListView. * After that, the ArrayList data are collected for the ListView element and transmitted to the exterior element */ holder = (ViewHolder) v.getTag(); DataFlags dataFlags = getData(position); holder.flag.setImageResource(dataFlags.getFlagID()); holder.name.setText(v.getResources().getString(dataFlags.getNameID())); holder.abbreviation.setText(v.getResources().getString(dataFlags.getAbbreviationID())); return v; } /* * A method that takes an object of the ArrayList to further work with him and transmit its data in a ListView item */ DataFlags getData(int position){ return (getItem(position)); } /* * This data structure is needed to ensure that when scrolling through a large list of artifacts and do not arise from skipping data ListView one position to another, * that is achieved by tagging each element ListView */ private static class ViewHolder { private ImageView flag; private TextView name; private TextView abbreviation; } }
Die Verwendung von ViewHolder ist von entscheidender Bedeutung, da Sie, wenn Sie diese Technik nicht verwenden, ein unangemessenes ListView-Verhalten erhalten können, das auftritt, wenn unkontrollierte Daten von einer ListView zu einer anderen Position springen. Und dies wird nur scheinbar geschehen, aber tatsächlich werden die Daten an ihrem Platz bleiben. Es gibt eine Diskrepanz zwischen dem Erscheinungsbild der ListView und ihrem Inhalt.
Ergebnis
Wenn beim Lernen der Lektion keine Probleme und Fehler aufgetreten sind, sollte das Erscheinungsbild der resultierenden ListView etwa wie folgt aussehen:
Benutzerdefinierte Listenansicht
Benutzerdefinierte ListView mit gedrücktem Element
Спасибо за пример.
У меня возникает ошибка.
AndroidRuntime: FATAL EXCEPTION: main
Подскажите, пожалуйста, с чем это может быть связано?
Честно, вот в этой ошибке может быть что угодно, вплоть до того, что вы просто где-то не в том порядке код запсали.
Это просто ошибка в рантайме, для всего, что могло случиться.