Android ListView mit benutzerdefiniertem Adapter Beispiel Tutorial

Im diesem Tutorial verwenden wir einen CustomAdapter, der die benutzerdefinierten Zeilen der Android ListView mit einem ArrayList füllt. Um die Benutzererfahrung zu verbessern, animieren wir die ListView beim Scrollen.

Überblick über den benutzerdefinierten Android ListView Adapter

Der einfachste Adapter zum Befüllen einer Ansicht aus einem ArrayList ist der ArrayAdapter. Das werden wir in diesem Tutorial umsetzen. Es gibt auch andere Adapter, wie zum Beispiel den CursorAdapter, der sich direkt an ein Ergebnisset aus einer lokalen SQLite-Datenbank bindet und einen Cursor als Datenquelle verwendet.

Recycling von Zeilen

Wenn eine ListView instanziiert wird und die Zeilen so bevölkert werden, dass die volle Höhe der Liste gefüllt ist, werden keine neuen Zeilenobjekte im Speicher erstellt. Wenn der Benutzer durch die Liste scrollt, werden Elemente, die den Bildschirm verlassen, im Speicher für spätere Verwendung aufbewahrt. Jede neue Zeile, die in den Bildschirm kommt, verwendet dann eine ältere Zeile, die im Speicher aufbewahrt wurde.

Erstellen einer Ansichtsvorlage

Erstellen wir ein XML-Layout, das die Elemente in einer Zeile auf individuelle Weise darstellt. row_item.xml

<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="10dp">

    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:text="Marshmallow"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:textColor="@android:color/black" />


    <TextView
        android:id="@+id/type"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/name"
        android:layout_marginTop="5dp"
        android:text="Android 6.0"
        android:textColor="@android:color/black" />

    <ImageView
        android:id="@+id/item_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:src="@android:drawable/ic_dialog_info" />


    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true">

        <TextView
            android:id="@+id/version_heading"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="API: "
            android:textColor="@android:color/black"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/version_number"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="23"
            android:textAppearance="?android:attr/textAppearanceButton"
            android:textColor="@android:color/black"
            android:textStyle="bold" />

    </LinearLayout>

</RelativeLayout>

In diesem Tutorial werden wir eine Anwendung erstellen, die eine Liste von Zeilen mit Textbeschreibungen und einem Infosymbol enthält. Durch Klicken auf die Zeile wird die Snackbar mit den Textelementen dieser Zeile angezeigt. Durch Klicken auf die Info wird eine Snackbar mit Informationen spezifisch für diese Zeile angezeigt.

Projektstruktur

Code

Wir erstellen eine benutzerdefinierte ListView, indem wir ArrayAdapter mit dem DataModel als Objekt unterklasse. getView() ist die Methode, die die tatsächliche Ansicht zurückgibt, die als Zeile innerhalb der ListView an einer bestimmten Position verwendet wird. Die content_main.xml enthält die ListView wie unten dargestellt. content_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    tools:context="com.journaldev.customlistview.MainActivity"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/activity_main">

    <ListView
        android:id="@+id/list"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

</RelativeLayout>

Das Datenmodell, das in der ArrayList enthalten ist, wird unten angezeigt. DataModel.java

public class DataModel {

    String name;
    String type;
    String version_number;
    String feature;

    public DataModel(String name, String type, String version_number, String feature ) {
        this.name=name;
        this.type=type;
        this.version_number=version_number;
        this.feature=feature;

    }

    public String getName() {
        return name;
    }
    
    public String getType() {
        return type;
    }
    
    public String getVersion_number() {
        return version_number;
    }
    
    public String getFeature() {
        return feature;
    }
    
}

Der CustomAdapter, der das DataModel in die ListView einfügt, wird unten gezeigt. CustomAdapter.java

public class CustomAdapter extends ArrayAdapter implements View.OnClickListener{

    private ArrayList dataSet;
    Context mContext;

    // Ansichtscache suchen
    private static class ViewHolder {
        TextView txtName;
        TextView txtType;
        TextView txtVersion;
        ImageView info;
    }

    public CustomAdapter(ArrayList data, Context context) {
        super(context, R.layout.row_item, data);
        this.dataSet = data;
        this.mContext=context;

    }

    @Override
    public void onClick(View v) {

        int position=(Integer) v.getTag();
        Object object= getItem(position);
        DataModel dataModel=(DataModel)object;

        switch (v.getId())
        {
            case R.id.item_info:
                Snackbar.make(v, "Release date " +dataModel.getFeature(), Snackbar.LENGTH_LONG)
                        .setAction("No action", null).show();
                break;
        }
    }

    private int lastPosition = -1;

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // Datenobjekt für diese Position abrufen
        DataModel dataModel = getItem(position);
        // Überprüfen, ob eine vorhandene Ansicht wiederverwendet wird, sonst Ansicht aufblasen
        ViewHolder viewHolder; // view lookup cache stored in tag

        final View result;

        if (convertView == null) {

            viewHolder = new ViewHolder();
            LayoutInflater inflater = LayoutInflater.from(getContext());
            convertView = inflater.inflate(R.layout.row_item, parent, false);
            viewHolder.txtName = (TextView) convertView.findViewById(R.id.name);
            viewHolder.txtType = (TextView) convertView.findViewById(R.id.type);
            viewHolder.txtVersion = (TextView) convertView.findViewById(R.id.version_number);
            viewHolder.info = (ImageView) convertView.findViewById(R.id.item_info);

            result=convertView;

            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
            result=convertView;
        }

        Animation animation = AnimationUtils.loadAnimation(mContext, (position > lastPosition) ? R.anim.up_from_bottom : R.anim.down_from_top);
        result.startAnimation(animation);
        lastPosition = position;

        viewHolder.txtName.setText(dataModel.getName());
        viewHolder.txtType.setText(dataModel.getType());
        viewHolder.txtVersion.setText(dataModel.getVersion_number());
        viewHolder.info.setOnClickListener(this);
        viewHolder.info.setTag(position);
        // Die fertige Ansicht zurückgeben, um auf dem Bildschirm gerendert zu werden
        return convertView;
    }
}

Im obigen Code haben wir einen onClickListener zum ImageView hinzugefügt, der beim Klicken eine SnackBar mit einer Beschreibung für die jeweilige Zeile anzeigt. Außerdem werden die Listenzeilen beim Scrollen animiert. Die beiden Animations-XML-Ressourcendateien sind unten aufgeführt. down_from_top.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="https://schemas.android.com/apk/res/android"
    android:shareInterpolator="@android:anim/decelerate_interpolator">
    <translate
        android:fromXDelta="0%" android:toXDelta="0%"
        android:fromYDelta="-100%" android:toYDelta="0%"
        android:duration="400" />
</set>

up_from_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="https://schemas.android.com/apk/res/android"
    android:shareInterpolator="@android:anim/decelerate_interpolator">
    <translate
        android:fromXDelta="0%" android:toXDelta="0%"
        android:fromYDelta="100%" android:toYDelta="0%"
        android:duration="400" />
</set>

Die MainActivity.java, in der der CustomAdapter der ListView zugewiesen ist, ist unten definiert. Zusammen damit wird ein zufälliges ArrayList von DataModel-Objekten bevölkert. MainActivity.java

public class MainActivity extends AppCompatActivity {

    ArrayList dataModels;
    ListView listView;
    private static CustomAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        listView=(ListView)findViewById(R.id.list);

        dataModels= new ArrayList<>();

        dataModels.add(new DataModel("Apple Pie", "Android 1.0", "1","September 23, 2008"));
        dataModels.add(new DataModel("Banana Bread", "Android 1.1", "2","February 9, 2009"));
        dataModels.add(new DataModel("Cupcake", "Android 1.5", "3","April 27, 2009"));
        dataModels.add(new DataModel("Donut","Android 1.6","4","September 15, 2009"));
        dataModels.add(new DataModel("Eclair", "Android 2.0", "5","October 26, 2009"));
        dataModels.add(new DataModel("Froyo", "Android 2.2", "8","May 20, 2010"));
        dataModels.add(new DataModel("Gingerbread", "Android 2.3", "9","December 6, 2010"));
        dataModels.add(new DataModel("Honeycomb","Android 3.0","11","February 22, 2011"));
        dataModels.add(new DataModel("Ice Cream Sandwich", "Android 4.0", "14","October 18, 2011"));
        dataModels.add(new DataModel("Jelly Bean", "Android 4.2", "16","July 9, 2012"));
        dataModels.add(new DataModel("Kitkat", "Android 4.4", "19","October 31, 2013"));
        dataModels.add(new DataModel("Lollipop","Android 5.0","21","November 12, 2014"));
        dataModels.add(new DataModel("Marshmallow", "Android 6.0", "23","October 5, 2015"));

        adapter= new CustomAdapter(dataModels,getApplicationContext());

        listView.setAdapter(adapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView parent, View view, int position, long id) {

                DataModel dataModel= dataModels.get(position);

                Snackbar.make(view, dataModel.getName()+"\n"+dataModel.getType()+" API: "+dataModel.getVersion_number(), Snackbar.LENGTH_LONG)
                        .setAction("No action", null).show();
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Das Menü aufblasen; Dadurch werden Elemente zur Aktionsleiste hinzugefügt, falls vorhanden.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Behandle Klicks auf Elemente der Aktionsleiste hier. Die Aktionsleiste wird
        // automatisch Klicks auf die Home-/Up-Schaltfläche behandeln, solange
        // du eine übergeordnete Aktivität in der AndroidManifest.xml angibst.
        int id = item.getItemId();

        //noinspection VereinfachbareAnweisung
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

Die Ausgabe der Anwendung in Aktion wird unten angezeigt. Damit endet dieses Tutorial. Sie können das endgültige Android ListView Custom Adapter-Projekt über den folgenden Link herunterladen.

Android ListView Custom Adapter-Projekt herunterladen

Referenz: API-Leitfaden List View

Source:
https://www.digitalocean.com/community/tutorials/android-listview-with-custom-adapter-example-tutorial